[React] FSD 아키텍처란? 유지보수하기 좋은 프론트엔드 구조

2026. 3. 11. 23:40·Front-End/React

들어가며

출처 : https://www.instagram.com/p/DR4F7zGiScJ/

 

어느 정도 프론트엔드 개발에 익숙해지다 보니, 신규 기능 개발은 이제 크게 어렵지 않습니다.

사실상 가장 힘든 일은 이해하기 어렵게 짜여진 코드의 맥락을 추적하고, 파편화되어 흩어져 있는 코드를 유지 보수하는 일입니다.

 

오늘은 이런 어려움을 해소할 수 있는 방법 중 하나인 Feature-Sliced Design (FSD) 아키텍처 방법론을 소개합니다. 😀

 

보통 리액트 프로젝트의 폴더구조

 

우리에게 익숙한 간단하고 대중적인 폴더 구조입니다.

파일의 역할에 따라 폴더를 나눕니다. 계층형 구조 혹은 역할 기반 구조라고 부르기도 합니다.

 

소규모 앱에는 이런 구조로도 충분하지만, 프로젝트 규모가 커질수록 다소 불편한 점들이 보이기 시작합니다.

이 폴더 구조는 앱이 거대해졌을 때 어떤 고민이 생길 수 있을까요?

 

나노바나나 - 파일들의 의존성이 복잡하게 얽혀있어 머리아픈 이미지

 

바로 “컴포넌트가 소비되는 곳과 가까운 곳에 위치하지 않는다.” 입니다.

개발자는 컴포넌트 하나를 수정하기 위해 components, api, hooks 폴더를 이리저리 뒤적여야 합니다.

연관된 파일을 파악하기 어려운 구조는 개발자의 실수를 유발하고, 피로도를 높입니다.

✅ 짧은 팁
IDE의 전체 검색 Ctrl + Shift + F, 이 파일이 어디에서 사용중인지 확인하는 Find Usages를 사용하면
조금 더 편하게 폴더를 이리저리 뒤적일 수 있습니다.

 

 

React Colocation - 가까이 둡시다.

// 계층형 구조 : 흩어져있는 코드
src/
 ├── api/ (UserAPI, PostAPI, AuthAPI...)
 ├── components/ (UserCard, PostList, Button...)
 ├── hooks/ (useUser, usePost, useAuth...)
 └── types/ (user.d.ts, post.d.ts...)

// colocation : 자주 함께 변경되는 파일들을 같이 보관해보자
src/
 └── features/
      └── user/
           ├── UserProfile.tsx
           ├── useUser.ts      
           ├── user.api.ts
           ├── user.d.ts
           └── UserProfile.styles.css

 

React에서 Colocation은 “일반적으로 자주 함께 변경되는 것들을 같이 보관”하는 원칙을 말합니다.

단순히 로직, 파일을 가깝게 배치하는 것만으로도 가독성과 유지보수성이 향상됩니다.

 

하지만 프로젝트의 규모가 거대해지고, 수십 개의 컴포넌트가 서로 엉키기 시작하면 어떨까요?

단순히 '가깝게 두는 것'만으로는 해결되지 않는 순환 참조와 의존성 지옥이 기다리고 있습니다.

 

예를 들어, user 폴더의 컴포넌트에서 post 폴더를 참조해도 되는지 등의 규칙이 없기 때문입니다.

따라서 더 견고한 아키텍처를 위한 어떠한 규칙, 방법론이 필요하게 됩니다.

 


 

FSD(Feature-Sliced Design)란?

https://feature-sliced.design/kr/docs/get-started/overview

 

Overview | Feature-Sliced Design

Feature-Sliced Design (FSD) 는 프론트엔드 애플리케이션의 코드를 구조화하기 위한 아키텍처 방법론입니다.

feature-sliced.design

https://feature-sliced.design/docs/get-started/overview

 

 

FSD는 프론트엔드 애플리케이션의 코드를 구조화하기 위한 아키텍처 방법론입니다.

대규모 프로젝트에서 유지보수를 쉽게 만들기 위해 등장했습니다.

코드가 얼마나 많은 책임을 가지는지와 다른 모듈에 얼마나 의존하는지에 따라 계층화합니다.

 

 

1. 레이어 (Layer)

https://feature-sliced.design/kr/docs/reference/layers

레이어는 FSD에서 코드를 나눌 때 사용하는 가장 큰 구분 단위입니다.

핵심은 “상위 레이어는 하위 레이어만 참조할 수 있다”는 단방향 의존성 규칙입니다.

 

위 레이어는 아래 레이어를 사용할 수 있지만, 반대는 불가능합니다.

(리액트도 그렇고 프론트엔드 생태계는 단방향을 참 좋아하는 것 같아요.)

 

6개의 주요 레이어 요약

