본문 바로가기
Project/관리하당

폴더구조의 Best Practice를 찾아서

by 이의찬 2023. 11. 30.

1. Why?

잘 정리된 폴더구조는 깔끔하게 정리된 수납장과 같다. 깔끔하게 폴더구조를 정리해둠으로 인해서 통일된 '멘탈 모델'을 만들고, 이에 대한 리소스 투입을 줄여 개발에서의 능률을 향상시킬 수 있다고 생각한다.

SSAFY에서의 첫 프로젝트인 스타게이트를 진행하면서 이를 크게 체감할 수 있었는데, Atomic 패턴 사용을 위해 컴포넌트들을 atoms, molecules, pages로 분리한 다음 src폴더에 플랫하게 두었다가 구조와 생각이 잔뜩 꼬이는 경험을 했다. 이 때, 폴더구조는 단순히 담아두는 것 이상의, 멘탈모델이라는 것을 실감할 수 있었다.

 

싸피에서의 첫 프로젝트였던 스타게이트 이후 두 차례의 프로젝트를 더 진행하면서 폴더구조 관련 고민한 포인트들을 작성해보고자 한다.


2. 모익(Next.js / App Routing)

 

모익은 React를 사용했던 스타게이트와는 달리, Next.js 13버전을 사용하면서 App Routing 방식을 사용하기로 합의되어 있었다. 

문제

React로 구현한 기존의 방식은 pages 폴더에 page들을, component 폴더에 컴포넌트를 단계별로 분리해두는 심플한 구조였지만, App Routing의 경우에는 App 폴더 내부에 page 파일을 생성하면 자동적으로 연결되는 방식이였다.

 

그렇기에 상대적으로 관심사의 분리가 쉽지 않을 것으로 예상해 Atomic 패턴을 사용하지 않는 것도 고려했지만, Atomic 패턴을 통한 재사용성과 일관성을 포기하는 것이 아쉬웠기에 결국 도입하는것으로 결정했다.

mockup을 atomic 패턴에 맞게 분류한 모습

모익의 경우에는 App Routing으로 인해 컴포넌트의 위치를 두 부분으로 나누었다.

  • 공용 컴포넌트는 src/component/단계별 component
  • 관심사별 컴포넌트는 src/app/관심사/단계별 component

component폴더 - 단계별로 구현된component
app - 관심사 - 단계별 분류된 component

결과

득보다는 실이 많은 방식이였다. 단점을 간략하게 적자면

  •  컴포넌트가 공용이냐 혹은 하나의 관심사에서만 사용되느냐에 따라서 나누고, 단계별로 또 나눔
    • 지나치게 나눈 부작용으로 component가 하나밖에 없는 폴더도 있었음
  • 하나의 관심사에서 사용할 계획이였으나 다른 관심사에서도 사용해야 한다면? 관심사 폴더에서 공통 컴포넌트 폴더로 이동해야함
    • 공통 컴포넌트와 관심사별 컴포넌트를 함께 사용하는 경우, "src/component/단계별 component"와 "src/app/관심사/단계별 component"를 오가야함
    • => 결국 이를 신경쓰면서 생각이 꼬임 -> 리소스 소모!
  • 이 글에서도 말했었지만 대부분의 organisms가 하나의 기능에만 종속되어 있게 되었음

이는 Atomic 패턴 자체의 문제라기 보다는 App Routing 방식임에도 불구하고 기존의 방식처럼 관심사별 컴포넌트와 공통 컴포넌트를 분리하는 방식을 선택한 나의 잘못이라고 생각한다.

추후 개선 방안

추후에 Next.js App Routing 방식 프로젝트를 하게 된다면

  • "src/component/단계별 component"에 모든 컴포넌트를 몰아두고
  • "src/app" 폴더 내부에는 page와 template 등 라우팅에 필요한 요소들만 넣어두겠다.

3. 관리하당(React-Native)

컴포넌트의 경우

모익에서 아쉬웠던 점을 해결하기 위해 다음과 같이 합의하였다.

  • 최대한 재사용성을 높여서 UI 설계
  • 관심사로 컴포넌트를 분류하지 않고, 모든 컴포넌트를 component폴더에서 단계별로 분류

