-
Notifications
You must be signed in to change notification settings - Fork 0
팀 어썸 오렌지가 Feature 기반 폴더 구조를 채택한 이유
저희 프로젝트는 다른 프로젝트와 다르게, feature 기반의 폴더 구조를 채택하고 있어요. 간략히 말하자면, 연관된 피처를 담당하는 컴포넌트나 훅 등 코드들을 하나의 코드로 묶는 폴더 전략이에요. 팀 어썸 오렌지는 왜 feature 기반 폴더 구조를 채택했을까요?
.
├── components/
│ ├── common/
│ │ └── modal
│ ├── introSection
│ ├── simpleIntroduction
│ └── interaction
├── hooks/
│ └── interaction
├── utils
├── pages
└── constants
전통적인 프론트엔드 프로젝트는 위의 형태의 폴더 구조를 채택하고 있어요. 사실, 저희도 이전에 프로젝트를 했을 때에는 위의 폴더 구조를 따랐었어요. 이 폴더 구조는 파일의 유형에 따라서 파일을 그룹짓는다는 특징이 있어요. 이 폴더 구조를 "유형 기반 폴더 구조"라고 부르기로 해요.
이 폴더 구조는 컴포넌트는 컴포넌트끼리, 훅은 훅끼리 분류되어 있기 때문에 심리적으로 편안하다는 이점이 있고, 새로운 파일을 생성할 때 파일의 유형에 따라 파일을 위치하면 되기 때문에 파일 위치가 편하다는 이점이 있어요. 또한, 각 폴더가 특정 구조만의 파일을 포함하므로 폴더의 역할이 명확하다는 이점도 있다고 해요.
이렇게 좋아 보이는 유형 기반 폴더 구조지만, 저희의 경험상 유형 기반 폴더 구조는 문제가 있었어요. 유형 기반 폴더 구조는 유사한 기능을 담당하는 파일들이 이리저리 찢어져 있다는 특징이 있는데, 아래의 문제점은 유형 기반 폴더 구조의 특징에서 비롯되는 문제에요.
import { * as Status} from "../../../../constants/fcfsConstants";
가장 큰 문제점은 연관된 기능을 개발할 때, 유사한 기능을 가진 폴더를 찾기 매우 어렵다는 것에 있어요. 예를 들어, 선착순 이벤트라는 기능을 개발한다고 하면, 선착순 이벤트에서 사용되는 상수를 불러오기 위해, 프로젝트의 루트 폴더로 내려갔다가, constants 폴더를 찾은 뒤 선착순 이벤트에 있는 기능을 찾아야 해요. 이는 컴포넌트와 훅의 로직이 결합되어 있는 상황에서 더 심각해져요.
또 다른 단점은, 단일 파일 단위로는 재사용이 가능하지만, 기능 단위로 재사용을 하기가 어렵다는 점이 있어요. 유형 기반 폴더 구조는 유사한 기능을 가진 파일들이 찢어져 있기 때문에, 기능 자체를 다른 프로젝트에 사용하려면 찢어져 있던 기능을 모아서 한 데 묶고, 그것을 유형 기반 폴더 구조를 가지는 다른 프로젝트에 적용시키려면 기능들을 또다시 찢어야 한다는 문제가 있어요.
.
├── common/
│ └── modal/
│ ├── index.jsx
│ ├── openModal.js
│ └── store.js
└── mainPage/
├── introSection
├── simpleIntroduction
└── interaction
그래서 저희는 Feature 기반 폴더 구조를 채택했어요. Feature 기반 폴더 구조는 유사한 기능을 가진 파일들을 한 데 묶어서, 기능 개발 중 탐색을 용이하게 하는 것에 그 목적이 있어요. 저희 프로젝트는 여러 개의 섹션으로 구성되어 있고, 각각의 섹션에서 재사용되는 로직이 많지 않을 것이라고 판단해서, 유형 기반 폴더 구조의 파일 재사용성이 도움이 되지 않는다고 판단했어요. 오히려, 각각의 feature 자체를 다른 곳에서도 쓸 수 있는 확장성(인터랙션을 재사용한다면?)을 위해서는 Feature 기반 폴더 구조가 더 유리하다고 생각했어요. 또한, 저희의 백로그 요구 사항은 무려 165개에 달하기 때문에, 파일을 탐색하는 시간이라도 줄여서 개발 시간을 확보하여, 개발의 효율성을 높이고자 Feature 기반 폴더 구조를 채택하게 되었어요.
간혹 하나의 Feature에 있는 기능을 다른 feature에서 참조해야 할 때가 있어요. 하지만, 동일한 계층에 있는 feature를 다른 feature에서 참조하게 된다면, 코드의 의존성이 복잡해질 것이라고 생각했어요. 또한, 어느 feature에도 소속되지 않은 단순 컴포넌트나, 여러 곳에서 사용되는 공통 feature 등이 있을 수 있다고 생각했어요.
저희는 이 문제를 shared라는 폴더 계층을 두는 것으로 해결했어요. shared 폴더는 두 개 이상의 기능에 대해 참조되거나, 어느 feature에도 소속되지 않은 파일을 모아놓은 폴더에요. 이 때, shared 폴더는 shared-feature 폴더와 components/hooks 폴더로 구분되어요. components/hooks 폴더는 shared 내에서도 feature로 구분하기 애매한 공통 컴포넌트/훅을 모아놓은 폴더로, 기존 유형 기반 폴더 구조의 명확성과 단일 컴포넌트 재사용성을 챙기고자 했어요.
-
🎯 기술적 선택 이유
-
✨ UX 및 접근성
-
#️⃣ 코드 퀄리티
-
🛠️ 구현