FSD 아키텍처 적용기 : "이 코드는 어디에 넣어야 할까?" FSD가 답해준 코드 위치의 명확성

FSD 아키텍처 적용기 : "이 코드는 어디에 넣어야 할까?" FSD가 답해준 코드 위치의 명확성

요약: 레포지토리의 복잡한 구조적 문제를 해결하기 위해 FSD(Feature-Sliced Design) 아키텍처를 도입한 경험과 그 과정에서 했던 고민들을 공유합니다.

💡 리뷰어 한줄평

pebble.stone 아키텍처에 정답은 없지만, 팀이 직면한 pain point를 명확히 진단하고 FSD를 도입하여 ‘지속 가능한 서비스 구조’를 구축해 나가는 과정이 인상적입니다.

teemo.c 프로젝트 규모가 커지며 구조적 복잡도나 사이드 이펙트로 고민 중이라면, 마쉬의 실전 경험이 담긴 FSD 적용 사례를 통해 명확한 방향성을 얻을 수 있을 거예요.

시작하며

안녕하세요. 카카오페이에서 FE 개발을 하고 있는 마쉬입니다.

혹시 새로운 기능을 추가하거나 코드를 수정할 때마다 이 코드는 도대체 어디에 넣어야 할지, 그리고 복잡하게 얽힌 의존성은 어떻게 풀어야 할지 고민해 본 적 있으신가요? 프로젝트 규모가 커질수록 명확한 구조가 없으면 개발자를 괴롭히는 이 구조적인 한계를 해결하기 위해, FSD(Feature-Sliced Design) 아키텍처를 도입했습니다.

이번 글에서는 기존 프로젝트의 구조적 한계를 극복하고 확장성 및 유지보수성을 높이기 위해 FSD 아키텍처를 도입하고 적용한 경험을 공유합니다. FSD 아키텍처의 개념과 장단점 설명부터 FSD 아키텍처를 적용하게 된 배경, 적용 과정 그리고 최종 적용된 구조를 상세하게 다룹니다.

이 글이 코드 위치의 명확성과 구조적 안정성을 고민하고 있는 분들에게 실질적 도움이 되는 참고 자료가 되었으면 좋겠습니다.

FSD 아키텍처란?

공식문서에 따르면 FSD 아키텍처는 Feature-Sliced Design(기능 분할 설계) 의 약자로, 프론트엔드 애플리케이션 구조를 위한 아키텍처 방법론입니다. 이 설계 방법론은 컴포넌트 중심의 UI 환경에서 복잡한 사용자 인터페이스 애플리케이션 구조를 체계적으로 조직합니다. 또한 초기 버전의 단점을 계속해서 보완해 나가고 있는 살아있는 아키텍처 방법론입니다.

FSD 아키텍처
FSD 아키텍처

이미지 출처 : FSD 공식문서

FSD 아키텍처의 핵심은 코드를 3가지 차원으로 분리하여 재사용 가능한 로직을 통제하고, 높은 응집도와 낮은 결합도를 유지하는 데 있습니다. 3가지 차원은 수직적인 레이어(Layers), 수평적인 슬라이스(Slices), 그리고 기술적 목적에 따른 세그먼트(Segments) 로 나누어 관리하는 것 입니다.

FSD의 핵심 개념

구분역할특징 및 규칙
레이어 (Layers)코드를 재사용의 범위와 의존성(import) 규칙에 따라 수직적으로 나누어 놓은 계층 구조상위 레이어는 하위 레이어를 참조할 수 있는 단방향 의존성을 가집니다. (app > pages > widgets > features > entities > shared)
슬라이스 (Slices)레이어 내에서 코드를 비즈니스 도메인별로 분할같은 레이어 안에서는 다른 슬라이스를 참조할 수 없습니다. (높은 응집도, 낮은 결합도 유지에 도움)
세그먼트 (Segments)슬라이스 내에서 코드를 기술적 목적에 따라 구분이름은 ui, api, model 등 목적을 설명해야 합니다. (components, hooks 같은 성격은 지양).

1️⃣ Layers?

