Open api generator를 사용하는 Next.js 프로젝트에서 Feature Sliced Design을 적용한 사례를 남기는 회고록

Layers는 FSD 패턴의 첫 번째 수준을 나타냅니다. 레이어는 각각이 다루어야 할 책임과 다른 모듈과의 의존도에 따라 분류됩니다.
각 Layer는 Slice와 Segment들로 세분화되며, app과 shared 레이어는 그 자체로서 Slice이기 때문에 예외입니다.

상위 레벨에 있는 레이어는 하위 레벨을 의존성으로 가질 수 있지만 그 반대는 성립될 수 없습니다.
하위 레이어일수록 추상화가 심화되며(특정 상황에 국한되지 않는 범용성 높은 작업만을 포함), 상위 레이어일수록 비즈니스 로직이 심화됩니다.
💡 레이어에 대한 가져오기 규칙
레이어 간 가져오기 규칙이 정의되어 있는 이유는 FSD 패턴이 포함 관계를 구체화하는 패턴이기 떄문입니다.
레이어는 매우 응집력 있는 모듈 그룹인 슬라이스로 구성되어 있습니다.
슬라이스의 모듈(파일)은 아래 레이어에 위치하는 것들만 의존성으로 가질 수 있습니다.
For example, the folder
📁 ~/features/aaais a slice with the name "aaa". A file inside of it,~/features/aaa/api/request.ts, cannot import code from any file in📁 ~/features/bbb, but can import code from📁 ~/entitiesand📁 ~/shared, as well as any sibling code from📁 ~/features/aaa, for example,~/features/aaa/lib/cache.ts.
이제 하위 레이어에서부터 각각을 알아보고 프로젝트에 어떻게 적용하였는지 알아보겠습니다.
Shared는 다른 모든 레이어의 근간을 형성하며, Slice를 두지 않고 Segment가 바로 하위에 존재합니다.
일반적으로 Shared가 포함하는 세그먼트는 다음과 같습니다.
📁 api : API 클라이언트이며 특정 백엔드 엔드포인트에 요청을 하는 기능을 포함할 수 있습니다.📁 ui : 애플리케이션의 ui Kit을 포함합니다. 비즈니스 로직을 포함하는 코드는 존재해선 안되며, 비즈니스 기반으로 분류하는 것은 괜찮습니다. Atomic Design 기준 Atoms 컴포넌트가 포함될 수 있습니다.📁 lib : 내부 라이브러리 모음. 이 세그먼트를 helper나 utilities 같은 뭉둥그려진 구조로 사용해서는 안되며, 날짜나 색상 같은 특정한 목적별로 관리되어야 합니다.📁 config : 환경 변수 등 전역 configuration이 포함됩니다.📁 routes : 라우팅 관련 constants나 pattern 등을 포함할 수 있습니다.📁 store : 프로젝트 전반에 걸쳐 사용할 Zustand store를 포함할 수 있습니다.엔터티 레이어에 포함되는 슬라이스는 실제 다루고자 하는 이 세상의 개념을 포함합니다. 코문철 기준으로, 리뷰/배틀/댓글 등 도메인이 해당됩니다.
아래는 코문철 Entities 레이어 캡처입니다.
각 슬라이스에는 아래 세그먼트들이 포함됩니다.
| 파일 | 역할 |
|---|---|
types.ts | 타입 정의 (인터페이스, enum 등) |
model.ts | 데이터 변환 및 비즈니스 로직 |
api.ts | API 호출 관련 함수 |
open api generator를 사용하지 않는 경우, api in/out 타입을 types.ts에 작성해야 합니다. 하지만 api in/out 스펙은 자동 생성되므로
등이 있다면 이곳에 작성합니다.
💡 open api generator로 자동 생성된 api in/out dto interface는 프로젝트 root/generate 하위에 자동 생성되지만, entites/domain/types.ts에 작성한 것으로 간주하여 의존 관계를 관리하도록 하였습니다.
이 파일은 실제 데이터를 다루는 로직을 포함합니다.
주요 역할은:
types.ts에서 정의한 타입 사용)이 파일은 엔터티와 관련된 API를 호출하는 함수를 포함합니다.
코문철에서는 open api generator로 자동 생성된 스펙을 호출하면서
위 세가지 설정을 추가하였습니다.
Features 레이어가 Entities, Shared와 어떻게 다른지 표로 나타내었습니다.
| 폴더 | 역할 |
|---|---|
entities/ | 도메인 모델 (User, Comment, Battle 등 핵심 개념) |
feature/ | 도메인 단위의 비즈니스 로직과 UI (BattlePage, UserProfile 등) |
shared/ | 전역적으로 사용되는 공통 모듈 (UI, Utils, API 클라이언트 등) |
이 레이어는 앱의 주요 상호 작용을 포함합니다. 각 도메인에서 다루어야 할 기능을 담지만, “모든 것을 기능으로 세분화”하는 상황을 경계하면 되겠습니다.
코문철의 Feature layer는 Entities layer와 동일하게 도메인 별 Slice를 갖도록 하고, 아래 Segment 들을 갖도록 하였습니다.
| 파일 | 역할 |
|---|---|
model/ | 상태 관리 (Zustand) |
ui/ | ui 컴포넌트 |
hooks/ | React Hooks |
types.ts | 타입 정의 |
helper.ts | 유틸리티 함수 |
constants.ts | 상수 정의 |