니들이 FSD를 알아??

김인태·2024년 3월 4일
6

시작하며..

안녕하세요 까를로스입니다.. 일단 어그로 죄송하고

저는 FSD라는 걸 잘 모릅니다... 제로초 선생님의 영상을 보고 처음 접해봤습니다..ㅎㅎ

어떤 프로젝트를 시작할 때 여러가지를 고민하는데. 어떤 스택을 사용하고, 어떤 인프라를 사용할지,

서비스는 어떻게 할 것인지.. 등 그중에서도 폴더구조도 참 고민을 많이 하는 것 같습니다.

그냥 파일만 잘 정리해놓으면 된다고 생각할 수 있지만, 어디에 어떤 파일이 들어가 있는지

명시적으로 잘 표현할 수 있다면, 그것을 통해서 개발 능률이 올라갈 수 있지 않을까?

또한 파일간의 응집도를 올리고 결합도를 떨어뜨려서 수정하기 쉬운 아키텍처를 만들 수 있겠다!

그래서 좋은 폴더 구조가 있고, 이렇게도 할 수 있구나~ 라는 것을 알아보고자 아래 링크에 있는 글과 동영상을 정리 해보았습니다.

참고로 이런 방법이 있다!지 폴더 구조에 정답은 없다고 생각합니다!

[제로초] 아직도 React 폴더 구조로 고민하고 계신가요? FSD 한 번 써보세요

https://www.youtube.com/watch?v=64Fx5Y1gEOA&t=92s

[기능 분할 설계]

https://emewjin.github.io/feature-sliced-design/

리액트에서 유행하는 패턴이라면 컨테이너 프리젠터, 컨테이너 컴포넌트 패턴을 많이 사용한다.

데이터와 UI만을 담당하는 컴포넌트를 분리를 하는 패턴을 많이 사용했는데, hook가 도입되면서

컨테이너들을 hooks로 대체할 수 있게 되었다. 이 폴더 구조가 나쁜 것은 아니지만,

제로초 선생님께서는 명확한 이유가 없이 이 폴더 구조를 선택했다고 한다.

그러다가 FSD(Feature-Sliced Design) 라는 키워드를 찾았다고 한다. 무엇인지 알아보자.

먼저 Layers, Slices, Segment 폴더로 구분하고 Depth를 3으로 제한한다.

폴더를 마구잡이로 넣고 컴포넌트를 많이 만든다면?

파일이 너무 깊어지면 파일 import 할 때 ../../../ ……. 과 위치를 구분하기 힘들어질 것이다.

Layers

  • app: 애플리케이션 로직이 초기화되는 곳입니다. 프로바이더, 라우터, 전역 스타일, 전역 타입 선언 등이 여기에서 정의됩니다. 애플리케이션의 진입점 역할
  • processes: 이 레이어는 여러 단계로 이루어진 등록과 같이 여러 페이지에 걸쳐 있는 프로세스를 처리. 이 레이어는 더 이상 사용되지 않는 것으로 간주되지만 여전히 가끔씩 마주할 수 있습니다. 선택적 레이어입니다.
  • pages: 이 레이어에는 애플리케이션의 페이지가 포함됩니다. (브라우저 주소단위의 컴포넌트)
  • widgets: 페이지에 사용되는 독립적인 UI 컴포넌트입니다.
  • features: 이 레이어는 비즈니스 가치를 전달하는 사용자 시나리오와 기능을 다룹니다. 예를 들어 좋아요, 리뷰 작성, 제품 평가 등이 있습니다. 선택적 레이어입니다.
  • entities: 이 레이어는 비즈니스 엔티티를 나타냅니다. 이러한 엔티티에는 사용자, 리뷰, 댓글 등이 포함될 수 있습니다. 선택적 레이어입니다. (데이터 그 자체)
  • shared: 이 레이어에는 특정 비즈니스 로직에 종속되지 않은 재사용 가능한 컴포넌트와 유틸리티가 포함되어 있습니다. (전역적으로 사용하는) 여기에는 UI 키트, axios 설정, type설정, 애플리케이션 설정, 비즈니스 로직에 묶이지 않은 헬퍼 등이 포함됩니다.

⇒ 제로초 선생님 추천은 앱, 페이지, 엔티티, 쉐어드만 사용하는 것을 추천하신다.

깃허브의 예)

버튼을 페이지 말고도 전체적으로 사용할 것 같다? → shared

버튼의 동작 → feature

fork 버튼을 구현한다고 치면 fork에 대한 행위는 feature에 있을 것이고, 그 밑에 children으로 fork에대한 entities 컴포넌트가 있고, 공유되는 UI를 담당하는 버튼 컴포넌트가 있는 것이다.

컨테이너 컴포넌트 패턴과 거의 유사하다!

feature를 묶는 기준은? → 본인한테 있다~~~ (페이지 전체일수도, nav 한 줄이 될 수도 있을 것이다.)

  • onClick에 대한 행위 : feature
  • 공유되는 아이콘들 : shared
  • 데이터 : entities

[총정리]

가장 중요한 법칙은 위계질서가 있다는 것!

서로간의 import 하는 것이 아닌 app 폴더에서는 밑에 6가지를 import 할 수 있다.

feature에서는 아래 두 가지를 import 할 수 있다.

shared는 아무데나 가져다 공유 되는 것이기 때문에 가장 아래에 있는 것!

shared는 slices가 없다! 공유되는 것이기 때문에 어떤 도메인에 종속되지 않음!

index.js와 index.ts의 사용

export 하고 싶은 폴더만 사용한다! FSD를 사용한다면 index 파일을 사용해야한다!

(그렇게 약속하는 것!)

이렇게 해야 어떤 컴포넌트는 프라이빗 컴포넌트인지 퍼블릭 컴포넌트인지 캡슐화 하는 것!

캡슐화 : 서로 연관있는 속성과 기능들을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것

ex) 자바의 접근 제어자와 같은..

Segment

  • api - 필요한 서버 요청.
  • UI - 슬라이스의 UI 컴포넌트.
  • model - 비즈니스 로직, 즉 상태와의 상호 작용. actions 및 selectors가 이에 해당
  • lib - 슬라이스 내에서 사용되는 보조 기능.
  • config - 슬라이스에 필요한 구성값이지만 구성 세그먼트는 거의 필요하지 않음.
  • consts - 필요한 상수.

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를 참고하세요.

https://nukeapp.netlify.app/ ← FSD로 만들어진 app

후기

항상 좋은 가르침을 주시는 제로초 선생님한테 쌰라웃 하고 싶다..!!!
또한 기능 분할 설계를 https://emewjin.github.io/feature-sliced-design/ 적어주신 분도
너무 감사드립니다!
어플리케이션의 규모가 좀 있을 때 사용하면 정말 좋을 것 같다..!
원래 있던 프로젝트의 폴더를 마이그레이션 해봐야겠다!

profile
새로운 걸 배우는 것을 좋아하는 프론트엔드 개발자입니다!

3개의 댓글

comment-user-thumbnail
2024년 5월 25일

제로초 선생님은 앱, 페이지, 엔티티, 쉐어드만 쓰는걸 추천한다는건, 비즈니스 로직까지 처음에 한번에 썼다가 나중에 분기하라는 의도로 이야기하신거겠져??

+추가
feature에서 동사라고 얘기하신게 ddd에서 유즈케이스인거죠 ㅎㅎ?

2개의 답글