본 글은 https://feature-sliced.design/docs/get-started/overview 를 해석한 글이다.

기능별로 나눠진 설계(FSD : Featured-Sliced Design)은 프런트엔드 스캐폴딩(scaffolding)을 위한 아키텍처 방법론이다.

  • 스캐폴딩(scaffolding) : 

간단히 말해, 코드 구성에 대한 규칙 및 컨벤션 모음이다. 이 방법론의 주요 목적은 끊임없이 변화하는 비즈니스 요구 사항에 직면하여 프로젝트를 더 이해하기 쉽고 체계적으로 만드는 것이다.

 

Is it right for me? : 나에게 적합한가)

FSD는 모든 사이즈의 팀과 프로젝트에서 구현 가능하다. 그러나 몇 가지 유의 사항이 있다:

  • 이 방법론은 프론트엔드 프로젝트에서만 적용된다. 만약 백엔드 아키텍처를 찾고 있다면 클린 아키텍처를 고려해라.
  • 이 방법론은 사용자 대면(user-facing) 애플리케이션에만 적용된다. 대규모 UI 키트를 설계하는 방법에 대한 영감은 Material UI를 참조해라.
  • 단일 페이지로 구성된 매우 단순한 앱은 FSD의 이점이 필요하지 않을 수 있으며 오버헤드로 인해 어려움을 겪을 수 있다. 하지만 FSD는 좋은 사고방식(way of thinking)을 장려하므로 원하는 경우 아주 작은 프로젝트에 자유롭게 사용할 수 있다.
  • Google Cloud 관리 대시보드 크기의 거대한 앱에는 사용자 지정(custom) 아키텍처가 필요하다. 그래도 FSD를 기반으로 할 수 있다

FSD는 특정 프로그래밍 언어, UI 프레임워크 또는 상태 관리자를 강제하지 않는다. - 직접 개발하거나 몇 가지 예제를 참조하라.

 

기존 프로젝트가 있다면, 두려워하지마라. - FSD는 점진적으로 적용할 수 있다. 다만 팀이 현재 아키텍처로 인해 어려움을 겪고 있는지 확인해야 하며, 그렇지 않다면 전환할 가치가 없을 수도 있다. 마이그레이션 가이드는 마이그레이션 섹션을 참조하세요.

 

Basics : 기초

FSD에서 프로젝트는 여러 레이어(layers) 로 구성되며, 각 레이어는 여러 슬라이스(slices)로 구성되고, 각 슬라이스는 여러 세그먼트(segments)로 구성된다.

레이어는 모든 프로젝트에 걸쳐 표준화되어 있으며 수직으로 배열되어 있습니다. 한 레이어의 모듈은 바로 아래 레이어의 모듈과만 상호 작용할 수 있다. 현재 7개의 레이어가 있다(아래에서 위로):

  1. `shared` - 프로젝트/비즈니스의 세부 사항과 분리된 재사용 가능한 기능(예: UIKit, libs, API)
  2. `entities` - 비즈니스 엔티티(예: User, Product, Order)
  3. `features` - 사용자 인터렉션, 사용자에게 비즈니스 가치를 가져다주는 액션들(예: SendComment, AddToCart, UsersSearch)
  4. `widgets` - 엔티티(entities)와 기능(features)을 의미 있는 블록으로 결합하는 구성(compositional) 레이어(예: IssuesList, UserProfile)
  5. `pages` -  엔티티(entities), 기능 (features) 및 위젯(widgets)에서 전체 페이지를 구성하는 구성 (compositional) 레이어
  6. `processes(deprecated)` - 복잡한 페이지 간 시나리오. (예: authentication)
  7. `app` - 앱 전체 설정, 스타일 및 공급자

그런 다음 비즈니스 도메인 별로 코드를 분할하는 슬라이스(slices)가 있다. 이렇게 하면 논리적으로 관련된 모듈을 서로 가깝게 유지하여 코드베이스를 쉽게 탐색할 수 있다. 슬라이스는 같은 레이어에 있는 다른 슬라이스를 사용할 수 없으므로 응집력이 높고 결합력이 낮다.

