[아키텍처] FSD : Feature-Sliced Design

김종현·2024년 9월 10일
0

아키텍처

목록 보기
2/2

기본 구성

레이어(Layer)

-최상위 디렉토리이며 애플리케이션 분해의 첫 번째 단계.
-최대 7개로 숫자 제한, 일부는 선택 사항.

-각 고유한 비즈니스 지향적 책임 영역 존재

  • app: 앱의 전역 설정. 프로바이더, 라우터, 전역 스타일, 전역 타입 선언 등을 정의. 애플리케이션의 초기화 및 진입점.
  • processes(deprecated, optional): 결제 flow와 같이 여러 단계로 이루어진 프로세스들.
  • pages: 브라우저 주소 단위의 컴포넌트들.
  • widgets: 페이지에 사용되는 독립적인 UI 컴포넌트. 필요에 따라 features를 자유롭게 묶어서 구성.
  • features(optional): 좋아요 등록, 리뷰 작성, 제품 별점 평가 등과 같은 유저 시나리오와 함수 관련 비즈니스 기능들.
  • entities(optional): 사용자(User), 주문(Order), 상품(Product) 등과 같은 비즈니스 로직에서 가장 중요한 개체들. feature를 위해 불러온 데이터.
  • shared: 특정 비즈니스 로직에 종속되지 않은 재사용 가능한 컴포넌트와 유틸리티들. 공용 UI , axios 설정(configuration), 애플리케이션 설정(configuration), 비즈니스 로직에 묶이지 않은 헬퍼 등이 포함.
<Shared.Button								//widget
	onClick={likeFeature.api.like}			//feature
	icon={shared.icon.thumbUp}				//shared
	data={likeFeature.model.likeCount}		//entities
/>

이러한 레이어들은 코드베이스를 조직화하고, 모듈화되고 유지보수 용이한 확장 가능한 아키텍처를 촉진하는 데 도움을 준다.

중요한 특징으로는 계층 구조에서 상위의 레이어는 아래의 레이어를 활용 할 수 있으나 역으로는 불가능하다는 점이다. 즉 단 방향성 흐름을 유지해야 한다.

슬라이스(Slice)

-각 레이어에는 하위 디렉토리로 슬라이스가 존재.
-슬라이스에서 연결이라 함은 추상화가 아니라 특정 비즈니스 엔티티에 대한 연결을 의미.
-코드를 value에 따라 그룹화 하는 것이 목표.
-슬라이스 디렉토리의 이름은 표준화 되어있지 않으므로 비즈니스 영역에 따라 명명. 예를 들어 socialNetwork 같은 경우는 post, user, newsfeed로 슬라이스 이름을 붙이면 됨.
-밀접하게 관련된 fragments는 같은 디렉토리 하위에 모일 수는 있으나 반드시 분리 되어 있어야 하며 직접 코드를 공유해서는 안됨. (index.js를 만들어 이쪽에서 공유할 것.)

세그먼트(Segments)

-각 슬라이스는 세그먼트로 구성. 세그먼트는 목적에 따라 슬라이스 내의 코드를 나누는 데 도움이 됨.

  • api : 서버 요청
  • UI : 슬라이스의 UI 컴포넌트
  • model : 비즈니스 로직, 다시 말해 state와의 상호 작용. ex) actions, selectors
  • lib : 슬라이스 내에서 사용되는 보조 기능
  • config : 슬라이스에 필수적인 설정이지만 구성 세그먼트는 거의 필요하지 않음
  • consts : 상수

공개 API(Public API)

-각 슬라이스와 세그먼트에는 공개 API가 존재.
-index.js 또는 index.ts 파일을 통해 슬라이스 또는 세그먼트에서 필요한 기능만 외부로 추출하고 불필요한 기능은 격리. 인덱스 파일은 진입점 역할을 수행.
-공개 API 사용에는 다음과 같은 규칙이 필요함.

  • 애플리케이션 슬라이스와 세그먼트는 공개 API 인덱스 파일에 정의된 슬라이스의 기능과 컴포넌트만 사용할 것.
  • 공개 API에 정의되지 않은 슬라이스 또는 세그먼트의 내부 부분은 격리된 것으로 간주하여 슬라이스 또는 세그먼트 내부에서만 접근할 것.
  • 요약하자면 index에서 export된 기능 외에는 밖에서 꺼내 쓰려하지 않아야 함.

심화

추상화 및 비즈니스 로직

