
프로젝트를 시작할 때 폴더구조를 어떻게 할지 모든 개발자들이 매번 고민한다고 생각한다.(정답이 없기 때문에..)
9기 프로젝트를 진행하면서 FSD 폴더 구조 전략을 쓰자는 이야기가 나왔다. 평소에 들어는 봤지만 , 정확히 알지는 못해서
이번 기회에 FSD 폴더 구조 전략에 대해 알아보고자 한다.
Q . 로그인과 관련된 컴포넌트,페이지,api를 찾아보세요.

찾는데 3초 이상 걸렸을 것이다.
이렇게 코드,파일들이 여러곳에 흩어져 있으면 많은 단점이 존재합니다.
- 특정 기능을 수정하려면 여러 폴더를 돌아다녀봐야한다. (가독성과 유지보수가 떨어진다)
- 기능 중심이 아닌, 기술 중심 분류로 구성되어있다. ⇒ 실제 사용 맥락이 고려되지 않는다.
- 하나의 폴더 안에 파일이 수백개씩 존재하거나 , 파일 depth가 깊어지는 현상이 발생한다. ex) 컴포넌트 폴더 안에 마구잡이로 컴포넌트 우겨 넣음
- 생산성이 떨어진다.
- 기능 하나 고쳤는데, 전혀 상관없는 회원가입 페이지가 터지거나,
- 코드를 수정 할 때 복잡해짐 ⇒ 높은 학습 비용이 생김
- 여러곳에서 복잡한 코드가 생긴다면, 잦은 코드 충돌 가능성도 높아진다.
예를들어 프로필을 수정한다고 가정한다.
ProfileForm 수정 ⇒ 이거 다른곳에서도 쓰일 거 같은데? ⇒ 다른곳에서 오류 안생기게 수정해야겠다. ⇒ 다른곳에서 오류가 터짐 .. 등등
이런 스파게티 코드처럼 .. 줄줄이 소세지가 된다.
이런 문제들은 개발 규모가 커지면 더 연속해서 터지는 문제 들이 발생한다. (원인조차 찾기 힘들어짐 ㅜㅜ)
FSD 폴더 구조 (Feature-Sliced-Design)
페이지 기능(feature)단위로 코드를 모아서 관리하면 유지보수가 더 편하지 않을까?
FSD란?
- FSD(Feature-Sliced Design) 아키텍처는 소프트웨어 시스템을 기능 중심으로 나누어 모듈화하고, 각 기능을 독립적으로 관리하는 방식이다.
- 특히 대규모 프론트엔드 애플리케이션에서 코드의 유지보수성과 재사용성을 높이기 위해 사용된다.
- FSD 아키텍처는 각 기능을 독립적인 도메인으로 분리하여 개발할 수 있도록 하고, 코드의 복잡도를 줄이며, 팀 협업을 개선하는 데 목적이 있다.
FSD기본 개념
- 기능 기반 분할: 애플리케이션을 기능별로 나누어 각 기능을 독립적인 모듈로 관리하며, 기능은 시스템에서 특정한 비즈니스 로직이나 사용자 인터페이스의 한 부분을 담당한다.
- 레이어링: 기능을 레이어로 나누어 책임을 분리한다. 일반적으로 Presentation, Domain, Data 레이어로 구성되며, 이는 기능에 따라 구체화된다.
features/
└─ login/
├─ ui/
│ └─ LoginForm.tsx ← Presentation
├─ model/
│ └─ login.model.ts ← Domain
├─ api/
│ └─ login.api.ts ← Data
└─ index.ts
- 폴더 구조: 기능별로 폴더 구조를 구성하여 코드의 가독성과 유지보수성을 높이며, 각 폴더는 그 기능과 관련된 모든 것을 포함한다.
- 재사용성: 공통 기능이나 유틸리티는 재사용 가능하도록 Shared 레이어에 배치한다. 이를 통해 중복 코드를 줄이고 일관성을 유지한다.

(processes는 현재 제거됨)
레이어 (Layers)
- 가장 상위 수준의 구성 단위
- 코드의 영향 범위와 코드가 서로 의존하는 흐름을 정의한다.
- 각 레이어는 특정 역할을 담당한다. 이는 다른 레이어에 의존하거나 영향을 미칠 수 있다
App- 말 그대로 앱이 실행하는 모든 것이 들어있는 레이어이다
- 전역 설정 , 스타일 ,프로바이더.라우팅 등을 포함한다.

Pages
- 완전한 애플리케이션 페이지가 위치하는 레이어
- 위젯, 기능 , 엔티티를 조합하여 구성한다.

