본문 바로가기
source-code/FrontEnd

Feature-Sliced Design(FSD) 도입기

by mattew4483 2024. 8. 3.
728x90
반응형

최근 사내 core-package의 FE 파트 폴더 아키텍처에 Feature-Sliced Design(FSD)를 도입했습니다.

 

해당 FE 서비스는 1) 전통적인 React 폴더 구조 → 2) 클린 아키텍처(헥사고날 아키텍처) → 3) FSD 

지금까지 이렇게 총 3번의 구조 변경을 겪었으며, 각 단계에서 느꼈던 문제점과 해결 방안을 공유하고자 합니다.

 

1. 전통적 폴더 구조

처음 프로젝트를 구성할 당시, 가장 일반적이고 전통적인 폴더 구조 형태를 따랐습니다.

src/
├── api/
│   ├── userApi.ts
│   └── productApi.ts
├── components/
│   ├── Header.tsx
│   ├── Footer.tsx
│   ├── UserProfile.tsx
│   └── ProductList.tsx
├── hooks/
│   ├── useFetchUser.ts
│   └── useFetchProducts.ts
├── utils/
│   ├── formatDate.ts
│   └── calculateDiscount.ts
├── App.tsx
├── index.tsx
└── styles/
    ├── global.css
    └── userStyles.css

공식문서를 포함한, 대부분 프로젝트 예시에서 위와 같은 폴더 구조를 따르고 있죠.

특정 모듈을 추가할 때 아무런 고민할 필요가 없다는 단점이자 장점을 갖고 있습니다.

(컴포넌트면 components에, react hook이면 hooks에, HTTP 요청을 하면 api 폴더에...)

문제점

위와 같은 구조는 프로젝트 규모가 커질수록 모듈 간 응집도가 저하되고, 불필요한 결합도가 증가한다는 문제를 갖고 있습니다.

응집도 저하

전통적인 폴더 구조에서는 특정 기능과 관련된 여러 파일들이 각기 다른 폴더에 분산되어 있습니다.

예를 들어, 단순한 메시지 전송 버튼을 구현하고자 해도...

메시지 버튼 자체는 components에, 관련 상태 제어 로직은 hooks에, 서버에 메시지를 저장하는 함수를 api에 나눠지고 말죠.

 

이렇게 코드의 응집도가 저하하면서,

맥락 이해가 어렵고 특정 기능을 수정하거나 찾기 위해 여러 폴더를 탐색해야 하는 불편함이 생겨났습니다.

결합도 증가

또한, 불필요한 결합도가 점차 증가할 수 밖에 없습니다. 왜일까요?

이유는 간단합니다. 의존성 방향이라는 개념이 존재하지 않기 때문이죠.

 

모든 폴더가 서로간에 의존할 수 있으며

이로 인해 의도치 않은 순환 참조가 발생하거나, 코드 수정으로 인한 사이드 이팩트가 예상치 못한 곳까지 전파되고 말았습니다.

전통적 폴더 구조에서 겪은 문제점
1. 응집도 저하
2. 결합도 증가

 

2. 클린 아키텍처(헥사고날 패턴)

이를 해결하기 위해, C.마틴이 제안한 클린 아키텍처 개념을 적용했습니다.

2024.06.10 - [source-code/FrontEnd] - 내가 프론트엔드에 클린 아키텍처를 도입한 이유

 

내가 프론트엔드에 클린 아키텍처를 도입한 이유

Backgrounds정부 지원사업 과제 프론트엔드 파트 총괄을 맡게 되면서,기존 서비스들을 개발하며 느낀 문제점들을 더는 답습하지 않겠다 라는 자그마한 목표를 세웠습니다. Existing Problems제가 느꼈

23life.tistory.com

그중 포트와 어댑터 패턴으로도 불리는, 헥사고날 아키텍처를 적용했죠.

 

해당 아키텍처의 가장 큰 목적은