레이어는 FSD 아키텍처에서 코드를 구분하는 가장 큰 범위 이며, 각 부분이 어떤 기능을 담당하는지, 다른 코드에 얼마나 의존하는지를 기준으로 합니다. 프로젝트마다 모든 레이어가 사용될 필요는 없고, 필요한 레이어만 추가하여 사용할 수 있습니다.

구분설명특이사항
App앱 전체 에 영향을 주는 코드 ( 라우터 설정, 진입점 설정, 전역 상태관리, 전역 스타일, 프로바이더 )slice 없이 segment 로만 구성됨
Processes페이지 간 복잡한 시나리오더 이상 사용되지 않음
Pages전체 페이지 또는 중첩 라우팅에서 페이지의 주요 부분대부분 페이지 1개는 슬라이스 1개 (단, 유사한 페이지는 하나의 슬라이스로 묶기 가능)
Widgets독립적으로 작동하고 여러 페이지에서 재사용되는 대규모 기능 또는 UI 컴포넌트 . 보통 하나의 완전한 기능
Features제품 전반에 걸쳐 재사용되는 기능 구현체로, 사용자에게 실질적인 비즈니스 가치를 제공하는 동작 ( 동사적 개념 )
Entities프로젝트가 다루는 비즈니스 데이터 ( 명사적 개념 )
Shared앱의 기본 구성 요소 를 모아둠. 재사용 가능한 기능, 특히 프로젝트/비즈니스의 특성과 분리되어 있을 때 (반드시 그럴 필요는 없음)slice 없이 segment 로만 구성됨

레이어는 위에서 아래로의 단방향 의존성을 가진다는 특징이 있습니다. 예를 들어 ~/features/benefit/ui/A.tsx~/shared/ui/B.tsx 를 import 하여 사용할 수 있지만, ~/shared/ui/B.tsx~/features/benefit/ui/A.tsx 를 import 하여 사용할 수 없습니다.

2️⃣ Slices?

슬라이스는 FSD 아키텍처에서 2번째 계층이며, 레이어 내에서 코드를 비즈니스 도메인별로 분할하는 역할 을 합니다. 슬라이스의 이름은 표준화 되어있지 않고, 애플리케이션의 비즈니스 도메인에 따라 결정됩니다. 슬라이스 내부는 팀이 원하는 방식대로 자유롭게 구성할 수 있습니다. 연관성이 높은 슬라이스는 그룹핑하여 관리할 수도 있습니다.

같은 레이어 안에서 다른 슬라이스를 참조할 수 없습니다. 이러한 특징이 높은 응집도와 낮은 결합도를 유지하는 데 도움이 됩니다.

왜 높은 응집도와 낮은 결합도를 유지할 수 있을까?

응집도가 높다는 것은 관련 기능이 함께 모여 있다는 의미 입니다. FSD 아키텍처에서는 도메인의 코드들이 슬라이스별로 모여 있도록 자연스럽게 구성됩니다.

결합도가 낮다는 것은 서로 다른 부분이 독립적으로 작동할 수 있다는 의미입니다. FSD 아키텍처에서는 같은 레이어 내에서 다른 슬라이스를 참조할 수 없기 때문에, 각 슬라이스는 독립적으로 기능을 수행할 수 있습니다.

결과적으로 각 슬라이스는 자신의 역할에만 온전히 집중 할 수 있고 동시에 다른 슬라이스와의 의존성이 줄어 , 응집도는 높아지고 결합도가 낮아집니다.

3️⃣ Segments?

세그먼트는 FSD 아키텍처에서 마지막 계층이며, 코드 내에서 기술적 목적에 따라 구분합니다. 중요한 원칙은 세그먼트 이름은 components, hooks 처럼 코드의 성격이 아닌, 코드의 목적을 설명해야 합니다. (예: components 대신 ui)

관례적으로 사용하는 네이밍은 아래와 같습니다.

네이밍설명예시
uiUI와 관련된 모든 것UI 컴포넌트, 날짜 포맷터, 스타일 등
api백엔드 통신 및 데이터 로직request 함수, 데이터 타입, mapper 등
model애플리케이션 도메인 모델스키마, 인터페이스, 스토어, 비즈니스 로직 (Redux/Zustand의 액션, 리듀서, 셀렉터 등)
lib슬라이스 내에서만 사용하는 라이브러리 코드
config설정 파일과 feature-flag 파일