Widgets
- 독립적으로 작동하는 대규모 기능 또는 UI 컴포넌트가 위치하는 레이어
- 여러가지 조합이 가능한 UI 블록 ex) 헤더,대쉬보드,탭 …등

features
- 사용자 상호작용과 관련된 기능 (동사) ex) 버튼을 누르는 기능 , 계정 생성하는 기능, 필터 기능 …등

entities
- 특정 비지니스 도메인의 본질적인 규칙과 데이터 구조 ex) user,product,order (명사형)
- 데이터 그 자체

shared
- 재사용 가능하며 독립적인 공통 컴포넌트, 유틸리티, 공통 코드가 위치함
- slice를 거치지 않음
슬라이스 (Slices)
- 비지니스 도메인 별로 코드를 분할한다.
- 레이어의 하위 디렉토리
- 관련된 모든 코드를 한 곳에 모아 높은 응집도를 달성하는 핵심적인 역할이다.
- 딱히 정해지지 않음. 개발자가 어떤 기능을 개발하고 싶은지에 따라서 자유롭게 정함

- 슬라이스 원칙
- 기술별이 아닌, 기능 중심으로 그룹화 한다.
- 한 슬라이스 안에서 필요한 요소들을 해결한다.
- 다른 슬라이스를 함부로 참조하지 않도록 제한한다.
세그먼트 (Segments)
- 기술적인 목적에 따라 코드를 그룹화함
- 내부의 코드를 체계적으로 구성하는 역할이다. ex) ui, model, api, lib, config

- 세그먼트 원칙
- 슬라이스 내부에서도 역할을 나눈다.
- 기능마다 공통적인 세그먼트 구조를 유지한다.
FSD의 규칙
그러면 폴더 이름만 바뀐거 아닌가요? 이게 무슨 의미가 있지요? FSD에는 중요한 법칙이 있습니다.

- 레이어간의 위계 질서가 존재함. (아무 데서나 아무 폴더를 import 하면 안 된다) ⇒ 추상화, 다형성 ,상속 달성
- App은 밑에 하위 5가지를 import 가능 , widgets은 하위 3가지 import 가능
- 하지만 feature가 widget을 import 불가능
- index.js (or index.ts)에서 export 한것만 import 한다 ⇒ 캡술화 달성
- 이 파일을 통해 슬라이스 또는 세그먼트에서 필요한 기능만 외부로 추출하고 불필요한 기능은 격리할 수 있다. 인덱스 파일은 진입점 역할을 한다.
- 애플리케이션 슬라이스와 세그먼트는 공개 API 인덱스 파일에 정의된 슬라이스의 기능과 컴포넌트만 사용한다.
- 공개 API (index.ts)에 정의되지 않은 슬라이스 또는 세그먼트의 내부 부분은 격리된 것으로 간주되며 슬라이스 또는 세그먼트 내부에서만 접근할 수 있다.
- import 및 export로 단순하게 작동하므로 애플리케이션을 변경할 때 코드의 모든 곳에서 import를 변경할 필요가 없다.
import { useLogin } from "@/features/login";
// features/login/index.ts
export { useLogin } from "./model/useLogin";
FSD의 장점
- 표준화된 구조를 가지고 있어 , 일관성을 유지할 수 있다.
- 구조가 일정해서 유지보수가 쉽고 확장성이 향상된다.
- 기능 중심으로 분리되어 있어 협업 효율성이 증가한다
FSD의 고려 사항
- 의존성 방향 고려하기 : features가 entities를 참조하는 건 가능하지만, 반대로는 참조할 수 없다
- 진입 장벽이 높아 학습하고 이해하는데 많은 시간이 소요된다.
- 프로젝트 규모가 작은 경우에는 FSD를 사용하면 불필요한 복잡성을 추가할 수 있다. 규모에 따라 적절히 선택하자!(느슨한 FSD)
- index.ts를 적극 사용하자
결론
- FSD에서도 정답은 없다 . 기준을 어떻게 보냐에 따라 다르기에 팀원들과 충분한 기준을 상의 후에 시작하자.
- FSD를 무조건 도입하는게 아니라 , 각 상황에 맞게 FSd 도입을 결정하는 것이 필요하다.
참고자료
https://emewjin.github.io/feature-sliced-design/?utm_source=substack&utm_medium=email
'study' 카테고리의 다른 글
| 크로스 브라우징 (0) | 2026.01.05 |
|---|---|
| taillwindCSS의 효율적 사용 feat)cva,clsx,twMerge (1) | 2025.12.30 |