React 폴더 구조
React 폴더 구조
계기
항상 리액트 개발을 하며 별거 아닌 것 같지만 스트레스를 받는 폴더 구조...
항상 폴더 구조가 일관성 없이 바뀌고 뭔가 명확하게 정립되지 않아 많은 고민을 해왔음.
마침 제로초님의 프론트엔드 폴더 구조에 관한 유투브 영상을 보고 정리해 보고자 함.
기존
// src 하위
assets
components
ㄴ 공통 컴포넌트 폴더
ㄴ ex) 커스텀 버튼
ㄴ ex) 커스텀 인풋 등
ㄴ pages 폴더와 같은 이름을 가진 폴더
ㄴ 페이지의 하위 구성 요소 컴포넌트(프리젠테이션 컴포넌트)
lib
ㄴ utils
ㄴ hooks
ㄴ styles(커스텀 스타일, styled components global styles...)
ㄴ api
pages
ㄴ ex) 로그인 폴더
ㄴ ex) 메인 폴터
ㄴ ex) 블로그 메인
store
ㄴ actions
ㄴ reducers
ㄴ index.ts(combine reducer)
ㄴ types.ts
//* store에서 사용하는 type들은 최대한 가까이 있는 것을 선호
types
ㄴ 전역에서 쓰이는 타입 등
assets폴더는 다들 아실 것이라 생각하고, components 폴더에는 어디에서든 사용할 수 있는 공통 컴포넌트들
page의 주제를 딴 폴더에서는 pages에서 쓰이는 하위 컴포넌트들
lib 폴더에서는 유틸성 함수, 훅, 전역 스타일, api 요청 instance 등
store에서는 리덕스 전역 state 정의
types에서는 앱 전역에서 쓰일 수 있는 타입들
각 컴포넌트에서 부모에게 받는 prop 타입은 각 파일에서 선언
프로젝트를 만들 때 마다 항상 폴더의 구조가 다르고 일관성이 없었고, 그나마 위의 패턴이 velopert님 velog
폴더 구조를 조금 참고해 사용하고 있는 패턴 이었다. 그래도 폴더 구조에 대한 갈증은 마르지 않았다.
찰나에 제로초님의 유투브에서 프론트엔드 폴더 구조에 대한 이야기가 올라왔다.
일명 FSD(Feature-Sliced Design) 라고 한다.
FSD 는 크게 레이어(layer), 슬라이스(slice), 세그먼트(segment)의 세 가지로 나뉘게 된다.
Layer
최상위 폴더이며 레이어의 수는 최대 7개
app: 초기화되는 곳. 프로바이더, 라우터, 전역 스타일, 전역 타입 선언 등이 정의. 애플리케이션의 진입점 역할.
//* main.tsx와 같이 전역에서 사용할 수 있는 context로 감싸진 *//
processes?: 여러 페이지에 걸쳐 있는 프로세스를 처리. 더 이상 사용되지 않지만 가끔 사용. deprecated !
pages: 애플리케이션의 페이지.
widgets: 페이지에 사용되는 독립적인 UI 컴포넌트.
/* 기존의 layout을 담당하는 폴더 */
features?: 비즈니스 가치를 전달. 좋아요, 리뷰 작성, 제품 평가 등.
entities?: 비즈니스 엔티티. 사용자, 리뷰, 댓글 등이 포함될 수 있음
//* 기존의 components 역할을 하는 폴더 *//
shared: 특정 비즈니스 로직에 종속되지 않은 재사용 가능한 컴포넌트와 유틸리티. UI 키트, axis 설정, 애플리케이션 설정, 비즈니스 로직에 묶이지 않은 헬퍼 등.
** 규칙 **
하위 레이어에서는 상위 레이어를 호출 할 수 없으며, 하위 레이어는 상위 레이어의 곳곳에 사용되기 때문에
하위 레이어의 변경은 많은 상위 레이어의 부수 효과를 발생하기 때문에 조심 해야 함.
슬라이스
슬라이스라는 하위 디렉토리는 특정 비즈니스 엔티티에 대한 것. 슬라이스의 주요 목표는 코드를 값별로 그룹화하는 것.
이 디렉토리에 있는 코드는 직접적으로 공유되지 않아야 함.
세그먼트
각 슬라이스는 세그먼트로 구성. 슬라이스 내의 코드를 나누는 데 도움.
api - 필요한 서버 요청.
UI - 슬라이스의 UI 컴포넌트.
model - 비즈니스 로직, 즉 상태와의 상호 작용. actions 및 selectors가 이에 해당
lib - 슬라이스 내에서 사용되는 보조 기능.
config - 세그먼트는 거의 필요하지 않음.
consts - 상수.
공개 API
각 슬라이스와 세그먼트에는 공개 API가 있고, index.ts파일에서 필요한 api만 외부로 공개
나머지는 내부에서만 사용될 수 있도록 한다.
이 컨셉의 구조가 아직 정확하게 이해가 가지 않는 부분이 많고, 더 공부를 해 봐야 겠지만,
전에 사용하던 구조와는 다르게 기준이 있고, 규제를 통한 일관성을 통해 정말 레고와 같이 컴포넌트를 조립한다
라는 느낌이 강하게 들었다. 정말 잘 이해하고 사용한다면 좋은 컨셉이 될 것 같지만,
진입 장벽이 높아 명확하게 이해하고 활용하지 않는다면 독이 될 수도 있을 거라는 생각이 들었다.
개인 프로젝트나 소규모 프로젝트에는 뭔가 적합하지 않다는 생각이다.
아직 명쾌하게 해소되지는 않았지만, 조금 더 고민하고 공부해 봐야할 명분이 생긴 것 같다.
# React 폴더 구조 ### 계기 항상 리액트 개발을 하며 별거 아닌 것 같지만 스트레스를 받는 폴더 구조... 항상 폴더 구조가 일관성 없이 바뀌고 뭔가 명확하게 정립되지 않아 많은 고민을 해왔음. 마침 제로초님의 프론트엔드 폴더 구조에 관한 유투브 영상을 보고 정리해 보고자 함. ### 기존 ```js // src 하위 assets components ㄴ 공통 컴포넌트 폴더 ㄴ ex) 커스텀 버튼 ㄴ ex) 커스텀 인풋 등 ㄴ pages 폴더와 같은 이름을 가진 폴더 ㄴ 페이지의 하위 구성 요소 컴포넌트(프리젠테이션 컴포넌트) lib ㄴ utils ㄴ hooks ㄴ styles(커스텀 스타일, styled components global styles...) ㄴ api pages ㄴ ex) 로그인 폴더 ㄴ ex) 메인 폴터 ㄴ ex) 블로그 메인 store ㄴ actions ㄴ reducers ㄴ index.ts(combine reducer) ㄴ types.ts //* store에서 사용하는 type들은 최대한 가까이 있는 것을 선호 types ㄴ 전역에서 쓰이는 타입 등 ``` assets폴더는 다들 아실 것이라 생각하고, components 폴더에는 어디에서든 사용할 수 있는 공통 컴포넌트들 page의 주제를 딴 폴더에서는 pages에서 쓰이는 하위 컴포넌트들 lib 폴더에서는 유틸성 함수, 훅, 전역 스타일, api 요청 instance 등 store에서는 리덕스 전역 state 정의 types에서는 앱 전역에서 쓰일 수 있는 타입들 각 컴포넌트에서 부모에게 받는 prop 타입은 각 파일에서 선언 프로젝트를 만들 때 마다 항상 폴더의 구조가 다르고 일관성이 없었고, 그나마 위의 패턴이 velopert님 velog 폴더 구조를 조금 참고해 사용하고 있는 패턴 이었다. 그래도 폴더 구조에 대한 갈증은 마르지 않았다. 찰나에 제로초님의 유투브에서 프론트엔드 폴더 구조에 대한 이야기가 올라왔다. 일명 FSD(Feature-Sliced Design) 라고 한다. FSD 는 크게 레이어(layer), 슬라이스(slice), 세그먼트(segment)의 세 가지로 나뉘게 된다. > # Layer > > 최상위 폴더이며 레이어의 수는 최대 7개 > > app: 초기화되는 곳. 프로바이더, 라우터, 전역 스타일, 전역 타입 선언 등이 정의. 애플리케이션의 진입점 역할. > > //* main.tsx와 같이 전역에서 사용할 수 있는 context로 감싸진 *// > > processes?: 여러 페이지에 걸쳐 있는 프로세스를 처리. 더 이상 사용되지 않지만 가끔 사용. deprecated ! > > pages: 애플리케이션의 페이지. > > widgets: 페이지에 사용되는 독립적인 UI 컴포넌트. > > /* 기존의 layout을 담당하는 폴더 */ > > features?: 비즈니스 가치를 전달. 좋아요, 리뷰 작성, 제품 평가 등. > > entities?: 비즈니스 엔티티. 사용자, 리뷰, 댓글 등이 포함될 수 있음 > > //* 기존의 components 역할을 하는 폴더 *// > > shared: 특정 비즈니스 로직에 종속되지 않은 재사용 가능한 컴포넌트와 유틸리티. UI 키트, axis 설정, 애플리케이션 설정, 비즈니스 로직에 묶이지 않은 헬퍼 등. > > ## ** 규칙 ** > > 하위 레이어에서는 상위 레이어를 호출 할 수 없으며, 하위 레이어는 상위 레이어의 곳곳에 사용되기 때문에 > > 하위 레이어의 변경은 많은 상위 레이어의 부수 효과를 발생하기 때문에 조심 해야 함. > > # 슬라이스 > > 슬라이스라는 하위 디렉토리는 특정 비즈니스 엔티티에 대한 것. 슬라이스의 주요 목표는 코드를 값별로 그룹화하는 것. > > 이 디렉토리에 있는 코드는 직접적으로 공유되지 않아야 함. > > # 세그먼트 > > 각 슬라이스는 세그먼트로 구성. 슬라이스 내의 코드를 나누는 데 도움. > > api - 필요한 서버 요청. > > UI - 슬라이스의 UI 컴포넌트. > > model - 비즈니스 로직, 즉 상태와의 상호 작용. actions 및 selectors가 이에 해당 > > lib - 슬라이스 내에서 사용되는 보조 기능. > > config - 세그먼트는 거의 필요하지 않음. > > consts - 상수. > > ## 공개 API > > 각 슬라이스와 세그먼트에는 공개 API가 있고, index.ts파일에서 필요한 api만 외부로 공개 > > 나머지는 내부에서만 사용될 수 있도록 한다. 이 컨셉의 구조가 아직 정확하게 이해가 가지 않는 부분이 많고, 더 공부를 해 봐야 겠지만, 전에 사용하던 구조와는 다르게 기준이 있고, 규제를 통한 일관성을 통해 정말 레고와 같이 컴포넌트를 조립한다 라는 느낌이 강하게 들었다. 정말 잘 이해하고 사용한다면 좋은 컨셉이 될 것 같지만, 진입 장벽이 높아 명확하게 이해하고 활용하지 않는다면 독이 될 수도 있을 거라는 생각이 들었다. 개인 프로젝트나 소규모 프로젝트에는 뭔가 적합하지 않다는 생각이다. 아직 명쾌하게 해소되지는 않았지만, 조금 더 고민하고 공부해 봐야할 명분이 생긴 것 같다. <a href="https://emewjin.github.io/feature-sliced-design/?utm_source=substack&utm_medium=email" target="_blank">[참고]</a>