세그먼트가 위치하는 레이어마다 활용하는 방식은 조금 달라집니다.

✔️ ui 세그먼트

레이어설명
Pages재사용되지 않는 UI, 로딩 상태, 에러 처리 컴포넌트들을 관리
Widgets여러 페이지에서 재사용하는 독립적으로 동작하는 큰 UI 컴포넌트들을 관리
FeaturesForm 등 상호작용이 가능한 UI 컴포넌트들을 관리
Entities여러 페이지에서 재사용 가능한 특정 도메인과 관련된 UI 컴포넌트들을 관리
Shared비즈니스 로직을 제외한 공통 UI 컴포넌트들

✔️ api 세그먼트

레이어설명
Pages데이터 조회/변경 API 요청
Features기능 관련 API 요청
Entities해당 Entity의 API 요청
SharedAPI 요청에 사용되는 공통 코드

✔️ model

레이어설명
Features검증, 내부 상태
Entities데이터 상태와 검증 스키마

✔️ config 세그먼트

레이어설명
Featuresfeature flag
Shared환경변수, 전역 feature flag 등

FSD 의 전체 구조

지금까지 알아본 FSD 아키텍처의 전체 구조를 나열하면 아래와 같습니다.

└─ src
  ├─ app
  │	├─ routes
  │	├─ store
  │	├─ styles
  │	├─ entrypoint
  │	└─ ...
  ├─ pages
  │	├─ benefitList
  │	│	├─ ui
  │	│	├─ api
  │	│	└─ ...
  │	├─ benefitDetail
  │	│	└─ ...
  │	└─ ...
  ├─ widgets
  │	├─ benefitItem
  │	│	├─ ui
  │	│	└─ ...
  │	└─ ...
  ├─ features
  │	├─ benefit
  │	│	├─ config
  │	│	├─ model
  │	│	├─ api
  │	│	├─ ui
  │	│	└─ ...
  │	├─ coupon
  │	│	├─ config
  │	│	├─ model
  │	│	├─ api
  │	│	├─ ui
  │	│	└─ ...
  │	└─ ...
  ├─ entities
  │	├─ benefit
  │	│	├─ model
  │	│	├─ api
  │	│	├─ ui
  │	│	└─ ...
  │	├─ coupon
  │	│	├─ model
  │	│	├─ api
  │	│	├─ ui
  │	│	└─...
  │	└─ ...
  └─ shared
  	├─ api
  	├─ ui
  	├─ lib
  	├─ config
  	├─ routes
  	├─ i18n
  	└─ ...

FSD의 장단점: 일관성, 확장성, 유지보수성 vs 학습 비용

FSD 아키텍처 장점은 크게 세 가지입니다.

  • 첫째, 구조가 명확하여, 팀 간 협업 및 신규 작업자 온보딩이 용이합니다.
  • 둘째, 추가 기능 작업시 사이드 이펙트 발생 확률이 줄어듭니다. 이는 레이어와 슬라이스로 코드가 구분 되어있기 때문입니다.
  • 셋째, 유지보수성이 향상됩니다. 재사용 가능한 코드 레벨과 지역적으로만 사용하는 코드 레벨을 레이어에 따라 구분할 수 있습니다.

단점을 꼽자면 모든 작업자가 FSD 아키텍처에 대해 학습이 필요하다는 점입니다.

그럼에도 장기적인 관점에서 FSD 아키텍처를 선택하는 것이 코드베이스의 일관성, 확장성, 그리고 유지보수성을 크게 향상시키는 중요한 결정이 될 수 있습니다.

FSD를 선택한 이유 : 복잡한 구조에서 명확성으로

기존에 관리하던 사장님 플러스 레포지토리(이하, ceo-plus 라 칭함)는 초기에는 웹뷰 내 단일 페이지들만 제공하는 구조였으며, 역할 중심으로 디렉토리가 묶여 있었습니다.

초기 구조

└─ src
  ├─ components
  ├─ apis
  ├─ pages
  ├─ configs
  ├─ mocks
  ├─ constants
  ├─ errors
  ├─ helpers
  ├─ hooks
  ├─ styles
  ├─ types
  └─ ...