레이어 설명 예시
App 애플리케이션의 설정, 전역 스타일, 프로바이더(Provider) 등 AppProvider, GlobalStyles, main.tsx
Pages 사용자에게 보여지는 개별 페이지 단위로 실제 콘텐츠를 조립하는 곳 HomePage, ProductDetailPage, LoginPage
Widgets 독립적인 UI 블록으로 여러 페이지에서 재사용되는 대규모 기능 또는 UI Header, Sidebar, Footer
Features 사용자의 행동(Action)과 관련된 비즈니스 가치를 제공 LoginByEmail, AddToCart, SearchProducts
Entities 비즈니스 실체(객체)를 나타냅니다. 데이터 모델, 상태, API 요청이 포함됩니다. User, Product, Order, Comment
Shared 프로젝트 전반에서 재사용되는 인프라성 코드와 공통 UI 컴포넌트입니다. Button, Input, APIClient, DateUtils

 

 

2. Slice - 비즈니스 도메인에 따른 최소 단위의 구분

슬라이스는 FSD 아키텍처의 2번째 계층입니다. 레이어 내 코드를 비즈니스 도메인별로 나눕니다.

슬라이스의 이름은 비즈니스 도메인에 맞게 자유롭게 정할 수 있습니다.

 

핵심 규칙은 "슬라이스끼리는 서로를 알 수 없다." 입니다.

예를 들어, features/auth 슬라이스는 같은 레이어에 있는 features/cart 슬라이스를 참조할 수 없습니다.

(import 못한다는 소리입니다.)

 

🤔 왜 서로 참조하지 못하게 하나요?

파일들을 비즈니스 맥락에 따라 한곳에 모음으로써 높은 응집도를 확보하고, 슬라이스 간의 의존성을 끊어 낮은 결합도를 유지하기 위해서입니다. 덕분에 프로젝트가 거대해져도 특정 기능을 수정할 때 발생하는 사이드 이펙트를 최소화하고 코드 베이스를 훨씬 쉽게 탐색할 수 있습니다.

 

 

3. Segment - 파일의 역할에 따른 최종 분류

세그먼트는 FSD 아키텍쳐의 3번째 계층입니다.

슬라이스가 하나의 비즈니스 도메인으로 분류된다면,

세그먼트는 슬라이스의 비즈니스 덩어리를 기술적인 역할에 따라 다시 한번 분리합니다.

 

이름은 자유롭게 정할 수 있지만 보통 아래와 같은 이름을 사용합니다.

user
 ├ ui     // 화면에 보여지는 모든 것(컴포넌트, 스타일)
 ├ api    // 서버와의 통신
 ├ model  // 데이터 핵심 로직 (인터페이스, 상태 관리/Store)
 ├ lib    // 이 슬라이스에서만 사용하는 보조 도구 (라이브러리, 유틸)
 └ config // 설정 값

 

 

🤔 모든 레이어에서 세그먼트가 꼭 같아야할까?

반드시 그렇지 않습니다. 대부분의 경우 위의 세그먼트만으로 충분합니다.

하지만, 공유(shared) 레이어나 앱(app) 레이어에서는 필요에 따라 새로운 세그먼트를 만들어도 됩니다. (강제된 규칙이 아닙니다.)

즉, 기본 구조는 유지하되, 필요하면 유연하게 확장할 수 있습니다.

 

 

+ FSD 전체 폴더 구조 예시

더보기
src
│
├ app
│  ├ providers
│  ├ router
│  ├ styles
│  └ index.tsx
│
├ pages
│  ├ home
│  │  ├ ui
│  │  │  └ HomePage.tsx
│  │  └ index.ts
│  │
│  └ profile
│     ├ ui
│     │  └ ProfilePage.tsx
│     └ index.ts
│
├ widgets
│  ├ header
│  │  ├ ui
│  │  │  └ Header.tsx
│  │  └ index.ts
│  │
│  └ sidebar
│     ├ ui
│     │  └ Sidebar.tsx
│     └ index.ts
│
├ features
│  ├ login
│  │  ├ ui
│  │  │  └ LoginForm.tsx
│  │  ├ model
│  │  │  └ useLogin.ts
│  │  ├ api
│  │  │  └ loginApi.ts
│  │  └ index.ts
│  │
│  └ add-to-cart
│     ├ ui
│     │  └ AddToCartButton.tsx
│     ├ model
│     │  └ cartStore.ts
│     ├ api
│     │  └ addCartApi.ts
│     └ index.ts
│
├ entities
│  ├ user
│  │  ├ ui
│  │  │  └ UserAvatar.tsx
│  │  ├ model
│  │  │  └ userStore.ts
│  │  ├ api
│  │  │  └ userApi.ts
│  │  └ index.ts
│  │
│  └ product
│     ├ ui
│     │  └ ProductCard.tsx
│     ├ model
│     │  └ productTypes.ts
│     ├ api
│     │  └ productApi.ts
│     └ index.ts
│
├ shared
│  ├ ui
│  │  ├ Button
│  │  │  └ Button.tsx
│  │  └ Input
│  │     └ Input.tsx
│  │
│  ├ lib
│  │  └ formatDate.ts
│  │
│  ├ api
│  │  └ baseApi.ts
│  │
│  └ config
│     └ env.ts
│
└ main.tsx

 


FSD의 장점과 단점

장점

1. 프로젝트 구조가 통일됩니다.

