Post

기능 분할 설계 (Feature-Sliced Design, FSD)

대규모 프론트엔드 애플리케이션을 구조화하기 위한 현대적인 아키텍처 방법론인 FSD를 소개합니다.

기능 분할 설계 (Feature-Sliced Design, FSD)

기능 분할 설계(Feature-Sliced Design, FSD)는 대규모 프론트엔드 애플리케이션을 구조화하기 위한 아키텍처 방법론입니다. 애플리케이션을 기능 단위로 분할하고, 각 기능을 독립적으로 개발, 테스트, 유지보수할 수 있도록 해요.


FSD의 핵심 원칙

  • 기능 중심 설계: 애플리케이션을 비즈니스 기능 단위로 구성
  • 계층화: 코드를 여러 계층으로 구분하여 관심사 분리
  • 단방향 의존성: 상위 계층은 하위 계층에만 의존
  • 명시적 공개 인터페이스: 각 모듈은 명확한 공개 API를 통해 상호작용
  • 구성 가능성: 작은 단위의 기능을 조합하여 더 큰 기능 구성

레이어 (Layers)

FSD 구조 개요 FSD의 전체 구조

레이어 구조 FSD 레이어 계층 구조

레이어 역할 예시
app 애플리케이션 초기화 및 글로벌 설정 라우팅, 전역 상태, 전역 스타일
processes 복잡한 비즈니스 프로세스 관리 (선택적) 다단계 체크아웃, 온보딩
pages 라우팅 가능한 화면 정의 홈페이지, 상품 페이지
widgets 재사용 가능한 UI 블록 헤더, 사이드바, 상품 목록
features 사용자 시나리오와 비즈니스 로직 로그인, 장바구니 추가
entities 도메인 객체와 관련 로직 사용자, 상품
shared 공유 유틸리티 및 UI 키트 버튼, API 클라이언트, 설정

레이어 의존성 각 레이어는 하위 레이어에만 의존 가능

각 레이어는 하위 레이어에만 의존할 수 있어, 단방향 데이터 흐름을 보장해요.


슬라이스 (Slices)

슬라이스는 각 레이어 내에서 특정 기능 영역이나 도메인을 나타내는 하위 디렉토리예요. 특정 비즈니스 도메인이나 기능을 캡슐화하고, 독립적으로 개발 및 테스트할 수 있습니다.

1
2
3
4
5
6
7
8
src/
  features/
    auth/              // 인증 관련 슬라이스
    product-catalog/   // 상품 목록 관련 슬라이스
    shopping-cart/     // 장바구니 관련 슬라이스
  entities/
    user/             // 사용자 엔티티 슬라이스
    product/          // 상품 엔티티 슬라이스

세그먼트 (Segments)

세그먼트는 슬라이스 내부의 코드를 목적에 따라 더 세분화한 것입니다.

세그먼트 역할
ui UI 컴포넌트
model 비즈니스 로직 (상태 관리, 액션, 셀렉터)
api 외부 서비스와의 통신
lib 유틸리티 함수
config 설정 및 상수
1
2
3
4
5
6
7
8
9
10
features/
  auth/
    ui/
      LoginForm.tsx
      RegisterForm.tsx
    model/
      authSlice.ts
      authSelectors.ts
    api/
      authApi.ts

Public API

각 슬라이스나 세그먼트의 루트에 index.ts 파일을 생성하고, 외부에서 사용할 항목만 명시적으로 export합니다.

1
2
3
4
5
// features/auth/index.ts
export { LoginForm } from './ui/LoginForm';
export { RegisterForm } from './ui/RegisterForm';
export { login, logout } from './model/authSlice';
export { selectUser } from './model/authSelectors';

Public API를 통해 내부 구현을 숨기면, 리팩토링 시 외부에 영향을 주지 않고 내부 구조를 변경할 수 있어요.


프로젝트 구조 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
src/
  app/
    index.tsx
    store.ts
    routes.ts
  pages/
    HomePage/
    ProductPage/
  widgets/
    Header/
    Footer/
  features/
    auth/
    product-search/
  entities/
    user/
    product/
  shared/
    ui/
    lib/

페이지는 위젯과 기능을 조합하여 구성해요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// pages/HomePage/index.tsx
import { Header } from 'widgets/Header';
import { ProductList } from 'widgets/ProductList';
import { ProductSearch } from 'features/product-search';

export const HomePage = () => (
  <>
    <Header />
    <main>
      <ProductSearch />
      <ProductList />
    </main>
  </>
);

장점

  • 모듈성: 기능 단위로 코드를 구성하여 재사용성과 유지보수성 향상
  • 확장성: 새로운 기능 추가나 기존 기능 수정이 용이
  • 테스트 용이성: 각 슬라이스와 세그먼트를 독립적으로 테스트 가능
  • 팀 협업: 기능 단위로 작업을 분배하여 병렬 개발 가능
  • 코드 네비게이션: 일관된 구조로 코드 탐색이 쉬움

적용 시 고려 사항

학습 곡선 팀 전체가 FSD 개념을 이해하고 동의해야 합니다.

오버엔지니어링 주의 작은 프로젝트에서는 복잡도가 증가할 수 있습니다. 프로젝트 규모가 중대형 이상이고, 팀 크기가 3명 이상이며, 장기 유지보수가 예상될 때 적합합니다.

일관성 유지 프로젝트 전반에 걸쳐 FSD 규칙을 일관되게 적용해야 합니다.

리팩토링 비용 기존 프로젝트를 FSD로 전환하는 데 상당한 노력이 필요할 수 있습니다. 전체를 한 번에 변경하기보다는, 새로운 기능부터 FSD를 적용하고 점진적으로 확대하는 것을 권장합니다.


참고 자료

This post is licensed under CC BY 4.0 by the author.