서비스 확장

서비스가 확장되고 혜택, 쿠폰, 멤버십, 매장 소식 등 다양한 feature가 추가 되었습니다.

└─ src
  ├─ components
  │	├─ benefit
  │	├─ coupon
  │	├─ membership
  │	├─ common
  │	└─ ...
  ├─ apis
  │	├─ benefit
  │	├─ coupon
  │	├─ membership
  │	├─ common
  │	└─ ...
  ├─ pages
  │	├─ benefit
  │	├─ coupon
  │	├─ membership
  │	└─ ...
  ├─ configs
  ├─ mocks
  ├─ constants
  ├─ errors
  ├─ helpers
  ├─ hooks
  ├─ styles
  ├─ types
  └─ ...

직면한 문제: 개발 생산성과 시스템 안정성 저하

기존 구조에서 위와 같은 방식으로 구조가 변경되면서 발생한 문제는 아래와 같습니다.

1. 개발 생산성 저하 및 탐색 비용 증가
첫 번째로 개발 생산성이 떨어졌습니다. 기존 구조 내에 기능별 그룹핑 디렉토리가 추가되고 공통 컴포넌트나 API의 위치가 모호해지면서, 개발자는 특정 코드가 어디에 위치하는지 즉각적으로 파악하기 어려웠습니다. 코드를 수정해야 할 때마다 관련된 여러 파일을 탐색해야 하는 불필요한 시간 낭비가 발생했습니다. 또한 신규 작업자마다 구조를 다르게 이해하여 pages/***/components 와 같이 비일관적인 구조도 발생했습니다. 이는 추가 기능 개발 및 기존 로직 수정 시에 다시 새로운 규칙을 정해야 하거나 기존 규칙을 파악하는데 드는 의사결정 비용을 증가시켜, 전반적인 개발 속도와 효율성이 크게 떨어지는 결과를 낳았습니다.

2. 시스템 안정성 저하 및 기존 작업자 의존 심화
두 번째로, 점차 시스템 안정성이 우려되며 기존 작업자에게 의존하는 경향이 생겼습니다. 기능이나 공통 로직이 뒤섞여 위치한 구조 때문에, 특정 컴포넌트나 로직을 수정했을 때 예상치 못한 다른 화면이나 기능까지 수정이 필요한 상황이 있었습니다. 이는 모듈 간의 경계가 불분명했기 때문에 코드 수정의 영향 범위를 예측하기 어려워진 상황을 의미합니다. 결과적으로, 코드 변경에 대한 부담감이 커지고 시스템의 안정성이 전반적으로 저하되었으며, 기존 로직을 잘 아는 작업자에게 의존하는 경향이 심화되었습니다.

FSD를 선택한 이유

FSD 아키텍처를 선택하기 전에 FDD(Feature-Driven Development) 구조로 리팩토링을 시도 했으나 ceo-plus 에 맞는 구조는 아니라는 결론 을 내렸습니다.

왜냐하면 ceo-plus 에는 여러 feature에서 사용되지만 또 범용적으로 사용되지는 않는 ui, API, hooks, helper 함수, types 등이 너무 많이 존재했고, 이를 sharedcommon 에 넣을 경우 재사용 범위를 통제하지 못해 코드의 의존성이 다시 엉킬 위험 이 있었습니다. ceo-plus 는 여러 feature가 제공되는 환경에 있었고, 하나의 서비스 수정 시 다른 서비스에 영향을 끼치지 않도록 구조상 분리하고 싶었기 때문입니다.

다른 아키텍처는 없는지 찾던 도중, 접하게 된 FSD 아키텍처 공식문서에서 아래의 문구를 읽게 되었습니다. 아래 글은 프로젝트 구조에 대해 고민하고 있던 그 당시 저에게 굉장히 매력적인 문구였습니다.

현재 구조가 문제가 없다면 반드시 바꿀 필요가 없습니다. 다만 아래와 같은 상황이라면 도입을 고려해보세요:

  • 프로젝트가 커지면서 구조가 얽히고, 기능 개발 속도가 느려졌을 때
  • 새로운 팀원이 구조를 이해하기 어려운 상황일 때

