본문 바로가기
항해 플러스

항해 플러스 프론트엔드 6주차 회고(FSD: Feature-Sliced Design)

by 이의찬 2025. 8. 18.

1. 새롭게 알게 된 점 : 클린코드와 아키텍처는 도대체 왜 필요한가

회사의 시니어 개발자님이 흥미롭게 읽었다며 '소프트웨어 파괴의 미학'이라는 글을 추천해주셨었는데, 그 당시에는 그냥 니체랑 개발을 엮어두었어서 흥미롭게 읽었다. 사실 디테일한 방법론은 잘 이해 못했었다.

이번 과제를 진행하면서, FSD는 비즈니스의 복잡성으로 인해 요구사항의 변화에 따라서 코드가 계속 갈아엎어지는 부분을 해결하려고 레이어 사이를 분리해 두었던 게 아닐까? 라는 생각이 들었다.

즉, 비즈니스와 엮인 정도가 곧 외부 요구사항에 대한 변화 가능성이니, 이에 따라서 계층을 나눠 둔 것이라고 생각한다.고로 지금까지의 모든 클린코드와 아키텍처를 학습한 이유도 외부 요구사항에 대해서 유연하게 대응하기 위해서와 가독성을 높이기 위해서라는 생각이 들었다.

하지만 그 관점에서 봤을때 FSD가 최고인가? 라기에는 너무 세세하게 나누기도 했고, 분류 조건이 사람마다 다르기에 실무에서 이대로 사용하는 것은 어렵지 않을까? 라는 생각이 들기도 한다.

그렇기에 이번 챕터를 진행하면서 얻은 가장 큰 깨달음은, '결합도를 낮추면서 응집도는 높인다.'를 왜 해야하는지를 깨달은 점이라고 생각한다. 이를 위해서는 여러 방법론들이 있겠지만, 가장 중요한 원칙 하나만 꼽으라고 하면 단일 책임의 원칙으로 꼽겠다.

일단은 함수형 프로그래밍의 순수함수 분리와, FSD를 배우면서 익힌 기능 + 도메인 분리를 해야한다는 사고방식(FSD를 사용하겠다는 뜻은 아니다)만 잘 갖추고 있다면 어지간한 문제는 해결할 수 있지 않을까? 라는 자신감도 약간은 생겼다.

2. 가장 노력했던 부분 : 스스로 FSD에 대해 정의내리기

FSD는 이전에도 사용해봤지만, 그 때는 제대로 이해하지 못해서 widgets와 features, entities를 합쳐서 components로 사용했었다. 또 이번 주차의 팀별모임에서도 서로 FSD에 대한 정의에 대해서 이야기를 나누다가 결국 "FSD는 서브웨이다! 구체적인 부분은 알아서하고, 같은 레이어끼리 순환하지 못하게 하고, 하위 레이어에서 상위 레이어를 참조할 수 없도록 하는 철학만 지키면 된다!"라는 결론을 냈었다.

아주 맛있어보이는 서브웨이. 내일 점심으로 먹어야겠다.

이렇게 사람마다 FSD에 대한 의견이 달랐기에 과제를 시작하기 전에 스스로 FSD에 대해서 정의를 내리고 시작하고 싶었다. FSD 공식 홈페이지에서 제공하는 FSD의 레이어 별 단계는 다음과 같다.

src/
├── app/          # Routing, Entrypoint, Global Styles, Provider 등 앱을 실행하는 모든 요소
├── pages/        # 전체 page 또는 중첩 Routing의 핵심 영역
├── widgets/      # 독립적으로 동작하는 대형 UI·기능 블록
├── features/     # 제품 전반에서 재사용되는 비즈니스 기능
├── entities/     # user, product 같은 핵심 도메인 Entity
└── shared/       # 프로젝트 전반에서 재사용되는 일반 유틸리티

하지만 공식 홈페이지의 설명들은 명확하게 이해가 되지 않거나 혹은 와닿지 않는 부분들이 있었다. 대표적으로 공식 홈페이지에서는 read api는 entities에, 그 외인 create, update, delete api들은 features에 두기를 권장한다.

다른 분들과도 이를 주제로 많은 이야기를 나누었다. 그 과정에서 굳이 api를 나눠서 둘 이유가 있을까?와 만약 그렇다면, 다른 기능에서 같은 api를 사용한다면 중복선언을 해야하나? 등의 의문점이 생겨났고, 스스로 다음과 같이 정의를 내려보았다.

  • shared
    • 비즈니스 & 도메인과 아무런 연관이 없는, 재사용이 가능한 코드들
  • entities
    • 순수한 데이터, 즉 서버에서 가져온 데이터가 위치해야 한다고 생각한다. 이를 위해서 이것을 호출하는 api와 model 모두 이곳에 위치해야 한다고 생각한다. 물론 나만의 원칙이고, FSD 공식문서와는 다르긴 하다.
    • 원래는 비즈니스 로직도 이곳에 위치해야하지않나? 생각했지만, 데이터와 함께 두기보다는 사용자의 동작과 함께 위치하는게 더 적절해보여 features로 두는게 맞아보인다.
  • features
    • 사용자의 동작에 따라 동작하는 기능들이다. 비즈니스 로직과 그리고 tanstack query를 비롯한 hook등이 위치하는게 적절할 것이다.
  • Widgets
    • UI 덩어리다. 도메인이 섞일 수 있는 최소 단위다.
  • pages
    • 페이지.
  • app
    • 앱에 대해서 접근하는 진입점이며, 세팅과 layout, provider 등이 위치할 것이다.

3. 더 고민이 필요한 부분 : 적절한 아키텍처 선택하기

사실 FSD는 현재 나온 프론트엔드 아키텍처 중 결합도를 낮추고, 응집도를 높이기 위한 여러 아이디어가 녹아들어간 방법이라고 생각한다. 테오의 폴더구조의 변화로 이해하는 프론트엔드 멘탈모델 변천사에서 볼 수 있듯이, 프론트엔드는 여러 방법을 모색해왔다.

  • 전통적인 역할 기반 폴더 구조
  • 아토믹 디자인 패턴
  • 로직과 화면을 분리하는 컨테이너-프레젠터 패턴
  • 도메인과 비도메인 분리
  • 그리고 현재 등장중인 기능 중심 아키텍처들...

이런 역사를 통해 FSD라는 방식까지 등장했다. FSD는 기능(역할)을 중심으로 도메인별로 분리하는 방식이니 그야말로 결합도는 최대한 낮추고, 그러면서도 응집도는 높힐 수 있다.

하지만 그렇다고 FSD를 사용해야한다는 것은 아니다. 테오가 말했듯이 사람마다 생각하는 기준이 조금씩 다르다는 문제점이 너무 클 뿐더러, 설령 혼자서 개발하는 극초기 스타트업같은 환경에서도 프론트엔드에서 기능별 + 도메인별로 하나하나 쪼개고 있으면 병목현상이 엄청날테니까. 폴더구조는 말 그대로 '롤 템트리' 같은거라서 확실한 정답이 없다고 생각한다.

무지성 FSD = 무지성 여눈

결국 어떤 상황에 어떤 구조를 선택해야할까?에 대해서는 아직 막연하게 느끼는 것 같아서 스스로 아쉽다. 물론 비즈니스와도 연관이 깊은 부분이라 많은 경험이 필요한 부분이겠지만, 앞으로 프로젝트를 진행해보면서 기초적인 구조에서부터 답답함을 느끼고 스스로 확장해나가는 경험을 해보고 싶다.