-계층이 높은 레이어일수록 특정 비즈니스 노드에 더 많이 종속되고 더 많은 비즈니스 로직이 포함된다. (계층이 높은 레이어 = 레고로 만든 조형물)
-계층이 낮은 레이어일수록 추상화 수준이 높고 재사용성이 높으며 레이어 자체의 자율성이 적습니다. (계층이 낮은 레이어 = 레고 조각)

FSD의 문제 해결 방식

기능 분할 설계의 과제 중 하나는 결합을 느슨하게 하고 응집력을 높이는 것. FSD가 이 과제를 어떻게 달성하는지 이해하는 것이 중요함.

OOP에서는 다형성(polymorphism), 캡슐화(encapsulation), 상속(inheritance)추상화(abstraction) 와 같은 개념을 통해 이러한 문제들을 오랜 시간 동안 해결해 왔습니다. 이러한 개념들은 코드 분리, 재사용성, 그리고 다양한 결과를 보장하므로 컴포넌트나 기능이 어떻게 사용되느냐에 따라 다른 결과를 얻을 수 있도록 합니다.

★기능 분할 설계는 이러한 원칙들을 프런트엔드에 적용하는 데 도움을 준다.★

추상화와 다형성은 레이어를 통해 달성됩니다. 낮은 레이어는 더 추상화 되어있기 때문에 더 높은 레이어에서 재사용될 수 있으며, 특정한 매개변수나 속성에 따라 컴포넌트나 기능이 다르게 작동할 수 있습니다.

캡슐화는 슬라이스와 세그먼트 외부에서 필요하지 않은 것을 격리시키는 공개 API를 통해 달성됩니다. 슬라이스의 내부 세그먼트에 대한 접근은 제한되며, 공개 API는 슬라이스 또는 세그먼트의 기능 및 컴포넌트에 접근할 수 있는 유일한 방법입니다.

상속 또한 레이어를 통해 달성됩니다. 더 높은 레이어는 낮은 레이어를 재사용할 수 있습니다.

고전적 아키텍처와의 비교


고전적인 아키텍처에는 눈에 띄는 단점이 있습니다. 가장 큰 단점은 컴포넌트 간의 암묵적인 연결과 모듈의 복잡성 때문에 프로젝트가 유지보수하기 어려워진다는 것입니다. 고전적인 아키텍처의 단점은 시간이 흐를수록 더욱 분명해집니다. 프로젝트가 진화할수록 애플리케이션 아키텍처는 엉망진창이 되어 버립니다.

고전적인 아키텍처는 지속적인 유지보수가 없는 작은 프로젝트나 개인 프로젝트에는 적합합니다.

기능 분할 설계는 그 개념과 표준 덕분에 고전적인 아키텍처의 문제를 해결할 수 있습니다. 그러나 FSD를 사용하는 개발자들은 고전적인 아키텍처를 다룰 때보다 더 높은 이해도와 기술 수준을 필요로 합니다. 일반적으로 2년 미만의 경력을 가진 개발자들은 FSD에 대해 들어보지 못한 경우가 많습니다.
그러나 기능 분할 설계를 사용할 때는 문제를 “나중”이 아닌 “지금” 해결해야 합니다. 코드의 문제점과 개념에서 벗어난 부분들이 즉시 드러납니다.

단순 모듈식 아키텍처와의 비교

단순한 모듈식 아키텍처에는 몇 가지 단점이 있습니다.

  • 기능을 어떤 모듈이나 컴포넌트에 넣을지 명확하지 않을 때가 있습니다.
  • 다른 모듈 내에서 모듈 사용에 어려움이 있습니다.
  • 비즈니스 엔티티를 저장하는 데 문제가 있습니다.
  • 글로벌 함수의 암시적 종속성으로 인해 구조가 복잡해집니다.
    복잡하거나 적당히 복잡한 프로젝트의 경우, 단순한 모듈식 아키텍처보다 기능 분할 설계를 선호해야 합니다. FSD는 많은 근본적인 아키텍처 문제를 해결하며 단점도 거의 없습니다.

단순함 및 개발 속도 측면에서 단순 모듈식 아키텍처가 FSD보다 유리할 수 있습니다. MVP가 필요하거나 수명이 짧은 프로젝트를 개발하는 경우에는 단순한 모듈식 아키텍처가 FSD보다 적합할 수 있습니다. 하지만 그 외의 경우에는 기능 분할 설계가 더 바람직해 보입니다.

Next.js와 FSD의 충돌

최근에는 Next.js를 기능 분할 설계와 함께 사용하는 경향이 증가하고 있습니다. Next.js는 FSD와 잘 작동하지만, 페이지의 파일 라우팅과 앱의 부재라는 두 가지 영역에서 충돌이 발생합니다.