결과적으로, 아래 두 가지 이유로 FSD 아키텍처가 ceo-plus 프로젝트 구조와 가장 잘 맞는다고 생각하였습니다.

  • 레이어와 슬라이스 개념을 통해 코드의 재사용 레벨과 지역적 사용 레벨을 명확히 구분할 수 있습니다.
  • 코드 레벨에서 구조적 분리를 가능하게 합니다.

FSD 적용 과정

FSD 아키텍처는 마이그레이션 문서를 제공하고 있습니다. FSD 아키텍처의 공식 마이그레이션 가이드를 따랐으며, 기본적인 1단계부터 4단계 과정은 생략하고 프로젝트 특성상 추가적인 고민이 필요했던 부분에 대해 중점적으로 소개하겠습니다.

FSD 아키텍처 작업 전 코드 구조는 아래와 같습니다.

└─ src
  ├─ benefit
  │	├─ components
  │	├─ apis
  │	├─ pages
  │	├─ helpers
  │	└─ ...
  ├─ coupon
  │	├─ components
  │	├─ apis
  │	├─ pages
  │	├─ helpers
  │	└─ ...
  ├─ membership
  │	├─ components
  │	├─ apis
  │	├─ pages
  │	├─ helpers
  │	└─ ...
  ├─ shared
  │	├─ components
  │	├─ apis
  │	├─ pages
  │	├─ helpers
  │	└─ ...
  ├─ configs
  ├─ mocks
  ├─ constants
  ├─ errors
  ├─ helpers
  ├─ hooks
  ├─ styles
  ├─ types
  └─ ...

적용 과정에서 기존 ceo-plus 의 특성을 고려하여 다음과 같은 사항을 결정했습니다.

1. widgets 의 사용 여부

ceo-plus 프로젝트에서는 FSD 아키텍처의 유연성을 활용하여, widgets 레이어는 사용하지 않기로 결정했습니다.

FSD 아키텍처는 프로젝트별로 필요한 레이어만 선택적으로 사용할 수 있으며, ceo-plus 의 경우 재사용되는 독립적인 UI 컴포넌트의 비중이 낮고, 대부분의 컴포넌트가 특정 페이지에 한정되어 사용되었습니다. 일부 재사용이 필요한 컴포넌트들 역시 features 레이어 내에서 충분히 효율적으로 관리 가능했기 때문에, 독립적인 widgets 레이어는 추가하지 않았습니다.

결과적으로, ceo-plus재사용 가능한 UI 컴포넌트는 features 레이어 내에만 배치하여, features 레이어가 담당하는 기능 단위 안에서 UI 컴포넌트까지 통합 관리하는 방식으로 아키텍처를 구성했습니다.

2. Slice Grouping 허용 및 Pages 레이어 구성

ceo-plus 서비스는 동일 도메인의 다양한 페이지가 제공 되고 있어, 페이지별로 Slice를 두면 너무 많은 Slice가 생기는 문제가 있었습니다. 혜택 도메인만 보아도 목록, 상세, 등록, 수정, …등의 페이지가 존재하여 너무 많은 slice 가 생성되고, 이는 결국 빠른 작업 속도를 저해할 수 있다고 판단했습니다. FSD 아키텍처 가이드에 따르면 하나의 페이지는 하나의 Slice에 속해야 하는 것을 권장하지만, 동일한 도메인 데이터를 다루는 페이지는 하나의 Slice에 속해 있을 수 있다고 했습니다.

결론적으로 동일한 도메인 데이터를 다루는 페이지들을 묶는 Slice Grouping을 허용하고, 레이어 사이의 Import Rule를 지키는 것으로 합의했습니다.

Slice Grouping 허용 전

└─ src
  ├─ ...
  ├─ pages ( layer )
  │	├─ benefitCreate ( slice )
  │	│	└─ ... ( segments )
  │	├─ benefitDetail ( slice )
  │	│	└─ ... ( segments )
  │	├─ benefitList ( slice )
  │	│	└─ ... ( segments )
  │	├─ couponCreate ( slice )
  │	│	└─ ... ( segments )
  │	├─ couponDetail ( slice )
  │	│	└─ ... ( segments )
  │	├─ couponList ( slice )
  │	│	└─ ... ( segments )
  │	└─ ... ( slice )
  └─ ... ( layers )