애플리케이션의 핵심 비즈니스 로직을 외부의 다양한 인터페이스(입출력, 데이터베이스, 웹 등)로부터 분리하는 것입니다.

애플리케이션 영역(domain, application)과 외부 인프라(Infrastructure)로 각 요소들을 분리하며,

각 레어어는 상위 레이어에만 의존한다!라는 명확한 의존성 방향을 제한하기 때문에핵심 비즈니스 로직에 대한 결합도가 현저하게 줄어드는 장점을 취할 수 있었습니다.

헥사고날 아키텍처 장점
1. 비즈니스 로직 결합도 저하
2. 애플리케이션 영역에 대한 테스트 코드 작성 용이. 정말 정말 용이.

문제점

하지만, 이 역시 FE 프로젝트에 곧바로 적용하기에는 적절하지 않은 부분이 있었습니다.

UI와 비즈니스 로직의 불필요한 분리

헥사고날 아키텍처에서는, 도메인과 애플리케이션 수준에서는 어떠한 외부 종속성도 가질 수 없습니다.

즉... UI 조차 말이죠!

하지만 FE에서, UI와 분리된 로직은 오히려 불필요한 응집도 저하를 야기하고 말았습니다.

구성 방식의 불명확성

비즈니스 로직 이외의 로직이 모두 외부 인프라에 작성되는데

이때 해당 외부 인프라에 대한 구성 방식이 명확하지 않아,

특정 기능을 추가할 때 “어디에 어떤 로직을 넣어야 하는지” 고민하는 시간이 점점 늘어났습니다.

헥사고날 아키텍처에서 겪은 문제점
1. 여전한 응집도 저하
2. 구성 방식의 불명확성으로 인한, 설계 소요 시간 증대

 

3. Feature-Sliced Design(FSD)

FSD는 위에서 언급한 문제들을 해결할 수 있는 효과적인 방법을 제시합니다.

https://feature-sliced.design/docs

 

Documentation | Feature-Sliced Design

feature-sliced-banner

feature-sliced.design

기능 중심 구조

FSD는 폴더 구조를 기능 단위로 나누어, 관련된 모든 파일이 한 곳에 모이도록 합니다.

이를 통해 코드의 응집도를 높이고, 특정 기능을 수정하거나 찾는 데 걸리는 시간을 줄입니다

명확한 의존성 방향

FSD는 각 layer별로 독립적인 경계를 설정하여, 기능 간의 의존성을 최소화합니다.

이때 상위 레어어는 하위 레이어에 의존할 수 없다는, 의존성 방향을 제시하기 때문에...

각 모듈 간 결합도를 낮추고, 변경 사항의 전파 범위를 예측 가능하게 만들 수 있습니다.

 

문제점

물론 아직 해당 아키텍처를 오랫동안 사용한 것은 아닙니다.

하지만 이전 아키텍처들과 비교했을 때는... 굉장히 만족하는 중!

예전부터 여러 프로젝트를 맡으며 생각했던, "~~ 하면 좋지 않을까?" 하는 아쉬움들을 모두 담아낸 듯한 느낌을 받았으니까요.

 

현재 한 가지 고민 중인 것은 → 단위 테스트 코드 관련 부분입니다.

 

헥사고날 아키텍처에서는 애플리케이션 영역에 대한 테스트 코드를 반드시 작성한다는 컨벤션을 세우고 따랐습니다.

이것이 가능했던 이유는, 애플리케이션 영역이 아무런 외부 의존성도 갖지 않는, 순수 JS 함수로만 이뤄져 있기 때문이었죠.

 

하지만 FSD에서는 가장 하위의 layer, 즉 shared라 할지라도 이러한 외부 의존성에 자유롭지 않습니다.

그리고 이는 자연스래... 테스트 코드 작성의 복잡함으로 이어지고 말죠.

 

이러한 상황에서 각 단위 테스트를 어떻게 작성할 것인지, 강제한다면 어떻게 할 것인지 등에 대한 고민을 이어가고 있습니다.

728x90
반응형