Skip to content

Commit

Permalink
feat: 20241010_FSD_도입_가이드_이재용 (#93)
Browse files Browse the repository at this point in the history
enigsuss authored Oct 21, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 3c3ff8e commit cd7de0f
Showing 1 changed file with 282 additions and 0 deletions.
282 changes: 282 additions & 0 deletions 기술블로그/_posts/2024-10-10-fsd-intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
---
layout: post
title: "Feature-Sliced Design (FSD) 소개"
author: "이재용"
categories: ["프론트엔드 기술블로그"]
banner:
image: "https://feature-sliced.design/kr/img/preview.png"
background: "#000"
height: "100vh"
min_height: "38vh"
heading_style: "font-size: 4.25em; font-weight: bold; text-decoration: underline"
tags: ["Frontend", "directory", "architecture", "FSD", "Feature-Sliced Design"]
---

## 들어가며

대규모 프론트엔드 애플리케이션을 개발하면서 가장 큰 도전 과제 중 하나는 **확장성과 유지보수성**입니다.
프로젝트가 커질수록 구조가 복잡해지고, 기능 추가나 변경이 기존 코드에 의도치 않은 영향을 미칠 가능성이 커집니다.

이런 상황에서 **Feature-Sliced Design(FSD)** 은 유용한 아키텍처 패턴으로,
각 기능을 독립적이고 재사용 가능하게 모듈화하여 관리할 수 있도록 도와줍니다.

이번 글에서는 FSD의 기본 개념을 소개하고, 도입을 고민하는 분들을 위해 그 장점과 도입 시 유의해야 할 점들에 대해 알아보겠습니다.

---

### 왜 Feature-Sliced Design인가?

기존의 프론트엔드 구조는 주로 **레이어링(예: 컴포넌트, 컨테이너, 유틸리티)** 을 기반으로 나누어집니다.
하지만 이 방식은 시간이 지나면서 복잡해지기 쉽고, 변경의 여파가 여러 레이어에 걸쳐 확산될 수 있습니다.
FSD는 이러한 문제를 해결하기 위해 **기능 중심(Feature-Oriented)** 으로 코드를 구성합니다.

즉, **화면(UI)**, **상태(State)**, **로직(Logic)** 을 기능별로 하나의 모듈로 묶어, 기능 단위로 코드를 분리하는 방법입니다.
이를 통해 애플리케이션의 각 부분이 서로 독립적이면서도 필요한 경우 쉽게 재사용할 수 있습니다.

---

### FSD의 기본 원칙

FSD는 크게 세 가지 원칙을 기반으로 합니다.

#### **모듈화 (Modularity)**
각 기능을 독립적으로 나누어 개발합니다.
한 기능은 상태 관리, 비즈니스 로직, UI를 모두 포함할 수 있으며, 해당 기능만을 담당하는 모듈로 관리됩니다.
이로 인해 새로운 기능을 추가하거나 기존 기능을 수정할 때 전체 애플리케이션에 미치는 영향을 최소화할 수 있습니다.

#### **기능 중심 구조 (Feature-Oriented)**
애플리케이션의 코드를 UI 컴포넌트나 로직별로 나누는 것이 아니라 **기능 단위로 수직 분리**합니다.
예를 들어, 로그인 기능과 사용자 프로필 기능은 각각 독립된 모듈로 나뉘며, 각 모듈은 자신의 비즈니스 로직과 상태 관리 로직을 포함합니다.

#### **레이어링 (Layering)**
FSD는 여러 레이어로 애플리케이션을 구성하는데, 각 레이어는 고유한 역할을 수행합니다.
이를 통해 코드의 역할을 명확하게 구분하고, 레이어 간의 의존성을 관리하여 복잡성을 줄입니다.
일반적으로 **App**, **Pages**, **Widgets**, **Features**, **Entities**, **Shared**라는 레이어로 나누어집니다.

---

### FSD 폴더 구조 살펴보기

Feature-Sliced Design(FSD)을 처음 도입하려는 개발자라면, 가장 먼저 궁금해할 부분이 **폴더 구조**일 것입니다.

FSD의 폴더 구조는 크게 **Layers**, **Slices**, **Segments**로 구분됩니다.

---

#### **Layers**

애플리케이션의 전반적인 책임을 수평적으로 나눈 것입니다.
각 레이어는 전체 애플리케이션의 특정 부분을 관리하고, 각 레이어는 독립적인 모듈로 동작합니다.
이 구조는 기능의 책임을 명확히 분리하고, 레이어 간의 의존성을 최소화하도록 돕습니다.

```bash
src/
├─ app/ # 전역 설정 및 상태 관리
├─ pages/ # 라우팅된 페이지 모음
├─ widgets/ # 페이지에 사용되는 독립적인 UI 컴포넌트
├─ features/ # (optional) 개별 기능 모듈
├─ entities/ # (optional) 도메인 엔터티 및 비즈니스 로직
└─ shared/ # 공통 컴포넌트 및 유틸리티
```

**app**

애플리케이션의 전반적인 설정과 상태 관리를 담당합니다. 여기에는 라우팅 설정, 글로벌 스타일, 상태 관리 관련 코드들이 포함됩니다.

**pages**

각 라우트에 대응하는 페이지들이 위치하며, 애플리케이션 내에서 사용자가 접근하는 구체적인 화면입니다.

**widgets**

위젯은 페이지 단위에서 재사용되는 UI 요소를 정의하는 폴더입니다.

**features** (optional)

개별 기능들을 독립적인 모듈로 관리하는 폴더입니다. 로그인, 회원가입, 사용자 프로필 등 기능별로 분리되어 있습니다. 선택적 레이어입니다.

**entities** (optional)

도메인 엔터티와 비즈니스 로직을 관리하는 폴더로, 주로 데이터 모델과 관련된 코드들이 위치합니다. 선택적 레이어입니다.

**shared**

여러 레이어에서 공통적으로 사용되는 컴포넌트나 유틸리티 함수들이 위치하는 폴더입니다.

---

#### **Slices**

기능별로 애플리케이션을 수직으로 나눈 것입니다.
각 슬라이스는 특정 기능을 독립적으로 처리하며, 하나의 기능에 필요한 상태 관리, UI, 비즈니스 로직 등을 모두 포함합니다.

```bash
src/
├─ features/
│ ├─ auth/ # 인증 기능
│ └─ user-profile/ # 사용자 프로필 기능
```
`Slice`의 이름은 프로젝트의 비즈니스 영역에 따라 직접 결정되므로 표준화되어 있지 않습니다.
밀접하게 관련된 조각들은 구조적으로 디렉토리 내에 그룹지을 수 있지만, 이 디렉토리에 있는 코드는 직접적으로 공유되지 않아야 합니다.

---

#### **Segments**

슬라이스 내부에서 더 세부적인 역할로 나누어진 폴더입니다.
각 슬라이스는 상태 관리, UI 컴포넌트, 유틸리티 등을 세그먼트로 나누어 관리할 수 있습니다.

```bash
src/
├─ features/
│ ├─ auth/
│ │ ├─ ui/ # 인증 관련 UI 컴포넌트
│ │ ├─ model/ # 인증 상태 관리 및 비즈니스 로직
│ │ └─ lib/ # 인증 관련 유틸리티 및 API 호출
│ └─ user-profile/
│ ├─ ui/ # 사용자 프로필 UI 컴포넌트
│ ├─ model/ # 사용자 프로필 상태 관리
│ └─ lib/ # 유틸리티 및 API 호출 로직
```

`segment`도 팀의 합의에 따라 구성과 이름이 변경될 수 있습니다.
일반적으로 사용되는 세그먼트는 다음과 같습니다.

**api**
서버 요청을 처리하는 로직이 위치하는 세그먼트입니다. 외부 API와의 통신이나 데이터 요청 로직을 담습니다.

**ui**
기능과 관련된 UI 컴포넌트들이 위치합니다. 슬라이스 내에서 특정 기능에 필요한 모든 UI 요소가 여기에 포함됩니다.

**model**
비즈니스 로직과 상태 관리 로직을 처리하는 세그먼트입니다. 여기에는 actions, selectors, 상태 관리와 관련된 로직이 포함됩니다.

**lib**
슬라이스 내부에서 사용되는 보조 기능을 담습니다. 유틸리티 함수나 기타 로직이 여기에 위치합니다.

**config**
슬라이스에 필요한 구성값이나 설정이 포함된 세그먼트입니다.

**consts**
슬라이스에서 사용하는 상수를 정의하는 세그먼트입니다.

---

### FSD 도입의 장점

로그인 기능을 수정해야 하지만, 프로필 기능에는 영향을 주고 싶지 않은 경우를 가정해봅시다.
```bash
src/
├── features/
│ ├── authentication/
│ │ ├── model/
│ │ │ └── useAuth.ts # 로그인 및 세션 상태 관리
│ │ ├── ui/
│ │ │ └── LoginForm.tsx # 로그인 UI 컴포넌트
│ │ └── api/
│ │ └── authAPI.ts # 인증 관련 API 호출
│ └── userProfile/
│ ├── model/
│ │ └── useUserProfile.ts # 사용자 프로필 관리 훅
│ ├── ui/
│ │ └── ProfileCard.tsx # 사용자 프로필 카드 UI
│ └── api/
│ └── profileAPI.ts # 프로필 API 호출
```
Authentication과 User Profile 기능이 분리되어 있으므로,
로그인 기능을 수정해도 프로필 기능에는 영향을 주지 않습니다.
이렇게 기능을 독립적으로 모듈화하면, 코드 변경이 다른 기능에 영향을 미치는 문제를 방지할 수 있습니다.

만약 여러 페이지에서 인증 상태를 확인하는 훅이 필요하다면,
shared 폴더에 해당 훅을 정의하고 필요한 곳에서 재사용할 수 있습니다.
```bash
src/
├── features/
│ ├── authentication/
│ │ ├── model/
│ │ │ └── useAuth.ts # 인증 상태 관리 훅
│ │ └── api/
│ │ └── authAPI.ts # 인증 관련 API 호출
│ └── dashboard/
│ ├── model/
│ │ └── useDashboardData.ts # 대시보드 데이터 훅
│ ├── ui/
│ │ └── Dashboard.tsx # 대시보드 UI 컴포넌트
│ └── api/
│ └── dashboardAPI.ts # 대시보드 API
└── shared/
└── hooks/
└── useAuth.ts # 재사용 가능한 인증 훅 (각 기능에서 import 가능)
```
이렇게 공통 모듈을 shared 폴더에 정리해 두면, 중복 코드를 줄이고 코드의 재사용성을 높일 수 있습니다.

또한, FSD는 기능별로 모듈화되어 있기 때문에, 특정 기능을 추가하거나 수정할 때 다른 기능에 영향을 미치지 않습니다.
만약 한 사람은 게시글을 개발하고, 다른 사람은 댓글 기능을 개발한다면,
```bash
src/
├── features/
│ ├── article/
│ │ ├── model/
│ │ │ └── useArticle.ts # 게시글 상태 관리 훅
│ │ ├── ui/
│ │ │ ├── ArticleCard.tsx # 게시글 카드 UI
│ │ │ └── ArticleList.tsx # 게시글 리스트 UI
│ │ └── api/
│ │ └── articleAPI.ts # 게시글 API 호출
│ └── comment/
│ ├── model/
│ │ └── useComment.ts # 댓글 상태 관리 훅
│ ├── ui/
│ │ └── CommentList.tsx # 댓글 리스트 UI
│ └── api/
│ └── commentAPI.ts # 댓글 API 호출

```
게시글 관련 기능을 수정해도 다른 사람의 댓글 기능에 영향이 가지 않습니다.
이렇게 기능을 독립적으로 모듈화하면, 협업할 때에도 코드 충돌을 방지할 수 있습니다.

---

### 도입 시 고려사항

FSD는 분명 강력한 패턴이지만, 처음 도입할 때는 몇 가지 유의해야 할 점이 있습니다.

#### **복잡성 증가**
FSD는 기능 중심으로 코드를 모듈화하다 보니, 작은 프로젝트에서는 오히려 복잡하게 느껴질 수 있습니다.
따라서 프로젝트의 규모와 복잡도를 고려하여 도입을 결정하는 것이 중요합니다.

#### **처음 설계 시 많은 고민 필요**
FSD는 기능을 기준으로 모듈화하는 패턴이기 때문에,
처음에 기능을 어떻게 분리할지, 어떤 부분을 모듈로 나눌지에 대한 많은 고민이 필요합니다.
초반 설계에 시간이 다소 소요될 수 있지만, 장기적으로는 유지보수성 면에서 이점을 제공합니다.

#### **팀원들의 이해 필요**
FSD를 도입하려면 이 패턴에 대한 팀원들의 이해가 필요합니다.
폴더 구조나 레이어링 원칙, 기능 모듈화의 장점을 충분히 이해하고 있어야 효율적으로 작업을 진행할 수 있습니다.

---

### FSD 도입을 위한 실용적인 팁

#### **작은 프로젝트부터 시작하기**
처음부터 대규모 프로젝트에 FSD를 적용하기보다는, 작은 규모의 프로젝트나 기존 프로젝트의 일부에 먼저 도입해 보는 것이 좋습니다.
이를 통해 FSD의 장단점을 파악하고, 실제로 팀에서 잘 동작하는지 실험해 볼 수 있습니다.

#### **공통 모듈을 우선적으로 정리하기**
`shared` 폴더에 공통 유틸리티와 컴포넌트를 먼저 정리해 두면, 기능 모듈을 작성할 때 유용합니다.
반복적으로 사용하는 컴포넌트와 함수는 공통 모듈로 정리하여 코드 중복을 줄일 수 있습니다.

#### **기능별 레이어링은 점진적으로 도입하기**
처음부터 모든 레이어를 엄격히 구분하지 말고, 프로젝트가 성장함에 따라 필요한 레이어를 점진적으로 추가하는 방식으로 접근하는 것이 좋습니다.
이를 통해 과도한 구조화로 프로젝트가 복잡해지는 것을 막을 수 있습니다.

---

### 마치며

Feature-Sliced Design은 규모가 커지고 복잡해지는 애플리케이션에서
기능을 독립적으로 모듈화하여 유지보수성과 확장성을 높일 수 있는 강력한 아키텍처 패턴입니다.
초기 도입 시 설계에 대한 고민이 필요하지만, 올바르게 도입되면 장기적인 유지보수와 확장에 큰 도움을 줄 수 있습니다.

프론트엔드 애플리케이션에서 **기능 중심의 모듈화**가 필요하다고 느끼신다면, FSD를 도입해 보세요.
만약 대규모 프로젝트에서 효과적으로 코드를 관리할 수 있는 방법을 찾고 있다면, FSD는 유용한 선택이 될 것입니다.

0 comments on commit cd7de0f

Please sign in to comment.