Slice Grouping 허용 후

└─ src
  ├─ ...
  ├─ pages ( layer )
  │	├─ benefit ( slice group )
  │	│	├─ benefitCreate ( slice )
  │	│	│	└─ ... ( segments )
  │	│	├─ benefitDetail ( slice )
  │	│	│	└─ ... ( segments )
  │	│	├─ benefitList ( slice )
  │	│	│	└─ ... ( segments )
  │	│	└─ ...
  │	├─ coupon ( slice group )
  │	│	├─ couponCreate ( slice )
  │	│	│	└─ ... ( segments )
  │	│	├─ couponDetail ( slice )
  │	│	│	└─ ... ( segments )
  │	│	├─ couponList ( slice )
  │	│	│	└─ ... ( segments )
  │	│	└─ ...
  │	└─ ... ( slice groups )
  └─ ... ( layers )

3. pages/[slice]/api vs features/[slice]/api vs entities/[domain]/api

API 코드를 어디에 배치해야 할지에 대한 난관에도 봉착했습니다.

초기에는 단순하게 모든 API 관련 코드를 Entities 레이어에 몰아넣으려는 시도를 했으나, 곧바로 문제가 발생했습니다. 특정 페이지에서만 필요한 단순 조회 API까지 전역 Entity에 섞이면서 Entity 레이어가 비대해지고 진정한 '도메인 엔티티'의 역할을 수행하기 어려워졌기 때문입니다.

이 시행착오를 통해 아래와 같은 기준에 따라 API가 어떤 도메인/범위에서 재사용되는지에 따라 위치를 명확히 구분했습니다.

  • 페이지 내 슬라이스에서만 사용하는 API : API가 다른 페이지에서 사용되지 않는다면, pages/[slice]/api 하위에 존재합니다.
    • ex) pages/benefit/benefitList/api : BenefitList 슬라이스에서만 사용하는 혜택 목록 조회 API.
  • 페이지 슬라이스 그룹 내 다른 슬라이스에서 재사용하는 API (기능 관련) : features/[slice]/api 하위에 존재합니다. Features는 slice group 단위로 결정했습니다.
    • ex) features/benefit/api : benefit 기능 내의 혜택 상세 조회 API (BenefitDetail, BenefitUpdate 슬라이스에서 사용)
  • 여러 페이지 슬라이스 그룹에서 재사용하는 API (데이터 관련) : entities/[domain]/api 하위에 존재합니다. Entities는 DB 개념의 도메인으로 결정했습니다.
    • ex) entities/partner/api : partner 도메인의 매장 상세 조회 API. (여러 페이지의 슬라이스 그룹에서 사용)
└─ src
  ├─ ...
  ├─ pages ( layer )
  │	├─ benefit ( slice group )
  │	│	├─ benefitCreate ( slice )
  │	│	│	├─ api : pages/benefit/benefitCreate 하위에서만 사용하는 API 들 위치
  │	│	│	└─ ...
  │	│	├─ benefitDetail ( slice )
  │	│	│	└─ ...
  │	│	└─ ...
  │	└─ ...
  ├─ features ( layer )
  │	├─ benefit ( slice )
  │	│	├─ api : pages/benefit 하위에서만 사용하는 API 들 위치
  │	│	└─ ...
  │	└─ ...
  ├─ entities ( layer )
  │	├─ partner ( slice )
  │	│	├─ api : 여러 pages 에서 사용하는 API 들 위치
  │	│	└─ ...
  │	└─ ...
  └─ ...

4. 상향식 (Bottom-Up) 방식 채택

FSD 아키텍처는 점진적 도입이 가능하다는 장점이 있습니다. 기존 코드베이스를 한 번에 전환하는 것은 높은 리스크와 많은 리소스를 요구하는 작업이기 때문에, 이러한 장점은 운영 중인 서비스에 FSD를 적용하는 데 최적의 특징이었습니다.