Pages

Next.js에서는 pages 디렉토리가 파일 라우팅을 담당하며, 각 컴포넌트가 하나의 라우트를 나타냅니다. FSD에서는 pages는 페이지들의 평면 목록을 담고 있는 레이어로 사용됩니다. 이로 인해 Next.js 페이지와 FSD 페이지를 어떻게 결합할지에 대한 충돌이 발생합니다.

Next.js와 FSD를 함께 사용할 때, [root]/pages/와 같이 Next.js 페이지를 애플리케이션 루트에 저장하는 방법이 있습니다. 그리고 FSD 페이지는 [root]/src/pages/와 같이 src 폴더 내에 저장합니다.

다른 해결 방법으로는 두 개의 디렉토리를 유지하는 것이 있습니다. FSD의 페이지들의 평면 목록을 다시 이름 지은 pages-flat과 Next.js의 중첩된 라우트를 위한 pages입니다. 실제 페이지 코드는 pages-flat에 저장되고, 그 후에 pages로 내보낼 수 있습니다.

두 가지 방법 모두 사용하셔도 됩니다만, 저는 첫 번째 방법을 선호합니다.

App

app 레이어의 모든 기본적인 기능은 Next.js에서 처리합니다. 그러나 페이지와 독립적으로 전체 애플리케이션에 대해 무언가를 실행해야 하는 경우 레이아웃 패턴을 사용하여 전체 애플리케이션을 위한 레이아웃을 만들 수 있습니다.

레이아웃 패턴에 대한 Next.js의 문서 Routing: Pages and Layouts를 참고하세요.

기능 분할 설계의 잠재력

FSD는 비교적 젊은 소프트웨어 아키텍처 방법론입니다. 그러나 이미 많은 은행, 핀테크, B2B, 전자상거래 등 다양한 기업들에서 사용되고 있습니다. 이 관련 기업 목록은 Github Issue에서 확인할 수 있습니다.

현재 이 글을 작성하는 시점에 공식 FSD 문서의 깃허브 저장소는 858개의 스타를 받았습니다. 이 문서는 활발하게 확장되고 있으며, FSD 개발팀, 텔레그램 및 디스코드 커뮤니티는 아키텍처 관련 질문이 있는 분들을 위해 24시간 연중무휴로 도움을 드리고 있습니다.

이 아키텍처의 잠재력은 매우 높게 평가되며, 전 세계의 다양한 대형 기업들 사이에서 널리 사용되고 있습니다. 적절한 도입이 이루어진다면, FSD는 프런트엔드 개발 분야에서 주도적인 아키텍처 솔루션으로 성장할 수 있는 잠재력을 가지고 있습니다.

아키텍처의 장점과 단점

장점

아키텍처 구성 요소를 쉽게 교체, 추가, 제거할 수 있습니다.
아키텍처 표준화.
확장성.
방법론은 개발 스택과 독립적입니다.
예기치 않은 부작용 없이 모듈 간의 연결이 제어되고 명시적입니다.
아키텍처 방법론이 비즈니스 지향적입니다.

단점

다른 많은 아키텍처 솔루션들에 비해 높은 진입 장벽이 있습니다.
인식, 팀 문화 및 개념 준수가 필요합니다.
도전 과제와 문제를 나중이 아닌 즉시 해결해야 합니다. 코드 문제와 개념에서 벗어난 부분을 즉시 확인할 수 있습니다. 그러나 이는 장점으로도 볼 수 있습니다.

결론

기능 분할 설계는 프런트엔드 개발자가 알고 사용할 수 있는 흥미롭고 가치 있는 발견입니다. FSD는 팀에 유연하고 표준화되며 확장 가능한 아키텍처와 개발 문화를 제공할 수 있습니다. 하지만 이 방법론의 긍정적인 측면을 활용하려면 팀 내에서 지식, 인식 및 규칙이 필요합니다.

FSD는 명확한 비즈니스 지향성, 엔티티 정의, 애플리케이션의 기능 및 컴포넌트 구성과 같은 특징들로 인해 다른 아키텍처들 사이에서 돋보입니다.

또한 개별적으로 프로젝트에서 FSD를 사용한 사례와, 기능 분할 설계의 공식 문서를 살펴볼 수도 있습니다.

공식문서
예제. Github Client
예제. Nike Sneaker and Footwear Store
예제. Sudoku

profile
고양이 릴스 매니아

0개의 댓글