리팩토링의 시작: 폴더 구조부터 정리하기
이 프로젝트를 시작할 때 폴더 구조나 아키텍처에 대한 개념이 부족했다. 기능을 추가하는 데 집중하다 보니 폴더 구조는 점점 복잡해졌고 유지보수가 어려운 상태가 되었다. 코드가 어디에 위치해야 하는지 명확하지 않아 개발 속도가 느려지고 협업에도 문제가 발생하기 시작했다.
이 문제를 해결하기 위해 폴더 구조를 정리하기로 했고 다양한 프론트엔드 아키텍처를 조사했다.
리액트 환경에서 유지보수성과 확장성을 고려했을 때 Feature-Sliced Design(FSD) 아키텍처가 적합하다고 판단했다.
기존 폴더 구조
기존 폴더 구조는 기능별 분류가 명확하지 않았고 코드가 여러 곳에 흩어져 있어 유지보수가 어려웠다.
├── apis/
│ ├── codingzone-api.js
│ ├── index.js
│ ├── index2.js
├── components/
│ ├── BlogForm.js
│ ├── Card.js
│ ├── czCard.js
│ ├── Footer.js
│ ├── NavBar.js
│ ├── Pagination.js
│ ├── ToastEditor.js
├── Modals/
│ ├── findpassword.js
│ ├── LoginForm.js
│ ├── Mypage.js
│ ├── Newpassword.js
│ ├── signupForm.js
│ ├── signupinfo.js
├── pages/
│ ├── Article/
│ │ ├── ArticleMain.js
│ │ ├── CreatePage.js
│ │ ├── EditPage.js
│ │ ├── ShowPage.js
│ ├── Coding-zone/
│ │ ├── CodingZoneMain.js
│ │ ├── CodingZoneAttendance.js
│ │ ├── CodingZoneManager.js
│ │ ├── CodingZoneRegist.js
├── App.js
├── index.js
├── index.css
└── reportWebVital.js
문제점
- 기능별 코드가 명확히 분리되지 않음 → components/, pages/, apis/ 등에 코드가 혼재되어 있어 유지보수가 어려웠다.
- API 구조가 일관되지 않음 → apis/ 폴더 내 모든 API가 모여 있어 특정 기능과 연관된 API를 찾기 어려웠다.
- 컴포넌트 재사용성이 떨어짐 → 기능별 분류가 명확하지 않아 불필요한 코드 중복이 발생했다.
FSD 기반으로 폴더 구조 개편
FSD(Feature-Sliced Design)는 프론트엔드 애플리케이션을 "기능(feature)" 중심으로 구성하는 아키텍처 패턴이다.
이는 애플리케이션을 도메인과 기능별로 나누고 모듈성을 극대화하여 유지보수성과 확장성을 높이는 방식을 따른다.
FSD는 크게 레이어(Layers), 슬라이스(Slices), 세그먼트(Segments) 개념을 활용하여 프로젝트를 구조화한다.
FSD의 주요 개념
1) Layers(레이어) - 코드의 역할을 명확하게 분리
FSD는 코드를 역할별로 레이어를 나누어 관리한다. 대표적인 레이어는 다음과 같다.
- app: 애플리케이션의 엔트리 포인트와 글로벌 설정을 포함
- processes: 여러 기능을 조합한 비즈니스 로직을 관리 (예: 결제 프로세스, 인증 흐름)
- pages: 특정 URL(라우트)과 연결된 페이지 컴포넌트
- widgets: 독립적으로 사용되는 UI 컴포넌트 (예: 카드, 버튼, 네비게이션 바 등)
- features: 애플리케이션의 주요 기능 (예: 로그인, 게시글 작성, 댓글 관리 등)
- entities: 데이터 모델과 API 연동을 담당 (예: 사용자, 게시글, 상품 데이터)
- shared: 여러 기능에서 공통적으로 사용하는 유틸리티, 스타일, API, 공통 컴포넌트 등
2) Slices(슬라이스) - 기능 단위로 코드 구성
각 레이어는 기능(feature) 단위로 코드를 구성한다.
예를 들어 features/ 레이어 내에서는 "게시글 작성", "댓글 관리" 등의 기능별로 폴더를 나누어 관리할 수 있다.
3) Segments(세그먼트) - 내부 구조 세분화
각 기능(Slice) 내부에서도 UI, 모델, API 등을 논리적으로 분리할 수 있다.
예를 들어 features/Post 폴더 내부에 ui/, model/, api/ 등을 구성하여 코드의 역할을 명확히 할 수 있다.
새로운 폴더 구조에서는 레이어(Layers) 를 기반으로 프로젝트를 구성하고 기능별(Slices)로 세분화했다.
app 레이어
├── app
│ ├── App.js
│ ├── index.js
│ ├── index.css
│ └── reportWebVitals.js
- 프로젝트의 진입점(entry point)과 글로벌 설정 파일을 포함한다.
- 기존에는 App.js와 index.js가 최상단에 위치했지만 이를 app/ 폴더로 이동하여 프로젝트 구조를 명확하게 정리했다.
entities 레이어
├── entities
│ ├── api
│ │ ├── ArticleApi.js
│ │ ├── UserApi.js
│ │ ├── CodingZone/
│ │ │ ├── AdminApi.js
│ │ │ ├── StudentApi.js
- 데이터 모델 및 API 호출을 담당하는 레이어로, 비즈니스 도메인과 관련된 엔티티(entity)를 관리한다.
- 기존에는 apis/ 폴더 안에 모든 API가 모여 있었지만, 기능별 API를 entities/api/ 내부에서 관리하여 유지보수성을 높였다.
features 레이어
├── features
│ ├── ArticlePage/
│ │ ├── BlogForm.js
│ │ ├── hooks/
│ │ │ ├── useBlogForm.js
│ ├── CodingZone/
│ │ ├── CodingZoneAttendance.js
│ │ ├── CodingZoneManager.js
│ │ ├── CodingZoneRegist.js
- 각 기능을 독립적인 모듈로 관리하여 유지보수를 쉽게 한다.
- 기존 pages/ 폴더에 있던 특정 기능 관련 코드들을 features/로 이동하여 기능 단위 개발이 가능하도록 개선했다.
pages 레이어
├── pages
│ ├── Article/
│ │ ├── ArticleMain.js
│ │ ├── CreatePage.js
│ │ ├── EditPage.js
│ │ ├── ShowPage.js
- 특정 라우트와 직접 연결되는 페이지 컴포넌트를 포함한다.
- features/와 pages/의 차이는 features/는 특정 기능을 담당하고 pages/는 라우트 단위로 관리된다.
shared 레이어
├── shared
│ ├── api/
│ │ ├── AuthApi.js
│ │ ├── EmailApi.js
│ ├── components/
│ │ ├── BaseModal.js
│ │ ├── BaseModal.module.css
- 여러 기능에서 공통적으로 사용되는 코드들을 포함한다.
- 기존에는 Modals/에 있던 로그인/회원가입 관련 모달을 shared/components/로 이동하여 다른 기능에서도 쉽게 재사용 가능하도록 변경했다.
widgets 레이어
└── widgets
├── layout/
│ ├── Footer.js
│ ├── Navbar.js
│ ├── Card.js
│ ├── Pagination.js
- 독립적으로 사용되는 UI 컴포넌트들을 포함한다.
- 기존 components/ 폴더에 섞여 있던 UI 요소들을 widgets/로 이동하여 재사용성을 높였다.
processes 레이어는 왜 사용하지 않았는가?
FSD에서는 프로세스 단위의 비즈니스 로직을 processes/에 분리하는 것을 권장하지만, 현재 프로젝트 규모에서는 필요하지 않았다.
- 현재 프로젝트는 단순한 CRUD 작업이 주를 이루고 있으며 복잡한 비즈니스 로직이 없어 processes/ 레이어를 생략했다.
- 향후 워크플로우(workflow)가 필요한 기능(예: 멀티 스텝 폼, 대시보드 데이터 처리 등)이 추가된다면 processes/를 도입할 예정이다.
글을 마치며: FSD 도입 이후 변화와 앞으로의 방향성
이번 프로젝트에서는 Feature-Sliced Design(FSD) 아키텍처를 도입하여 기존의 복잡하고 모호한 폴더 구조를 정리하고 기능 중심의 구조로 개선했다. 기존의 구조에서는 기능별 코드가 혼재되어 있어 유지보수가 어려웠고 협업 시에도 코드의 위치를 파악하는 데 많은 시간이 소요되었다.
FSD를 적용한 이후 각 기능(feature)별로 코드가 독립적으로 관리되면서 코드 탐색이 용이해지고 특정 기능을 수정하거나 확장하는 과정이 훨씬 수월해졌다. API 호출, 데이터 모델, UI 컴포넌트, 페이지 등이 레이어별로 정리되면서 코드 간의 의존성이 줄어들었으며 전반적인 코드의 모듈성과 재사용성이 증가했다.
기존에는 components/ 폴더에 UI 요소들이 무분별하게 모여 있었으나 공통적으로 사용되는 UI 컴포넌트는 widgets/, 여러 기능에서 공유하는 요소는 shared/에 배치하는 방식으로 재사용성을 극대화했다. 이를 통해 새로운 기능을 추가할 때 불필요한 코드 중복을 줄일 수 있었다. 현재 프로젝트의 특성상 복잡한 비즈니스 프로세스가 필요한 processes/ 레이어는 도입하지 않았다. 하지만 향후 멀티 스텝 폼, 대시보드 데이터 처리 등과 같은 워크플로우가 필요한 기능이 추가된다면 processes/ 레이어를 활용하여 더욱 구조적인 설계를 적용할 계획이다.
앞으로의 방향성
FSD 아키텍처를 도입한 것은 프로젝트의 유지보수성과 확장성을 고려한 중요한 결정이었다. 하지만 아키텍처는 정적(static)인 것이 아니라 프로젝트의 성장과 함께 발전해야 하는 것이다.
- 프로젝트가 커짐에 따라 비즈니스 로직이 복잡해진다면 processes/ 레이어를 도입하여 보다 체계적인 워크플로우 관리를 할 수 있도록 준비할 것이다.
- UI 컴포넌트가 증가할 경우 widgets/를 더 세분화하여 관리할 필요가 있으며 디자인 시스템을 구축하는 방안도 고려해볼 예정이다.
- API 연동이 많아질 경우 현재 entities/api/ 구조에서 GraphQL 혹은 REST API와 같은 데이터 계층을 좀 더 효율적으로 관리할 방법을 고민할 것이다.
프론트엔드 아키텍처는 단순히 코드 정리를 위한 것이 아니라 더 나은 개발 환경을 만들고, 효율적으로 협업할 수 있도록 돕는 도구다.
이번 개선을 통해 더욱 체계적인 개발 방식을 정립할 수 있었으며 앞으로도 지속적인 개선을 통해 더 발전된 구조를 만들어 나갈 것이다. 🚀
'[refactor: advICE]' 카테고리의 다른 글
[refactor] Lv.3 React 프로젝트에서 명명 규칙 통일하기 (feat. PascalCase) (0) | 2025.03.28 |
---|---|
[refactor] Lv.2.2 RTR 도입기: 진짜 로그아웃은 Refresh Token까지 지우는 것부터 (1) | 2025.03.27 |
[refactor] Lv.2.1 RTR 도입기: 액세스 토큰 만료? 자동 재발급으로 해결하기 (0) | 2025.03.25 |
[refactor] Lv.2 RTR 도입기: 쿠키 기반 로그인 응답 처리 (0) | 2025.03.24 |
[refactor] Lv.0 리팩토링 시작 (0) | 2025.02.06 |