본문 바로가기

지식!

번역)새 아키텍쳐를 소개합니다 - FSD

소개

프론트엔드 개발자는 종종 애플리케이션 아키텍쳐와 관련된 문제에 직면합니다. 쉽게 확장할 수 있고 애플리케이션 모듈 간의 느슨한 결합과 높은 응집성을 제공할 수 있는 아키텍쳐를 사용해야 합니다.

 

이 기사에서는 Feature-Sliced Design 아키텍쳐에 대해 설명합니다. 내 생각에는 이 방법론이 사용 가능한 옵션 중 최고입니다. 또한 FSD의 개념과 이 아키텍쳐 방법론이 해결하는 문제를 살펴봅시다.

 

먼저 레이어(layer), 슬라이스(slice), 세그먼트(sgment)라는 세 가지 개념을 구별해 보겠습니다.

 

레이어

레이어는 최상위 디렉터리이자 애플리케이션 분해의 첫 번째 수준입니다. 레이어 수는 최대 7개로 제한되어 있으며 표준화되어 있지만 일부는 선택 사항입니다. (준희 - 실제로 FSD 공식 문서를 살펴보면 process레이어는 deprecated라고 되어있다. 상황에 따라 넣으면 될 것같다.)

각 계층에는 고유한 책임 영역이 있으며 비즈니스 지향적입니다.

각 레이어를 개별적으로 고려해보겠습니다.

 

  • app: 애플리케이션 로직이 초기화 되는 곳입니다. 공급자, 라우터, 전역 스타일, 전역 유형 선언 등이 여기에 정의됩니다. 이는 애플리케이션의 진입점 역할을 합니다. (준희 - 흔히 리덕스의 Provider값이나 라우터 그리고 Context등의 전역적으로 필요한 설정 값을 넣는데 사용하는 레이어이다.)
  • process: 이 계층은 다단계 등록과 같이 여러 페이지에 걸쳐 있는 프로세스를 처리합니다. 이 레이어는 더 이상 사용되지 않는 것으로 간주되지만 여전히 가끔 나타날 수 있는 선택적 레이어입니다. (준희- 예를들면 사용자 로그인과 같은 인증 프로세스들)
  • page: 이 레이어에는 애플리케이션의 페이지가 포함됩니다.
  • widget: 페이지에 사용되는 독립형 UI 구성 요소입니다. (준희 - 전체적인 레이아웃을 담당하는 UI들이 모인 폴더이다. 예를들어 페이지가 바뀌어도 전첵적인 레이아웃은 그대로인 상황에서 해당 레이아웃을 렌더링하는 컴포넌트가 들어가면 될 것같다.)
  • features:이 계층은 비즈니스 가치를 전달하는 사용자 시나리오 및 기능을 다룹니다. 예를들어 좋아요, 리뷰 작성, 제품 평가 등은 선택 레이어입니다.  (준희 - 비즈니스 로직에 사용되는 파일들이 담긴 폴더라 예상한다. 버튼을 눌렀을 때의 이벤트 등)
  • entities: 이 레이어는 비즈니스 엔티티를 나타냅니다. 이러한 엔티티에는 사용자, 리뷰, 댓글 등이 포함될 수 있다. 이는 선택적 레이어입니다. (준희 - 흔히 컴포넌트 폴더에 있는 컴포넌트들이 담긴 폴더같다. 예를들어 features에서 불러온 데이터를 렌더링하는, todo-list의 예로 들면, featuers는 todo-list 데이터를 불러오고, entities는 그 불러온 데이터를 렌더링하는 파일이 모인 파일이다)
  • shared: 이 계층에는 특정 비즈니스 노리에 연결되지 않은 재사용 가능한 구성요소와 유틸리티가 포함되어 있습니다. 여기에는 UI키트, axios구성, 애플리케이션 구성, 비즈니스 로직에 얽매이지 않은 도우미 등이 있습니다.

이러한 계층은 코드베이스를 구성하고 모듈식, 유지 관리 및 확장 가능한 아키텍쳐를 촉직하는데 도움이 됩니다.

 

FSD의 주요 특징 중 하나는 계층 구조입니다. 이 구조에서는 기능이 계층 구조에서 더 높기 때문에 entities는 features를 사용할 수 없습니다.(준희- 즉, entities폴더에 담긴 파일은 features에 담긴 파일을 불러올 수 없다.) 이는 한 방향으로만 향하는 선형 흐름을 유지하기 위해 수행됩니다.

계층 구조에서 하위 계층이 위치할수록 코드의 더 많은 위치에서 사용될 가능성이 높기 때문에 계층을 변경하는 것이 더 위험합니다.

 

 

Slices

각 레이어에는 애플리케이션 분해의 두 번째 수준인 슬라이스라는 하위 디렉터리가 있습니다. 슬라이스에서 연결은 사물을 추상화하는 것이 아니라 특정 비즈니스 엔티티와 연결됩니다. 슬라이의 주요 목표는 값을 기준으로 코드를 그룹화하는 것입니다.

 