기존 코드를 FSD 아키텍처에 맞춰 재배치하는 과정은 다음과 같은 단계적 순서로 진행했습니다.

  1. 우선 pages 하위에 모두 작업을 진행합니다.
  2. 여러 pages/[slice-group]/slice 에서 사용하는 코드가 생기면 features/[slice-group] 하위로 이동합니다.
  3. 여러 features/[slice-group] 에서 사용하는 코드가 생기면 entities/domain 하위로 이동합니다.
  4. 전역에서 사용하는 코드는 shared 하위에 위치합니다.

이러한 단계적 이동 규칙을 통해, 이후 추가 작업 시 팀원들이 코드를 어디에 둘지 고민할 때마다 ‘이 코드가 현재 어느 레이어까지 재사용되는가?’ 라는 질문을 스스로 던지게 되었고, FSD의 레이어별 의존성 흐름(pages > features > entities > shared)을 자연스럽게 체득할 수 있었습니다.

FSD 적용 후기

FSD 아키텍처 적용 후, ceo-plus 는 다음과 같은 효과를 얻었습니다.

  • 명확한 코드 위치 파악 :
    • pages 하위 코드는 “아, 특정 pages/slice-group/slice 에서만 사용하는 구나!”
    • features 하위 코드는 “아. 특정 pages/slice-group 에서만 사용하는 구나!”
    • entities 하위 코드는 “아. 여러 pages/slice-group 에서 사용하는 구나!”
    • shared 하위 코드는 “아, 전역에서 사용되는 구나!”
  • 재사용 통제 : 레이어 규칙에 의해 잘못된 의존성(상위 레이어가 하위 레이어를 참조하는)을 사전에 방지할 수 있게 되었습니다.
  • 비즈니스 도메인 명확화 : 슬라이스 기준으로 코드가 묶이면서, 코드의 역할과 비즈니스 도메인을 한눈에 파악하기 쉬워졌습니다.
  • 개발 생산성 향상 : 코드를 어디에 배치할지 고민하는 시간이 사라져 신규 기능 개발 착수 속도가 눈에 띄게 빨라졌습니다.
  • 리팩토링 및 테스트 용이성 : 슬라이스 내의 높은 응집도로 인해, 특정 기능을 수정하거나 리팩토링할 때 잠재적인 영향 범위를 쉽게 예측할 수 있어 테스트 및 배포 안정성이 높아졌습니다.

마치며

FSD 아키텍처 도입은 모든 작업자들의 학습이 필요하다는 부담이 있었지만, 점진적 도입이 가능하고 장기적인 관점에서 코드베이스의 일관성, 확장성, 그리고 유지보수성을 크게 향상시키는 중요한 결정 이었습니다. FSD 아키텍처를 통해 우리는 확장 가능한 서비스 구조를 구축했고, 이는 곧 개발 생산성을 높이는 핵심 동력이 되었습니다.

개인적으로는 ceo-plus 프로젝트 구조가 점점 복잡해지고 뒤얽혀 갈 때마다 어떤 방식으로 구조를 분리하고 개선해야 할지 고민에 빠졌었습니다. 코드를 수정할 때마다 혹시나 발생할 사이드 이펙트를 걱정해야 했고, 그럴 때마다 개발자로서 느끼는 피로감은 상당했습니다. FSD 아키텍처는 바로 이러한 구조적 복잡성 문제에 대한 명확한 해답 을 제시해주었습니다. 코드가 있어야 할 위치를 정확히 지정해주고, 잘못된 의존성을 사전에 차단할 수 있었습니다.

오랜만에 아키텍처라는 근본적인 주제를 깊이 있게 공부해볼 수 있었고, 이를 실제 서비스에 적용해보며 큰 만족감을 느꼈습니다. FSD 아키텍처는 단순히 코드를 나누는 규칙을 넘어, 개발자에게 '이 코드는 어디에 넣어야 할까?'라는 근원적인 질문에 대한 확신을 안겨준 전략적 도구 였습니다.

저의 경험을 바탕으로, 구조적 문제로 고민하는 다른 개발팀에도 FSD 아키텍처 도입을 적극적으로 추천하며, 이 글을 마치도록 하겠습니다.

긴 글 읽어주셔서 감사합니다.

marsh.mallow
marsh.mallow

카카오페이 비즈니스 및 결제 서비스 FE 개발을 하고 있는 마쉬입니다. 다양한 서비스 개발을 경험해보고 싶습니다.

태그