웹 프로젝트

FE 프로젝트 아키텍처에 대한 고민(feat. FSD 아키텍처)

TERRY✨ 2024. 9. 6. 03:59

프로그래머스 최종 프로젝트에서 프론트엔드 폴더구조에 대한 논의를 거쳐 FSD 아키텍처에 대해 공부하고 내용을 공유하기로 했다.
FSD 아키텍처는 어떤 구조인지 살펴보며 이전에 사용하던 방식과 FSD 아키텍처를 사용했을 때를 비교하여 좋은 점을 살펴보고 우리 프로젝트에 적용했을 때 얻게되는 이점 또한 생각해보려고 한다.
 
FSD 공식페이지 : https://feature-sliced.design/

Welcome | Feature-Sliced Design

Architectural methodology for frontend projects

feature-sliced.design

공식문서에 다양한 서비스들의 깃허브 주소가 있다. 레퍼런스로 활용할 수 있을 것 같다.

FSD(FeatureSliced Design) Architecture

FSD(기능 분할 설계)는 기본적으로 Layers, Slices, Segments로 구성되어 있다.

https://feature-sliced.design/

Layers

모든 FSD 프로젝트에서 Layers는 표준화되어 있다. 총 7개의 Layer가 존재하고, 모든 레이어를 다 사용할 필요는 없다. 

  • app : 애플리케이션 로직이 초기화 되는 곳이다. 프로바이더, 라우터, 전역 스타일, 전역 타입 선언 등이 정의된다. 애플리케이션의 진입점 역할을 한다.
  • processes : 더이상 사용되지 않지만, 여러 페이지에 걸쳐 있는 프로세스를 처리한다. 
  • pages : 애플리케이션의 페이지가 포함된다.
  • widgets : 페이지에 사용되는 독립적인 UI 컴포넌트이다.
  • features : 사용자에게 비즈니스 가치를 가져다주는 작업인 사용자 시나리오나 기능을 다룬다.
  • entities : 비즈니스 엔티티를 나타낸다. 선택적 레이어이다.
  • shared : 특정 비즈니스 로직에 종속되지 않는 재사용 가능한 컴포넌트와 유틸리티가 포함되어 있다. UI키트, axios 설정, 애플리케이션 설정, 비즈니스 로직에 묶이지 않는 헬퍼 등이 포함된다.

Layers를 통해 모듈화되고 유지보수에 좋은 확장가능한 아키텍처를 구성하는데 도움이 될 수 있다.
 
여기서 중요한 점은 이 레이어가 계층화가 되어있다는 것이다. 즉, features 레이어는 entities와 shared 레이어보다 더 위에 있기 떄문에 entities와 shared 레이어는 features 레이어의 기능을 사용할 수 없다. 이는 선형적인 흐름을 유지하기 위함이라고 하는데, 아키텍처에 잘 적응하면 오히려 개발하기에는 편한 구조가 될 수 있다고 생각이 들었다. (특정 부분을 가져와야 하면 꼭 아래 계층에서만 가져올 수 있으니까... 결국 아래에서 만들도록 유도시키고, 특정 기능이나 코드도 아래 계층에서 찾으면 되기 때문에 구조와 관련된 개발 시간을 축소시키지 않을까?🧐)

https://dev.to/m_midas/feature-sliced-design-the-best-frontend-architecture-4noj

Slices

Layers의 하위로 Slices 디렉토리를 구성할 수 있다. 이 Slices의 목표는 코드를 값 별로 그룹화 하는 것이다. Layers에서는 각 Layer마다 이름이 존재했는데 Slices와 Segments는 특정한 이름이 없다. 팀에서 목적에 부합한 이름을 붙이면 된다고 한다. Slice는 각 Layer에서 독립적으로 사용되어야 하며 Slice에서 구현한 코드들은 직접적인 공유를 하지 않는 것이 이상적이라고 한다. 
(직접적인 공유라 함은 코드내 export를 말하는 건가?(확실치않음) -> 그래서 뒤에 나오는 Public API가 나오는건가 싶다.)

FSD 공식문서를 보면 app과 shared 레이어는 Slices를 가지지 않고 바로 Segments를 구성한다고 나와있다.

Segments

각 Slices는 Segments로 구성된다. Segment의 목적에 따라 Slice 내의 코드를 나누게 된다. Segments들의 이름 또한 제한되어 있지는 않지만 가장 일반적으로 쓰이는 이름들이 있다.

  • ui : UI 표시와 관련된 것 - UI 구성요소, 날짜 포맷터, 스타일 등
  • api : 백엔드 인터랙션 - 요청 함수, 데이터 타입 등
  • model : 데이터 모델 - 스키마, 인터페이스, 스토어, 비즈니스 로직 등
  • lib : 해당 Slice에서 사용되는 라이브러리 코드
  • config - configuration 파일과 feature flags

Public API (Barrel export)

Slice와 Segment에는 Public API가 있다. 이는 index.js, index.ts를 의미하며 이 파일을 통해 필요한 기능만 외부로 export 하는 방식이다. Public API에 대한 규칙은 아래와 같다.

  • app slice와 segment는 public API의 index 파일에 정의된 slice 기능과 컴포넌트만 사용한다.
  • public API에 정의되지 않은 slice 또는 segment의 내부 부분은 격리된 것으로 간주되며 slice 또는 segment 내부에서만 접근할 수 있다.
https://dev.to/m_midas/feature-sliced-design-the-best-frontend-architecture-4noj

Barrel export를 사용하면 import할때 import { Button, Title, Textfield } from 경로/index.ts 으로 깔끔하게 사용할 수 있어서 좋다.


이전에 사용한 방식 vs FSD

이전에는 기능별로 아키텍처를 구분하는 것이 아닌 코드의 역할에 따라서 아키텍처를 구분했었는데, 따라서 api, assets, components, pages, store, utils, style 등의 폴더를 최상위로 아키텍처를 구성하였다. 하지만 이 방식은 코드를 분리하거나 관리하기에는 복잡한 구조였다. 예를 들어 특정 기능을 하는 함수를 구현해야 할 때 해당 코드를 어디에다가 배치해야하는 지에 대한 고민이 필요하다.
 
FSD는 이러한 고민에서 벗어나게 해주는 것 같다. 기능단위로 구조가 나뉘어지기 때문에 명확하게 코드가 구분이 된다. 또한 레이어에서는 계층구조가 이루어져 있어, 상속이 가능하다. 이러한 특성은 유지보수하기에 장점이라고 생각한다. 또한 FSD 공식 문서를 보면 린트를 가지고 있다고 한다. 이를 활용하면 좀 더 FSD에 맞게 개발할 수 있지 않을까 싶다.
 
하지만 새로운 방식의 아키텍처이다보니, 우리팀의 경우 8명의 팀원이 이 방식의 구조에 친해지기에는 약간의 시간이 걸릴수도 있고, 개발하면서도 적응하기에는 쉽지 않을 것 같다. 해당 아키텍처를 사용하기 위해선 모든 팀원이 동일한 이해를 바탕으로 사용되어질 필요가 있다.
 

더보기