리액트 프로젝트를 시작할 때 가장 먼저 해야하는 것 중 하나가 바로 폴더 구조를 결정하는 것이다.
폴더 구조가 잘 설계 되었다면 프로젝트 규모가 커져도(폴더와 파일이 많아져도) 원하는 폴더, 파일을 찾아가는 것이 어렵지 않을 것이다.
즉 폴더 구조는 클린 코드와 같이 가독성을 위해 중요한 요소이며, 코드의 유지 보수성을 증가시킨다.
프로젝트마다 폴더 이름은 조금씩 다룰 수 있지만, 가장 많이 볼 수 있는 형태의 폴더 구조이다.
백엔드와 연결하는데 필요한 함수, 백엔드에서 받아온 파일을 처리하는 로직 등을 저장하고 있는 폴더
// 예시
export const axios = Axios.create({
baseURL: process.env.BASE_URL,
});
폰트, 이미지 등 컴포넌트 렌더링에 필요한 파일을 저장하는 폴더이다.
재사용 가능한 컴포넌트들을 모아 저장하는 폴더이다.
일반적으로 프로젝트가 커질 수록 많은 컴포넌트가 필요해지기 때문에 하위 폴더를 통해 컴포넌트를 분류하여 가독성을 높인다.
커스텀 훅을 모아 저장한 폴더
타입스크립트 사용시에 Type으로 사용할 인스턴스를 정의해 둔 폴더
서브 라우팅, private 라우팅 등의 라우트를 관리하는 폴더
프로젝트 전체에서 사용하는 환경 변수, 설정을 포함하여 config
폴더로 명명해 함께 관리할 수도 있다.
redux
, mobx
등의 상태 관리 저장소를 사용할 경우 관련 파일을 모아 놓은 폴더
Context API
를 사용할 경우 주로 context라고 한다.
UI 스타일 적용에 필요한 color
, font-size
등의 상수 값을 모아놓은 폴더
어플리케이션에 필요한 각종 로직 함수를 모아놓은 폴더
수치 연산, 정규식 표현 함수 등이 포함된다.
하나의 페이지, 레이아웃 등 컴포넌트 여러개가 쌓여 이루어지는 보다 큰 단위의 컴포넌트를 모아 놓은 폴더
위와 같은 구조는 프로젝트 초기에도 큰 어려움 없이 적용할 수 있는 구조라는 장점이 있다.
그러나 프로젝트 규모가 점점 커져 페이지, 컴포넌트, 커스텀 훅, 로직 등이 늘어날 수록 한 폴더안에 존재하는 파일이 많아져 가독성이 저하된다는 한계가 있다.
이로인해 Bast Practice에서는 기능별 폴더구조를 사용할 것을 권장한다.
참고자료
기능별 폴더구조와 기존 폴더구조의 차이점은 앞서 설명한 폴더 구조를 각 기능별로 갖도록 한다는 것이다.
우선 기존의 components
폴더에는 전체 프로젝트 또는 여러 모듈이 공통으로 사용하는 최소 단위의 컴포넌트만 남겨 놓는다.
그리고 기존의 page
대신 features
폴더를 생성해 각 기능별로 하위 폴더를 갖게 한다.
기능별 하위 폴더의 구조는 다음과 같다.
src/features/awesome-feature
|
+-- api # exported API request declarations and api hooks related to a specific feature
|
+-- assets # assets folder can contain all the static files for a specific feature
|
+-- components # components scoped to a specific feature
|
+-- hooks # hooks scoped to a specific feature
|
+-- routes # route components for a specific feature pages
|
+-- stores # state stores for a specific feature
|
+-- types # typescript types for TS specific feature domain
|
+-- utils # utility functions for a specific feature
|
+-- index.ts # entry point for the feature, it should serve as the public API of the given feature and exports everything that should be used outside the feature
이렇게 각 기능이 내부에서 사용하는 로직, 컴포넌트, 에셋 등을 하나의 폴더 안에서 관리 한다.
이렇게 되면 새로운 기능이 추가되더라도 공용 로직, 컴포넌트가 추가될 여지가 적으며, 새로운 기능 폴더를 생성하여 그 안에서 관리하면 된다는 장점이 있다.
다만 이는 프로젝트 규모가 작을 때 필요 이상의 복잡성을 유발할 수 있으므로, 프로젝트 규모를 고려해서 가장 효율이 좋은 방법을 선택하는 것이 좋을 것이다.