리액트의 보편적인 폴더 구조는 아래와 같습니다.
-page
-components
-hooks
-utils
-constants
-store
-...
위 보편적인 구조라도 각 폴더 내부에서 컨벤션을 정할 게 정말 많습니다.
특히 매일 가장 많이 생산되는 컴포넌트의 컨벤션이 가장 논의가 많이되고, 그만큼 고민이 많다.
components
- Button
- Header
- Skeleton
- LandingModal
- LandingButton
- CreateProjectNavigation
- GenerateProgressBar
components
- @common(공통되는 것)
- Button
- Header
- Skeleton
- Landing(관심사)
- LandingModal
- LandingButton
- CreateProjectNavigation
- GenerateProgressBar
components
- @common(공통되는 것)
- Button
- Header
- Skeleton
- Landing(관심사)
- @common(관심사 안에서 공통되는 것)
- LandingModal
- LandingButton
- Create(역할별)
- CreateProjectNavigation
- GenerateProgressBar
components
- Landing(관심사)
- @common(관심사 안에서 공통되는 것)
- LandingModal
- LandingButton
- Create(역할별)
- CreateProjectNavigation
- GenerateProgressBar
components
- Landing(관심사)
- @common(관심사 안에서 공통되는 것)
- LandingModal
- LandingButton
- Create(역할별)
- CreateProjectNavigation
- NavigationButton ✅
- index.tsx
- index.tsx
- Fallback.tsx
- ErrorFallback.tsx
- GenerateProgressBar
등등...
위 설명을 제외하고 아토믹 디자인 패턴과 같이 다양한 폴더 구조 패턴들에 대한 방법이 정말 많을 것이다.
저희는 충분한 고민 끝에 마지막 방법을 활용하고 있습니다.
각 관심사 내부에서 역할 별로 컴포넌트를 구분하고 내부에서만 사용되는 컴포넌트는 같은 Depth에 선언해 응집도를 유지하였습니다.
또한, Suspense, ErrorBoundary를 활용하는 컴포넌트에 대해선 Fallback, ErrorFallback 또한 같은 Depth에 선언에 응집도를 유지하였습니다.
저희 제품은 Landing이라는 관심사 안에서 Create, Edit 등의 역할에서 사용되는 컴포넌트가 너무 명확하게 잘 나눠져 있어 위방법을 채택하였다.
글쓴이가 2년 동안 느낀바로 두개의 기업에서 매일 컴포넌트를 만들며 느낀 가장 좋은 방법은 팀원들과 함께 논의하고 결정한 구조라고한다.
결국 프로젝트는 회사에 종속되고, 사내 개발자들이 보기에 쉬운 코드 및 구조가 좋은 구조일 테니까요.
요즘에 FE 트렌드로 보통 서버 상태 관리에 @tanstack/query 클라이언트 전역 상태 관리에 jotai, zustand, recil 을 많이 활용하시는 것 같다
글쓴이는 각 역할을 가진 건 컨테이너화를 해야 가독성 및 유지보수가 좋아진다고 생각한다.
tanstack/query를 예로 들면 일단 서버 상태 관리 라는 큰 틀안에서 key도 관리하고, api도 관리하고, 각 hook들도 관리하는 경우가 많은데, 파편화 되어있으면 유지보수 측변에서 좋은 지먼을 가져가긴 힘들다고 생각이 들어요.
- store
- hooks
- queries
- mutations
- ... 다양한 custom hook
기존엔 mutations, queries도 결국 hook이니 hooks 폴더에 함께 넣어주는 구조였습니다.
useOnClickOutside와 같이 기본적인 util hook들은 따로 monorepo package에 넣어줬음에도 불구하고 다양한 custom hook들이 생기면서 뒤섞여 찾아가기 힘들어지는 문제점이 생겼습니다.
또한, hooks라는 폴더의 역할이 너무 방대해진 느낌이 들어 hooks엔 custom hook캡슐화의 역할만 해주는 것들을 관심사에 맞게 모아놓기로 하였습니다.