간략하게 표현하자면 이런데(Templates는 사용하지 않았음)

└─src
    ├─component
    │  ├─atoms
    │  ├─molecules
    │  └─organisms
    └─screens

 

관심사로 컴포넌트를 분류하지 않고, 모든 컴포넌트를 모아둔다는 점에서 스타게이트에서 사용했던 방식과 굉장히 유사하다. (molecules 사용하지 않았음)

└─src
    ├─atoms
    ├─organisms
    └─pages

그런데 스타게이트 글을 읽어봤다면 알겠지만, 저 때 컴포넌트가 미친듯이 쌓여서 관리가 어려워졌고, 결국 각 폴더 내에서 관심사별로 컴포넌트를 분리하는 응급처방을 한 적이 있다.

떠오르는 악몽

이미 실패했다고 생각했던 방식, 관심사 분류 하지 않고 컴포넌트를 계층별로만 분리하는 방식으로 되돌아 간 이유는

  • 모익에서의 부작용 해결 가능
    • 지나치게 자세한 분리로 인한 깊은 depth 대신 단계별 분리만
    • 관심사 / 공통 컴포넌트 폴더 분류에 대한 고민 X
    • 관심사 폴더에 있는 컴포넌트도 다른 관심사에서 사용하는 순간 공통 컴포넌트로 이동시켜야 하는 불편함 해결
  • 기존의 문제점인 지나치게 많은 컴포넌트 문제 해결방안 
    • UI 기획 단계에서 최대한 같은 형식의 컴포넌트 재사용 빈도를 높여서 기획
    • 또한 컴포넌트의 재사용성과 유연성을 높이기 위해서 노력
      • 공통된 형식의 styled component를 만들고 상속받는 형식으로 컴포넌트를 제작
      • defalut 컴포넌트를 만들어서 이를 재사용
      • 컴포넌트가 만약 하나의 관심사에 종속된다면, 이름 앞에 이를 붙여서 네이밍해서 구분이 쉽게 함

이를 통해 불편함을 줄일 수 있었다. "관리하당"에서는 best practice에 가깝다고 생각한다. 

 

하지만, 컴포넌트의 숫자가 위 방식으로 컨트롤할 수 있는 수준을 넘어간다면 그때는 모익의 방식이 더 유리할 수 있다. 상황에 알맞은 방식을 차용해야 할 듯 하다.

전체 폴더 구조

컴포넌트를 제외한 다른 폴더는 아래와 같이 분류했다.

└─src
    ├─apis
    ├─assets
    │  ├─icon
    │  └─img
    ├─config
    ├─hooks
    ├─navigation
    ├─redux
    │  ├─slice
    │  └─store
    ├─screens
    │  ├─auth
    │  ├─bloodsugar
    │  └─...etc(생략)
    ├─styles
    ├─types
    │  └─api
    │     ├─request
    │  	  └─response
    └─utils
  • apis : apis를 호출하는 함수 폴더
  • hooks : 커스텀 hook이 담겨있는 폴더
  • styles : 공통으로 사용되는 style component들(button, card 등)을 담았다.
  • type : 공통으로 사용되는 type, interface들을 담았다.
    • api 폴더에는 api 호출시 사용되는 타입이 담겨 있으며, api폴더는 다시 requset / response에 따라 나눴다.
  • utils : 모듈화된 함수들이 담겨있는 폴더, 중복해서 사용되는 함수들을 담았다.

4. 래퍼런스

 

Next.js 폴더/파일 구조 잡기

주니어 개발자들이 가장 많이 물어보는 질문이 폴더 구조에 대해 묻는 것이다. 사실 이런 질문들은 항상 답이 정해져있다. “그때 그때 달라요” 아니 시발 그때 그때 다른게 어딨어? 하고 빡이

miriya.net

 

App Router | Next.js

Use the new App Router with Next.js' and React's latest features, including Layouts, Server Components, Suspense, and more.

nextjs.org