슬라이스 이름은 프로젝트 사업 영역에 따라 직접 결정되므로 표준화하지 않습니다.

예를들어 사진 갤러리에는 사진, 앨범, 갤러리와 같은 섹션이 있을 수 있습니다. 소셜 네트워크에는 게시물, 사용자, 뉴스피드와 같은 조각이 필요합니다.

 

밀접하게 관련된 조각은 디렉터리에 구조적으로 그룹화할 수 있지만 다른 조각과 동일한 격리 규칙을 준수해야 합니다. 이 디렉터리의 코드에 대한 공유 엑세스가 있어서는 안됩니다.

 

 

Segment

각 조각은 세그먼트로 구성됩니다. 세그먼트는 목적에 따라 슬라이스 내에서 코드를 나누는데 도움이 됩니다. 팀의 합의에 따라 세그먼트의 구성과 이름이 변경될 수 있습니다. 다음 세그먼트가 더 일반적으로 사용됩니다.

  • api - 필요한 서버 요청
  • UI - 슬라이스의 UI 구성요소
  • 모델 - 비즈니스 로직, 즉 작업 및 선택과 같은 사용자와의 상호작용
  • lib - 슬라이스 내에서 사용되는 보조 기능
  • config - 슬라이스의 필수 구성이지만 구성 세그먼트는 거의 발견되지 않습니다.
  • consts - 상수

 

Public API

각 slice와 세그먼트에는 공개 API가 있습니다. Public API는 index.js나 index.ts파일로 표현되는데, 이를 통해 슬라이스나 세그먼트에서 필요한 기능만 외부로 추출하고 불필요한 기능은 격리할 수 있습니다. 인덱스 파일은 진입점 역할을 합니다.

 

규칙

  • 애플리케이션 slice와 세그먼트는 공용 API 인덱스 파일에 정의된 slice와의 기능과 구성 요소만 사용합니다.
  • 공용 API에 정의되지 않은 슬라이스 또는 세그먼트의 내부 부분은 격리된 것으로 간주되며 슬라이스 또는 세그먼트 자체 내에서만 액세슬 할 수 있습니다.

Public API는 import 및 export 작업을 단순화하므로 애플리케이션을 변경할 ㅅ=때 코드의 모든 위치에서 import를 변경할 필요가 없습니다.

 

 

Deeper into architecture

FSD의 문제해결

FSD는 작업중 하나는 느슨한 결합과 높은 응집력을 달성하는 것입니다. FSD가 어떻게 이러한 결과를 달성했는지 이해하는 것이 중요합니다.

 

OOP에서는 이러한 문제가 오랫동안 다형성, 캡슐화, 상속, 추상화 등의 개념을 통해 해결되었습니다. 이러한 개념은 구성 요소나 기능이 사용되는 방식에 따라 다른 결과를 얻을 수 있는 코드의 격리, 재사용성 및 다양성을 보장합니다.

 

FAD는 이러한 원칙을 프론트엔드에 적용하는데 도움이 됩니다.

 

추상화와 다형성은 레이어를 통해 달성됩니다. 하위 레이어는 추상적이기 때문에 상위 레이어에서 재사용이 가능하며, 조건에 따라 컴포넌트나 기능이 지정된 매게변수나 props에 따라 다르게 동작할 수 있습니다.

 

캡슐화는 슬라이스와 세그먼트의 외부에서 필요하지 않은 것으로 격리하는 공용 API를 통해 달성됩니다. 슬라이스의 내부 세그먼트에 대해 엑세스는 제한되어 있으며 공개 API는 슬라이스 또는 세그먼트의 기능 및 구성 요소에 액세스할 수 있는 유일한 방법입니다.

 

상위계층이 하위 계층을 재사용할 수 있으므로 상속은 계층을 통해 달성됩니다.

 

Comparison with the classic architecture

기존 아키텍쳐에는 눈에 띄는 단점이 있습니다. 가장 큰 문제는 구성 요소와 모듈 혼란 사이의 암묵적인 연결로 인해 프로젝트를 유지 관리하기가 어려워진다는 것입니다. 고전적인 아키텍쳐의 단점은 시간이 지남에 따라 더욱 분명해집니다. 프로젝트가 길어질수록 애플리케이션 아키텍쳐는 해결하기 어려운 뒤엉킨 혼란이 더욱 커집니다.

 

클래식 아키텍쳐는 지속적인 유지 관리가 없는 소규모 아키텍쳐에 적합합니다.

(준희- 개인적으로 중요한 부분인 것같다. 이미 흔히 사용하는 익숙한 container-component 패턴 등의 패턴만으로 손쉽게 역할을 분배하고 해당 역할에 맞는 모듈끼리 합칠수 있지만 이를 FSD방식으로 구성하려면 닭잡는데 소잡는 칼을 사용하는 것 같은 느낌이다. 또한 FSD 아키텍처는 팀원 모두가 FSD에 깊은 이해를 동반한다는 필수 요소가 있기 때문에  이를 직접 적용하려면 꽤 많은 시간이 필요할 것 같다.)

 

