프로젝트를 진행하다 보니, 폴더 구조가 비효율적이라는 생각이 들었습니다. 점점 많은 파일과 폴더를 생성하다보니 찾고자 하는 파일 혹은 연관된 코드의 위치를 바로바로 못찾는 상황이었습니다. 이에 따라 2차 애자일을 시작하면서 아예 셋팅을 다시 하고 개발에 들어가기로 팀원분과 협의를 하게 되었습니다.
우선, FSD 구조에 대해서 살펴보기 전에, 먼저 프론트엔드에서의 폴더 구조가 어떻게 변화해 왔고 왜 변화해왔는지를 예제와 함께 자세하게 설명하고 있는 `Teo`님의 양질의 글을 읽었습니다. FSD가 나오게 된 배경을 이해하는데에 매우 도움이 되었습니다.
FSD란?
FSD는 Feature Slice Desingn의 줄임말로 애플리케이션의 기능과 목적에 따라 파일을 분류하는 방법입니다. FSD 구조를 사용하면 모듈화, 가독성, 재사용성을 향상시킬 수 있습니다.
언제 적용하나?
운영기간이 짧거나 작은 규모의 프로젝트라면 적용할 필요가 없지만, 점진적으로 소프트웨어 규모가 커질 예정이라면 적절한 방식입니다.
FSD 구성 요소
FSD는 layers, slices, segment 총 3단계의 계층 구조를 갖습니다.

Layers
FSD의 각 레이어는 특정한 책임을 가지고 있으며, 각 레이어는 하위 레이어만 참조할 수 있습니다. 즉 하위 레벨을 의존성으로 가질 수 있습니다. 그러나 그 반대는 성립되지 않습니다!
하위 레이어로 갈수록 추상화가 심화되며, 상위 레이어로 갈 수록 비즈니스 로직이 심화됩니다.
따라서 계층 구조에서 레이어의 위치가 낮을수록(shared로 갈 수록) 더 많은 곳에서 사용될 가능성이 높겠죠!

app
app은 애플리케이션 로직이 초기화되는 곳입니다. 최상위 프로바이더, 라우팅, 전역 스타일, 전역 타입 선언 등 전역적인 설정이 정의됩니다. 애플리케이션의 진입점 역할을 한다고 생각하면 됩니다.
pages
pages는 하위 레이어들을 조합하여 완전한 기능을 하는 애플리케이션의 페이지를 작성하는 곳입니다. 특정 URL에 매핑되는 모든 페이지들이 포함됩니다.
widget
widget은 페이지 내에서 사용되는 독립적인 UI 컴포넌트를 말합니다.
features
features는 재사용이 가능한 비즈니스 기능을 위한 레이어로
독립적으로 동작할 수 있는 하나의 특정 동작을 정의
하는 곳입니다. features 레이어에 작성된 코드는 다양한 페이지와 위젯에서 재사용될 수 있는 추상화된 로직입니다.
ex) 팔로우/팔로워, 리뷰 작성, 제품 평가 등이 있습니다.
entities
entities는 프로젝트에서 다루는 비즈니스의 핵심 데이터(엔티티)를 정의하는 레이어입니다. 이 레이어에는 주로 데이터 모델과 해당 데이터에 대한 로직이 포함됩니다.
ex) 사용자, 리뷰, 댓글 등이 포함될 수 있습니다.
shared
shared는 특정 비즈니스 로직에 종속되지 않은 프로젝트 전반에서 재사용 가능한 컴포넌트와 유틸리티가 정의되는 레이어입니다. shared 레이어는 슬라이스가 존재하지 않는데, 도메인에 상관없이 전역적으로 재사용이 가능한 요소들만 모아두는 레이어이기 때문입니다.
ex) UI 키트, axios 설정, 애플리케이션 설정, 비즈니스 로직에 묶이지 않은 헬퍼 등이 포함됩니다.
slices
[FSD 공식문서 - 슬라이스](https://feature-sliced.design/docs/reference/slices-segments#slices)
app과 shared 레이어에는 슬라이스가 없습니다!
slices는 FSD의 두 번째 계층으로, 제품, 비즈니스, 애플리케이션에서의 의미에 따라 관련된 코드를 그룹화함으로써 유지보수와 관리를 용이하게 하는 것이 목적입니다. 슬라이스는 일반적인 기능이 아닌 특정 비즈니스 엔티티를 기준으로 코드를 묶습니다.
네이밍 규칙
슬라이스 네이밍 규칙은 없습니다. 비즈니스 도메인에 따라 슬라이스의 이름이 결정됩니다.
ex) SNS 앱을 만드는 경우 post, user와 같은 슬라이스를 만들 수 있고, 사진 갤러리의 경우 photo, album등의 슬라이스가 있을 수 있습니다.
Import rule
각각의 슬라이스들은 디렉토리 내에서 그룹화 할수는 있지만, 독립적이고 응집력이 높은 코드 파일 그룹이기 때문에 같은 레이어 내 다른 슬라이스끼리는 참조할 수 없습니다.
ex) /features/aaa 슬라이스 내부에 있는 features/aaa/api/request.ts파일은 /features/bbb에 존재하는 모든 파일을 import 할 수 없습니다.
그러나 features/aaa에 존재하는 sibling 코드에는 접근할 수 있으며 entity, shared와 같은 features 레이어의 하위 레이어의 파일들은 import할 수 있습니다.
Public API rule
Every slice (and segment on layers that don't have slices) must contain a public API definition.
공식문서에서는 slice와 app과 shared의 segment 폴더 내부에는 Public API가 정의되어 있어야 한다고 말하고 있습니다. public API는 각 모듈 외부에서 import해서 사용할 수 있는 것들을 명확하게 선언하는 역할을 합니다.
└── features/ #
├── auth-form / # Internal structure of the feature
| ├── ui/ #
| ├── model/ #
| ├── index.ts # Public API
├── index.ts # Entrypoint features with its public API
Segments
Slices안에는 Segments라는 세 번째(마지막) 계층이 존재합니다. 세그먼트는 기술적인 특성에 따라 그룹화하는 것이 목적입니다. 세그먼트의 이름 규칙까지는 없지만, 일반적으로 많이 사용하는 이름이 있습니다.
ui— UI와 관련된 모든 것 (components, 날짜 포맷터, 스타일 등)api— 백엔드 상호작용과 관련있는 모든 것 (request functions, request/response 관련 데이터 타입,mappers등)model— 데이터 모델 (스키마, 인터페이스,stores, business logic관련 타입들)lib— library code that other modules on this slice need.config— 구성 파일과 기능 플래그
참고한 글
기능 분할 설계 - 최고의 프론트엔드 아키텍쳐
FSD 아키텍처 알아보기
FSD 완벽 가이드