Feature-Sliced Design이 무엇인지 설명합니다 — 기술적 계층이 아닌 비즈니스 기능별로 프로젝트를 분할하는 데 기반한 프론트엔드 모듈식 아키텍처 방법론입니다. 기존의 계층형 아키텍처(컨트롤러, 서비스, 리포지토리)와 달리 FSD는 애플리케이션의 기능적 능력별로 코드를 그룹화합니다. 각 기능에는 자체 로직, UI 및 데이터가 포함됩니다. State of Frontend 2024 설문조사에 따르면 React 개발자의 23%가 기본 아키텍처 방법론으로 FSD를 사용하며, 이는 순수 Feature-based 구조 다음으로 두 번째로 인기 있습니다.
주요 포인트
Feature-Sliced Design (FSD)는 2021년 feature-sliced.design 커뮤니티에서 처음 제안한 프론트엔드 애플리케이션 아키텍처 방법론입니다. FSD의 핵심 아이디어는 코드를 비즈니스 기능(슬라이스)별로 그룹화하는 것이며, 각 슬라이스는 자체 비즈니스 로직, 사용자 인터페이스, API 상호작용, 데이터 모델 및 테스트를 포함하는 자급자족 단위입니다. 이는 코드가 기술적 기준(controller, service, repository)으로 분할되는 기존의 계층형 아키텍처와 FSD를 구별합니다.
이 방법론은 Domain-Driven Design(DDD) 및 Bounded Context의 개념을 차용합니다. 애플리케이션의 각 기능은 명확한 경계를 가진 별도의 bounded context입니다. 슬라이스의 공개 API만 사용하는 경우 한 기능 내의 변경 사항이 다른 기능을 손상시켜서는 안 됩니다. State of Frontend 2024 설문조사에 따르면 FSD는 React 아키텍처 중 인기도에서 2위(23%)를 차지하며, 비공식적인 Feature-based 구조(31%)에 이어 두 번째입니다.
모바일 개발에서 FSD는 Android 모듈 및 iOS 프레임워크의 특성에 적응합니다. IT Sectr에서는 10개 이상의 화면과 3개 이상의 팀이 있는 프로젝트에 FSD를 사용합니다. 이 방법론은 독립적인 기능 개발을 가능하게 하며 슬라이스 경계가 없는 모노레포에 비해 git 충돌을 40% 줄입니다.
FSD는 7개의 계층 구조를 정의하며, 각 계층에는 특정 추상화 수준의 코드가 포함됩니다. 주요 아키텍처 규칙은 계층은 하위 계층에서만 코드를 가져올 수 있다는 것입니다. 이 규칙을 위반하면(entities에 features 계층 가져오기) 아키텍처 오류로 간주되며 린터에 의해 차단됩니다.
| 계층 | 목적 | 가져오기 |
|---|---|---|
| app | 애플리케이션 초기화, 프로바이더, 전역 스타일, 라우팅 | 모든 계층 |
| processes | 여러 기능을 결합하는 비즈니스 프로세스(온보딩, 결제) | pages, features, entities, shared |
| pages | 페이지의 기능 구성, 페이지 라우팅 | features, entities, shared |
| features | 사용자 시나리오: 로그인 양식, 즐겨찾기 목록, 검색 필터 | entities, shared |
| entities | 비즈니스 엔터티: User, Product, Order, Cart | shared |
| widgets | 복합 UI 컴포넌트: Header, Sidebar, ArticleCard | shared, entities |
| shared | 유틸리티, UI-kit, API 클라이언트, 설정 — 비즈니스 로직과 무관 | 외부 라이브러리만 |
FSD 프로젝트의 디렉토리 구조 예시:
src/
├── app/ // 애플리케이션 계층
│ ├── providers/
│ ├── router/
│ └── styles/
├── pages/ // 페이지 — 기능 구성
│ └── main/
├── features/ // 기능 — 사용자 시나리오
│ ├── auth/ // 슬라이스 «인증»
│ │ ├── ui/
│ │ ├── model/
│ │ └── api/
│ └── productList/ // 슬라이스 «제품 목록»
│ ├── ui/
│ └── model/
├── entities/ // 비즈니스 엔터티
│ ├── user/
│ └── product/
├── widgets/ // 복합 컴포넌트
│ └── header/
└── shared/ // 공유 유틸리티 및 UI-kit
└── ui/«계층은 아래쪽만 본다» 규칙은 FSD의 초석입니다. feature auth가 entity user를 가져오는 것은 올바릅니다. entity user가 feature auth를 가져오기 시작하면 순환 종속성 및 격리 위반입니다. 이 규칙을 강제하기 위해 ESLint 플러그인(eslint-plugin-fsd) 또는 슬라이스 공개 API의 사용자 지정 린터가 사용됩니다.
슬라이스(Slice) — FSD에서 그룹화의 기본 단위로, 하나의 비즈니스 기능 또는 엔터티에 해당합니다. 각 슬라이스는 7개 계층(features, entities, widgets, pages) 중 하나에 위치하며 특정 기능을 구현하기 위한 완전한 코드 세트(UI 컴포넌트, 데이터 모델, API 클라이언트, 상수, 테스트)를 포함합니다.
슬라이스 경계는 비즈니스 도메인에 의해 정의됩니다. feature auth는 인증과 관련된 모든 것(로그인 양식, 등록 양식, 비밀번호 재설정)을 포함합니다. entity user는 User 모델, UserRepository 및 직렬화를 포함합니다. 경계는 중복되어서는 안 됩니다. feature auth에 사용자 데이터가 필요한 경우 로직을 복제하는 대신 entity user를 가져옵니다. 모바일 개발에서 FSD 슬라이스는 종종 Android의 Gradle 모듈이나 iOS의 Swift 패키지에 해당합니다.
슬라이스는 엄격하게 격리됩니다. 한 슬라이스의 내부 구조는 다른 슬라이스에 보이지 않습니다. 슬라이스 간 상호작용을 위해 공개 API(index.ts/index.js 파일 — 외부 사용이 허용된 것만 내보냄)가 사용됩니다. 나머지는 모두 프라이빗 모듈입니다. 이 접근 방식은 우발적 종속성을 방지하고 리팩토링을 단순화합니다. 한 슬라이스의 프라이빗 구현을 변경해도 다른 슬라이스에 영향을 미치지 않습니다.
각 FSD 슬라이스 내에서 코드는 세그먼트별로 더 조직화됩니다 — 모든 슬라이스에서 반복되는 기술적 카테고리입니다. 표준 세그먼트 세트에는 ui(인터페이스 컴포넌트), model(비즈니스 로직, Store, Actions, Reducer), api(서버 요청, 변이), lib(유틸리티 및 헬퍼) 및 config(기능 설정)가 포함됩니다.
| 세그먼트 | 내용 | 예시 |
|---|---|---|
| ui/ | React/Vue/SwiftUI 컴포넌트, 스타일, Storybook | LoginForm.tsx, login.module.css |
| model/ | Store, Reducer, Actions, 타입, 계약 | LoginStore.ts, authReducer.ts |
| api/ | HTTP 클라이언트, 변이, RPC 호출 | authApi.ts, loginMutation.ts |
| lib/ | 도우미 함수, 유효성 검사기 | validateEmail.ts, formatPhone.ts |
| config/ | 상수, 기능 설정 | authConfig.ts, endpoints.ts |
세그먼트는 권장 사항이지 엄격한 규칙이 아닙니다. 슬라이스가 작은 경우 세그먼트를 병합할 수 있습니다. 큰 슬라이스(10개 이상의 파일이 있는 기능)의 경우 세분화가 필수입니다. 그렇지 않으면 내부 구조가 50개 파일의 «바구니»로 빠르게 변하여 필요한 컴포넌트를 찾는 데 몇 분이 걸립니다. 모바일 개발에서 세그먼트는 종종 유형별 파일 구조로 대체됩니다. 각 기능은 내부 유형이 있는 별도의 Swift 파일 또는 Kotlin 클래스입니다.
모바일 개발에서 FSD는 플랫폼별 기능(Android의 모듈식 구조(Gradle 모듈) 및 Swift Package Manager)에 적응합니다. Android 적응은 각 슬라이스가 자체 build.gradle을 가진 별도의 Gradle 모듈이라고 가정합니다. feature-auth, feature-profile, entity-user, shared-ui 모듈은 빌드 수준에서 서로 격리됩니다. feature-auth는 dependencies에 지정되지 않는 한 feature-profile을 가져올 수 없습니다.
iOS 적응은 Swift Package Manager를 기반으로 합니다. 각 슬라이스는 공개 API가 있는 Swift 패키지입니다. TCA 프로젝트에서 feature.auth 슬라이스에는 자체 Reducer, Store, View 및 API 클라이언트가 포함됩니다. Swift Community Survey 2024에 따르면 TCA를 사용하는 iOS 프로젝트의 28%가 FSD에 가까운 슬라이스 아키텍처를 사용합니다.
모바일 FSD 적응의 주요 문제는 shared 계층의 중복입니다. 모바일 개발에서 UI 컴포넌트(shared/ui)는 종종 플랫폼(Android Views vs Jetpack Compose vs SwiftUI)에 따라 달라지며, 각 기술에 대해 별도의 shared 모듈이 필요합니다. FSD에서 shared 계층은 일반적으로 플랫폼 독립적(유틸리티, 설정)이며 UI-kit은 별도의 모듈이나 컴포넌트 라이브러리로 이동됩니다.
장점 FSD는 10명 이상의 개발자가 있는 대규모 프로젝트에서 두드러집니다. 각 개발자 또는 팀은 다른 코드를 건드리지 않고 자체 슬라이스에서 작업합니다. git 충돌이 40~60% 감소합니다(feature-sliced.design 사례 연구 데이터). 새로운 기능은 슬라이스의 공개 API만 사용하는 경우 기존 기능을 손상시킬 위험 없이 추가됩니다. 하나의 기능 리팩토링은 다른 기능의 변경을 필요로 하지 않습니다. 공개 API를 유지하면서 하나의 슬라이스 내에서 ui/model/api를 다시 작성하면 됩니다.
| 측면 | FSD | Feature-based(FSD 없음) | 계층형 아키텍처 |
|---|---|---|---|
| 기능 격리 | 엄격함 | 중간 | 낮음 |
| 병렬 개발 | 10+ 팀 | 3~5 팀 | 1~2 팀 |
| 프로젝트 간 재사용 | 예(슬라이스 패키지) | 복사-붙여넣기만 | shared 모듈을 통해 |
| 진입 장벽 | 높음 | 낮음 | 중간 |
| Gradle 격리(Android) | 네이티브(모듈) | 네이티브(모듈) | 약함 |
단점 FSD의 — 소규모 프로젝트에는 과도한 중첩. 애플리케이션이 3~5개의 화면으로 구성된 경우 7개 계층과 각 슬라이스 내 세분화는 애플리케이션 자체보다 더 많은 조직 코드를 생성합니다. 진입 장벽이 높습니다. 새 개발자는 방법론을 배우는 데 2~4주가 걸립니다. 또한 FSD는 빠른 프로토타이핑과 호환성이 낮습니다. 프로토타이핑에는 빈번한 교차 계층 가져오기가 필요하지만 FSD에서는 금지되어 반복 속도가 느려집니다.
더 간단한 Feature-based 구조로 시작하고 화면 수가 20개를 초과하고 팀이 5명을 초과하면 FSD로 마이그레이션하는 것이 좋습니다.
자주 묻는 질문
Feature-based 아키텍처는 엄격한 가져오기 규칙 없이 기능별로 코드를 그룹화합니다. feature Auth는 제한 없이 다른 feature Profile을 가져올 수 있습니다. FSD는 계층 계층 구조와 «계층은 아래쪽만 본다» 규칙을 추가합니다. Feature-based에서는 entity와 feature가 동일한 수준에 있을 수 있고 서로 가져올 수 있습니다. FSD에서는 entity가 feature 아래에 있으며 feature가 entity를 가져오고 그 반대는 안 됩니다. Feature-based는 소규모 프로젝트에 적합하고 FSD는 대규모 프로젝트에 적합합니다.
슬라이스 격리는 단위 테스트를 단순화합니다. 각 슬라이스는 하위 계층의 종속성을 모킹하여 독립적으로 테스트됩니다. feature auth의 경우 entity user를 모킹하는 것으로 충분합니다. 통합 테스트는 슬라이스의 공개 API를 확인합니다. Android에서 기능의 Gradle 모듈에는 Reducer, API 클라이언트 및 UI(Compose Test를 통해)에 대한 테스트가 있는 자체 테스트 디렉토리가 있습니다. iOS에서 슬라이스 패키지에는 모든 세그먼트의 테스트가 포함됩니다.
네, FSD는 Jetpack Compose와 잘 호환되며, 특히 멀티 모듈 Android 프로젝트에서 그렇습니다. 각 슬라이스는 exported 디렉티브를 통해 공개 API가 있는 별도의 Gradle 모듈입니다. features 계층에는 Composable 기능(LoginFeature, ProductListFeature)이 포함되고, entities 계층에는 데이터 클래스와 Repository가 포함되며, shared에는 UI-kit(MaterialTheme-wrapper, 사용자 지정 컴포넌트)이 포함됩니다. FSD는 5명 이상의 개발자가 있는 대규모 Compose 프로젝트에 권장됩니다.
필수 계층은 app, shared, entities 및 features입니다. 나머지(processes, pages, widgets)는 선택사항이며 필요에 따라 추가됩니다. 모바일 개발에서 pages 계층은 종종 탐색 라우팅과 병합되고 widgets은 shared/ui-kit으로 대체됩니다. 프로세스(processes)는 일반적으로 모바일 프로젝트에서 사용되지 않습니다. 그 역할은 도메인 계층 또는 ViewModel의 비즈니스 로직이 수행합니다. 중요한 것은 가져오기 계층 구조 규칙을 따르는 것입니다.
FSD는 DDD에서 Bounded Context 및 Ubiquitous Language 개념을 차용합니다. 각 슬라이스는 bounded context에 해당합니다 — 용어가 명확한 의미를 갖는 경계입니다. 슬라이스 내에서는 개발자와 비즈니스 분석가 모두가 이해할 수 있는 통합 언어(ubiquitous language)가 사용됩니다. 예를 들어 auth 슬라이스에서 «로그인», «비밀번호», «토큰»이라는 용어는 모든 팀 구성원에게 동일한 의미를 가지며 분석가와 개발자 간의 오해를 30~50% 줄입니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.