모든 기능이 같은 구조를 사용하기 때문에 코드가 훨씬 일관성 있게 정리됩니다.

새로운 개발자가 프로젝트에 투입되어도 어디에 코드가 있고, 어디를 수정해야 하는지 빠르게 이해할 수 있습니다.

 

2. 변경과 리펙토링이 쉬워집니다.

위에서 설명한 FSD의 계층별 규칙(레이어, 슬라이스)을 통해 한 기능을 수정해도 다른 기능에 영향을 줄 가능성이 줄어듭니다.

 

3. 유지 보수성이 향상됩니다.

어떤 코드는 여러 곳에서 재사용해야 하고, 어떤 코드는 특정 기능에서만 사용해야 합니다.

FSD 아키텍쳐를 사용하면 공유 코드는 shared, 특정 기능 코드는 feature처럼 재사용 범위를 자연스럽게 나눌 수 있습니다.

 

4. 비즈니스 중심 구조가 됩니다.

폴더 이름을 비즈니스 용어로 만들기 때문에 실제 서비스 개념과 코드 구조가 맞춰집니다.

개발자는 프로젝트 전체를 완벽하게 이해하지 않아도 자신이 맡은 기능을 개발할 수 있게 됩니다.

즉, 신규 입사자의 온보딩 속도가 빨라지겠죠 !

 

단점

1. 초기 구조가 복잡하다.

레이어, 슬라이스, 세그먼트로 분리하기 때문에 폴더 구조가 꽤 많아집니다.

따라서 작은 프로젝트에는 오히려 오버 엔지니어링이 될 수 있습니다.

이런 경우에는 공식 문서에서 소개하는 점진적 도입을 참고하세요. 😎

 

2. 러닝 커브

FSD는 일반적인 React 폴더 구조와 다르고, 각 계층의 규칙이 존재하기 때문에 처음 접하는 개발자에게는 이해하기 어려울 수 있습니다.

 

3. 규칙이 중요하다.

FSD는 정해진 규칙도 있고, 유연하게 팀에서 만든 규칙을 적용할 수도 있습니다.

하지만 규칙을 잘 정하고 잘 지키지 않으면 FSD의 구조가 망가지게 됩니다.

(같은 팀에서 같은 컨벤션도 지키기 힘든데 잘 지켜지는 회사의 모습이 궁금하네요 🥲)

 


 


참고 문헌:

https://feature-sliced.design/kr/docs/get-started/overview

https://tech.kakaopay.com/post/fsd/

'Front-End > React' 카테고리의 다른 글

[React] 리액트 SNS 공유하기 기능 개발하기 (Web Share API란?)  (4) 2024.11.14
[React] 리액트 QR 코드 스캔하기 (react-qr-reader)  (6) 2024.10.31
[React] 리액트 QR 코드 생성하기 (qrcode.react)  (7) 2024.10.29
[React] Zustand란? 사용하는 이유! (상태 관리 라이브러리, 사용 방법 예시)  (4) 2024.03.14
[React] 리액트 CSS 초기화란? (CSS Reset, 여백 제거)  (2) 2023.10.12
'Front-End/React' 카테고리의 다른 글
  • [React] 리액트 SNS 공유하기 기능 개발하기 (Web Share API란?)
  • [React] 리액트 QR 코드 스캔하기 (react-qr-reader)
  • [React] 리액트 QR 코드 생성하기 (qrcode.react)
  • [React] Zustand란? 사용하는 이유! (상태 관리 라이브러리, 사용 방법 예시)
현기
현기
  • 현기
    현기의 개발블로그
    현기
  • 전체
    오늘
    어제
    • 분류 전체보기 (127)
      • Front-End (42)
        • Next (7)
        • React (9)
        • React Native (11)
        • Flutter (0)
        • Vue (1)
        • JSP (9)
        • HTML, CSS, JS (5)
      • Back-End (16)
        • Node.js (3)
        • Spring (8)
        • Flask (1)
        • AWS (4)
      • DB (5)
        • Oracle (4)
        • MySQL (1)
      • Python (7)
      • Java (27)
        • 자바 이론 (17)
        • 코딩테스트 연습 & 실습 (10)
      • 자료구조 & 알고리즘 (7)
        • 코딩테스트 (6)
        • 알고리즘 (1)
      • AI (3)
      • 블록체인 (0)
      • 프롬프트 엔지니어링 (0)
      • CS 지식 (5)
      • IT뉴스 (0)
      • 일상 (3)
      • etc (12)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 웹 이력서
  • 공지사항

  • 인기 글

  • 태그

    그리디
    React Native Chart
    포스트맨
    클로드 코드
    REST API
    react
    IS-A
    자바
    node.js
    큐
    서블릿
    next-intl
    DI
    티스토리챌린지
    리액트 네이티브
    react-native-chart-kit
    Python
    JSP
    JDBC
    자바 스프링
    자바스크립트
    Express
    오블완
    스택
    Spring
    React Native
    Java
    파이썬
    오라클
    쓰레드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
현기
[React] FSD 아키텍처란? 유지보수하기 좋은 프론트엔드 구조
상단으로

티스토리툴바