FSD는 개념과 표준 덕분에 기존 아키텍쳐의 문제를 방지합니다. 그러나 FSD로 작업하는 개발자의 이해 수준과 기술은 클래식 아키텍쳐로 작업할 때보다 높아야합니다. 일반적으로 경력이 2년 미만인 개발자들은 FSD에 대해 들어본 적이 없습니다.

그러나 FSD로 작업할 때는 문제를 "나중에" 해결하기 보다는 "지금" 해결해야 합니다. 코드의 문제와 개념의 차이가 즉시 명백해집니다.

 

 

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

단순한 모듈식(comparison with simple modular architecture)에는 몇가지 단점이 있습니다.

 

  • 때로는 모듈이나 구성요소에 기능을 어디에 넣어야할 지 불분명할 때가 있습니다.
  • 다른 모듈 내에서 다른 모듈을 사용하는데 어려움이 있습니다.
  • 비즈니스 항목을 저장하는데 문제가 있습니다.
  • 전역 함수의 암시적 종속성으로 인해 얽힌 구조가 발생합니다.

복잡하거나 적당히 복잡한 프로젝트에는 단순한 모듈식 아키텍쳐보다 기능 분할 디자인이 선호되어어야 하는 것 같습니다.

FSD는 많은 근복적인 아키텍쳐 문제를 해결하고 단점도 거의 없습니다.

 

단순성과 개발 속도 측면에서는 단순한 모듈형 아키텍쳐가 FSD보다 유리할 수 있습니다. MVP가 필요하거나 단기 프로젝트를 개발하는 경우 FSD보다 간단한 모듈식 아키텍쳐가 적합할 수 있습니다. 그러나 다른 경우에는 FSD방식이 더 좋습니다.

 

정리

FSD는 다음과 같은 장단점이 있습니다.

 

장점

  • 아키텍쳐 구성 요소를 쉽게 교체, 추가 또는 제거할 수 있습니다.
  • 아키텍쳐 표쥰화
  • 확장성
  • 방법론은 개발 스택과 무관합니다.
  • 예상치 못한 부작용 없이 모듈 간 제어되고 명시적인 연결
  • 비즈니스 중심의 아키텍쳐 방법론

 

단점

  • 다른 많은 아키텍처 솔루션에 비해 진입 장벽이 높습니다.
  • 인식, 팀 문화 및 개념 준수가 필요합니다.
  • 문제는 나중에 해결하기 보다 즉시 해결해야 합니다. 코드 문제와 개념 차이가 즉시 표시됩니다. 하지만 이는 장점으로도 볼 수 있습니다.

해당 글을 읽다가 문득 우아한 형제들의 레이어와 닮았다는 생각이 들었다.

(영상 링크)

해당 영상의 발표자님께서는 FSD나 하위 레이어가 상위 레이어를 import할 수 없다는 언급은 없었지만, 영상에서 설명하는 레이어의 분할은 FSD와 유사하게 느껴졌다.

 

나는 현재 가장 익숙한 컨테이너-컴포넌트 패턴을 주로 사용하고 전역 상태관리가 필요한 경우 Flux패턴을 사용하기도 한다. 

어떠한 패턴이 정답이다. 이 아키텍처를 제외하고 모두 다 필요없는 아키텍처이다.라는 건 없다. 단지 시대와 상황에 따라 아키텍쳐가 바뀌고 사라질 뿐이다.

내가 생각하는 좋은 아키텍쳐란 유지보수가 쉬운 아키텍쳐로 생각한다.

여기서 유지보수란 프로젝트의 투입인원이 계속 관리하는 것이 아닌 프로젝트에 투입된 새 개발자가 코드를 쉽게 이해하고 수정할 수 있는 것이다.

이러한 관점에서 봤을 때, FSD의 장단점이 분명히 존재한다.

  • 유지보수가 어렵다. 프로젝트의 모든 팀원들이 FSD에 깊은 이해를 동반한다 하더라도 새로 투입된 인원이 해당 프로젝트의 아키텍처를 이해하는데 많은 시간이 소요될 것 같다.
  • 어느 시점에서 FSD를 사용해야 좋을지 애매하다. 기사에는 "소규모 프로젝트"에 적합하지 않다는 말만 있을 뿐이다. 모든 아키텍쳐가 어느것에 적합하다라는 분명함이 없지만 FSD는 너무나 애매하다. 이는 온전히 개발자 개인의 역량에 따라 이 아키텍쳐를 선택할지 말지 고민해봐야 한다는 뜻이다.
  • 하지만, 잘만 이해한다면 FSD는 분명 좋은 아키텍처임에 분명하다. 나 또한 회사 프로젝트에 FSD를 적용해보려 했으나 실패했다. 그리고 잠깐이나마 FSD를 경험해 본바로는 폴더 구조를 거리낌없이 설계할 수 있었다.

 

 

'지식!' 카테고리의 다른 글

CS) 웹 브라우저에 URL을 입력하면.(GSLB, CDN)  (0) 2024.03.26