FSD의 기본 규칙은 상위 레이어가 “같은 레벨 또는 아래 레이어”에 의존할 수 있다는 것(역참조 금지)입니다.
widgets (큰 블록 조립)features (페이지가 단촐할 때), entities의 타입/단순 뷰(지양), shared UIfeatures 묶기 + 일부 entities 뷰/상태shared (공통 UI/유틸)entities(도메인 상태/쿼리) 사용하여 “사용자 가치 있는 기능(검색/편집/폼)” 완성sharedshared (유틸/공통 API 클라이언트)요점: 가능(Allowed) 과 권장(Preferred) 을 구분하세요.
- 가능: 상위 → 어떤 하위든 import.
- 권장: 가까운 레이어를 먼저 조합(pages → widgets 중심), 필요할 때만 더 아래로 “직통”.
index.ts(Public API)만 사용하세요.import { useAccount } from '@/entities/account'; ✅import { useAccount } from '@/entities/account/api/queries'; ⛔ (내부 경로 직행 금지)이유
1. 경계 유지: 내부 구현 교체 자유
2. 번들 최소화: 공개된 심볼만 노출
3. 리뷰/린트 자동화: 규칙화 쉬움
레이어 계층: app → pages → widgets → features → entities → shared
src/
├─ app/ # 앱 엔트리/프로바이더/라우팅
├─ pages/
│ ├─ main/ # 페이지는 합성만! (비즈니스 로직 없음)
│ │ └─ index.tsx # widgets/features를 조립
│ └─ sub-main/
├─ widgets/
│ └─ main-dashboard/ # 대형 UI 블록(여러 features를 묶어 페이지에 올림)
│ ├─ ui/
│ ├─ model/
│ ├─ lib/
│ ├─ api/
│ └─ index.ts # <- Public API
├─ features/
│ ├─ search-projects/ => Slices(Domain)
│ │ ├─ ui/ => Segments(역활)
│ │ ├─ model/ => Segments(역활) # (Zustand store/selectors)
│ │ ├─ api/ => Segments(역활) # (TanStack Query v5 hooks)
│ │ ├─ lib/ => Segments(역활)
│ │ └─ index.ts
│ └─ edit-project/ => Slices(Domain)
├─ entities/
│ ├─ project/
│ │ ├─ ui/
│ │ ├─ model/ # (도메인 상태/타입, 정적 셀렉터)
│ │ ├─ api/ # (도메인 단위 fetchers)
│ │ ├─ types/
│ │ └─ index.ts
│ └─ user/
├─ shared/
│ ├─ ui/ # Button/Modal 등 순수 재사용 UI
│ │ ├─ button/
│ │ ├─ modal/
│ │ └─ index.ts
│ ├─ lib/ # 유틸, 포맷터, hooks(도메인 무관)
│ ├─ api/ # 공통 fetcher, 클라이언트
│ └─ config/
FSD는 한마디로 아래와 같다.