각 슬라이스는 차례로 세그먼트(segments)로 구성된다. 세그먼트는 슬라이스 내의 코드를 기술적 목적에 따라 분리하는 데 도움이 되는 작은 모듈이다. 가장 일반적인 세그먼트는 `ui`, `model`(store, actions), `api`, `lib`(utils/hooks)이지만, 필요에 따라 일부를 생략하거나 더 추가할 수 있다.

Note
대부분의 경우, API 클라이언트가 스토리지(GraphQL, TanStack Query 등)인 경우를 제외하고는 
shared 레이어에만 `api` 및 `config`을 배치하는 것이 좋다.

Example : 예시

소셜 네트워크 애플리케이션이라고 생각해 보자.

  • `app/` : 라우팅, 스토어 및 글로벌 스타일 설정을 포함한다.
  • `pages/` : 애플리케이션에서 각 페이지에 대한 라우팅 컴포넌트를 포함하며, 대부분의 로직이 거의 없다.

애플리케이션 내부에서 뉴스 피드에 있는 포스트 카드(post card)를 생각해 보자.

  • `widgets` : 백엔드의 호출과 관련 있는 콘텐츠 및 상호 작용 가능한 버튼이 포함된 "조립형(assembled)" 포스트 카드를 포함한다.
  • `features` : 카드의 상호작용(예: 좋아요 버튼)과 상호작용을 처리하는 로직을 포함한다.
  • `entities` : 콘텐츠 및 상호 작용 가능한 요소를 위한 슬롯(slots)이 있는 카드의 셸(shell)을 포함한다. 글 작성자를 나타내는 타일(tile)도 여기에 있지만 다른 슬라이스에 있다.

Advantages : 장점

  • 통일성
    코드는 영향 범위(layers), 도메인(slices), 기술 목적(segments)에 따라 구성된다.
    이를 통해 초보자도 쉽게 이해할 수 있는 표준화된 아키텍처가 만들어진다.
  • 제어된 로직 재사용
    각 아키텍처 컴포넌트는 각가의 목적과 예측 가능한 종속성(dependencies)이 있다.
    이는 DRY 원리를 따르는 것과 적응 가능성(adaptation possibilities) 사이의 균형을 유지할 수 있다.
  • 변경 및 리팩토리에 대한 안정성
    특정 레이어에 있는 모듈은 같은 레이어 또는 그 위의 레이어에 있는 다른 모듈을 사용할 수 없다.
    따라서 예기치 않은 결과 없이 격리된 수정이 가능하다.
  • 비즈니스 및 사용자 요구사항에 대한 오리엔테이션
    앱이 비즈니스 도메인으로 분할되면 코드를 탐색하여 모든 프로젝트 기능을 발견하고 더 깊이 이해할 수 있다.

Incremental adoption(점진적 도입)

FSD의 강점은 구조 분해에 있다. 최상의 상태에서 코드의 모든 부분을 거의-결정론적(near-deterministically)으로 찾을 수 있다. 그러나 분해 레벨은 매개변수이므로 각 팀은 이를 조정해 단순한 채택과 이점 사이에서 균형을 맞출 수 있다.


다음은 경험을 바탕으로 기존 코드베이스를 FSD로 마이그레이션 하기 위한 제안된 전략이다:

  1. `app`과 `shared` 레이어의 윤곽을 그려 기초를 만드는 것부터 시작해라. 대개 이러한 레이어는 가장 작은 레이어이다.
  2. FSD 규칙을 위반하는 종속성이 있어도 기존 UI를 `widgets`과 `pages`로 모두 나누어라.
  3. `features`와 `entities`로 분리하고 페이지와 위젯을 로직이 있는 레이어에서 순순한 구성의 레이어로 전환하여 분해의 정밀도를 점진적으로 높여라.

프로젝트의 특정 부분만 리팩터링 하거나 리팩터링 하면서 새로운 대형 엔티티를 추가하는 것은 자제하는 것이 좋다.

+ Recent posts