들어가며
안녕하세요. KT AX플랫폼본부에서 프론트엔드 개발을 담당하고 있는 유현우입니다.
이번 주제는 (사장이지 Nx Monorepo와 MicroFrontend 도입기 ) 아티클과 이어지는 내용입니다. FSD 아키텍처를 검토하고 프로젝트에 적용하기까지의 과정을 담았습니다.
아키텍처 선택 과정
장단점 비교
1. 어떻게 해야 다수의 개발자가 일관된 구조로 코드를 생산할 수 있을까
다수의 개발 인력이 투입된 프로젝트인 만큼, 아키텍처 표준이 없을 경우 코드가 중구난방으로 작성될 위험이 있었습니다. 대표적인 리스크로는 코드 복잡성 증가와 중복 코드 생성이 있으며, 개발 인력이 많아질수록 이러한 문제는 걷잡을 수 없이 확산될 가능성이 컸습니다.
2. 폴더 구조만 봐도 프로젝트 구조를 파악할 수는 없을까
요구사항을 기준으로 프로젝트가 대규모로 확장될 것이 확실시되었기 때문에, 도메인별로 코드의 역할과 용도를 폴더 구조만 보고도 파악할 수 있어야 했습니다. 그리고 QA 기간에는 개발자가 관련 코드를 빠르게 찾을 수 있는 구조가 필요했습니다.
코드의 일관성과 구조적 명확성을 동시에 확보할 수 있고, Slices를 통해 코드 탐색 비용을 효과적으로 줄일 수 있는 FSD 아키텍처를 최종적으로 선택했습니다. 다음은 FSD(Feature-Sliced-Design) 아키텍처에 대한 설명입니다.
이미지 출처 : FSD 공식문서
Layers
| Title |
Description |
|---|---|
| app |
애플리케이션 초기화 및 전역 설정 (라우팅, 테마 등) |
| pages |
라우트 단위의 화면 구성 (여러 Widgets / Features를 조합한 최상위 UI) |
| widgets | 특정 기능 단위의 UI 및 로직 (예: User 리스트) |
| features | 재사용 가능한 독립적인 기능 단위 (예: 검색, 필터) |
| entities | 도메인 모델과 비즈니스 로직 관리 (User, Product, Order 도메인) |
| shared | 여러 곳에서 공유되는 코드 (UI 컴포넌트, 유틸리티 등) |
Slices
첨부된 그림을 예시로 들면 user, post, comment 도메인별로 구분되어 있는 것이 Slices 개념입니다. 비즈니스 도메인별로 코드를 분할합니다. 같은 레이어 안에서 다른 Slices를 참조할 수 없으며, 이는 높은 응집도와 낮은 결합도를 유지하는데 도움이 됩니다.
Segments
목적에 따라 코드를 그룹화합니다. 관례적으로 ui, api, model, lib, config 폴더가 포함됩니다.| Title | Description |
|---|---|
| ui |
UI와 관련된 모든 것: UI 컴포넌트, 날짜 포맷터, 스타일 등 |
| api |
백엔드 상호작용: request 함수, 데이터 타입, mapper 등 |
| model |
데이터 모델: 스키마, 인터페이스, 스토어, 비즈니스 로직 |
| lib |
슬라이스 안에 있는 다른 모듈이 필요로 하는 라이브러리 코드 |
| config | 설정 파일과 기능 플래그 |
실무에서 마주한 문제와 해결책
문제 ➊ : FSD 러닝커브 존재
모두가 FSD 개념을 정확히 이해하면 베스트였겠지만 끊임 없이 주어지는 요구사항으로 물리적인 학습 시간이 부족했습니다. 대부분의 프로젝트 일정이 그러하듯, 개별적인 학습 시간을 가질만한 여유가 없었습니다. 요구사항이 실시간으로 바뀌는 것도 이슈 중에 하나였는데, 특정 기능들은 어느 레이어에 배치해야 할지 결정하는 커뮤니케이션 비용이 발생했습니다.➊ 해결책 : pages, entities, shared 중심으로 레이어 간소화
2. entities: 도메인 관련된 api, type, util 등의 비즈니스 로직을 entities/{segments}에 배치
3. shared: entities, pages 에서 재사용되는 공통 코드 영역
문제 ➋ : 요구사항이 급변함에 따라 Layer가 지속적으로 변경됨
요구사항이 수정되면서 기존 화면이 사라지거나 부분적으로 변경됨에 따라 pages에서 widgets으로 이동해야 하는 상황이 빈번하게 발생했습니다. 공통화를 하더라도 이미 여러곳에서 사용하고 있었기 때문에 기존 동작을 보장하는데 리스크가 있었습니다.
➋ 해결책 : 점진적 구조 개선을 위한 코드 공통화 시간 확보
문제 ➌ : 코드 조각이 나뉘어져 데이터 흐름 파악이 어려움
➌ 해결책 : GET API 호출 가능한 레이어 제한 (pages, widgets, features)
사장이지 FSD 최종 형상
화면 1. 창업 상권분석 (pages, widgets)
- pages: 창업 상권분석 화면의 최상위 레이어로, 총 3개의 widgets을 import 하고 있습니다.
- widgets: 상단 필터와 탭 전환에 따라 전환되는 주요 콘텐츠로 구성됩니다.
화면 2. 하이오더 매장통계 (pages, widgets, features)
- pages: 하이오더 매장통계 화면의 최상위 레이어로, 총 2개의 widgets을 import 하고 있습니다.
- widgets: 탭 전환에 따라 전환되는 주요 콘텐츠로 구성되고, (시간 별, 결제 수단 별, 상품 별) 탭을 포함해서 총 6개의 features를 import 하고 있습니다.
- features: 매장 통계 페이지에서 GET API를 호출하는 최소 단위 레이어입니다.
폴더 구조
사장이지에 적용된 폴더 구조와 실제 화면에서의 FSD를 알아보았습니다.
이를 통해 레이어 간 역할 분리와 데이터 흐름이 실제 화면에서 어떻게 반영되는지 확인할 수 있었습니다.
AI 생성툴과 FSD 활용법
이번 장에서는 AI 생성툴과 FSD 아키텍처의 시너지를 알아보겠습니다. Cursor, Figma MCP를 활용하여 FSD 도입 전후를 비교했습니다. 두 케이스 모두 결과는 같았지만, 폴더 구조에는 차이가 있었습니다.
FSD 도입 전
Figma MCP를 활용하여 코드가 생성되었습니다. 브라우저에서 UI를 확인했을 때 별 문제가 없었지만, 개발자가 생성된 코드를 한 눈에 파악하기란 쉽지 않았습니다. 대표적으로 2가지 단점이 확인됐습니다.
물론 개발자 자체적으로 AI 코드를 하나씩 확인하는 것도 방법이지만, 시간이 많이 소요되는 작업이었고 이후에도 일관된 구조를 유지하기 어렵다는 한계가 있었습니다. 다음은 단점을 커버한 FSD 도입 후의 AI 코드 생성 결과입니다.
FSD 도입 후
브라우저에서 확인한 결과는 FSD 도입 전의 왼쪽 이미지와 동일했습니다. 미리 정의된 팀 내 README(FSD 가이드)를 AI 생성툴이 참조하도록 설정했습니다. FSD 구조를 접합했을 때 다음과 같은 장점이 있었습니다.
결론적으로, FSD 활용으로 AI 생성툴의 코드 생성에 일관성이 더해졌습니다.
마무리
물론 아키텍처를 한 번에 완성하기는 쉽지 않았습니다. 실제로는 팀 상황과 요구사항에 맞게 계속해서 조정하고 개선해 나가는 과정이 필요했습니다. 결국 좋은 아키텍처란 한 번에 정의되는 것이 아니라, 팀과 함께 점진적으로 발전해 나가는 구조라고 생각합니다.
🔥 공동 기여자들: P-Web개발부서 (백지경, 김남일, 박지원, 김수현)