일상이 개발
Next.js 폴더 구조 & 아키텍처 설계 완전정복 – 기능 중심 구조, Atomic Design, 서비스 계층까지 실전 가이드
아빠고미
2025. 5. 22. 12:10
반응형
Next.js 앱에서 폴더 구조 및 코드 아키텍처 설계 전략 – 확장성과 유지보수를 위한 모범 패턴 가이드
Next.js는 프론트엔드와 백엔드의 경계를 허무는 강력한 프레임워크입니다. 하지만 프로젝트가 커질수록 폴더 구조와 코드의 아키텍처가 복잡해지고, 초기 설계가 부실하면 유지보수 비용이 급격히 증가합니다.
이번 글에서는 실무에서 바로 적용 가능한 Next.js 앱의 폴더 구조 및 아키텍처 설계 전략을 다음과 같이 구성해 소개합니다:
- ✅ App Router 기반 디렉토리 구조 이해
- ✅ 기능 중심(feature-based) 폴더 구조
- ✅ Atomic Design + 도메인 중심 아키텍처
- ✅ 모듈화 전략 및 의존성 관리
- ✅ 확장성과 협업을 위한 구조 설계 팁
1. 🧭 App Router 디렉토리 구조 이해하기
✅ App Router 핵심 디렉토리
/app
├── layout.tsx // 전체 레이아웃
├── page.tsx // 루트 경로 페이지
├── [slug]/ // 동적 라우팅
│ ├── page.tsx
│ └── loading.tsx // 로딩 UI
├── (auth)/ // 중첩 라우팅 그룹
│ ├── login/
│ └── register/
📌 App Router 특징
- 폴더 이름이 곧 라우팅 경로
layout.tsx
는 해당 폴더 내 모든 하위 페이지에 적용loading.tsx
,error.tsx
,not-found.tsx
등 특별한 목적의 파일 지원
✅ 중첩 레이아웃 활용 예시
/app
├── layout.tsx // 공통 헤더/푸터
├── (auth)/layout.tsx // 로그인/회원가입 전용 레이아웃
➡️ route 그룹을 괄호로 감싸면 실제 URL 경로에 포함되지 않고 구조적으로만 나뉘어 레이아웃을 분리할 수 있습니다.
2. 🧱 기능 중심 Feature-based 폴더 구조
✅ 구조 예시
/features
├── auth/
│ ├── components/
│ ├── hooks/
│ ├── services/
│ └── types.ts
├── post/
│ ├── components/
│ ├── api/
│ ├── utils/
│ └── types.ts
📌 장점
- 도메인(기능) 단위로 폴더가 명확히 나뉘어 관리가 쉬움
- 팀 간 영역 구분이 명확
- 테스트 코드, 스타일, API가 기능 중심으로 분리
✅ 적용 팁
- 기능명은 단수형보다 복수형 추천 (ex:
posts
,users
) - 하위 폴더에는
components
,services
,utils
등 일관된 패턴 사용
3. 🧬 Atomic Design 패턴 + 도메인 아키텍처
✅ Atomic Design이란?
UI 컴포넌트를 작은 단위로 쪼개고 재사용할 수 있도록 설계하는 방법론입니다.
📦 컴포넌트 분류 예시
/components
├── atoms/ // 버튼, 입력창 등 가장 작은 요소
├── molecules/ // atom 조합 (폼그룹 등)
├── organisms/ // 로그인 폼, 헤더 등 의미 있는 단위
└── templates/ // 전체 페이지 프레임워크
✅ 도메인 + 디자인 혼합 전략
/features
├── auth/
│ ├── components/
│ │ ├── atoms/
│ │ └── organisms/
➡️ 기능 단위로 폴더를 나누되, 그 안에 Atomic 분리를 적용하면 재사용성과 협업 효율을 동시에 잡을 수 있습니다.
4. 🧩 서비스 계층과 도메인 분리 전략
✅ 왜 서비스 계층이 필요한가?
- 비즈니스 로직을 컴포넌트에서 분리
- 복잡한 계산/조건 처리 등을 한 곳에 집중
- 테스트 용이성 증가
📦 구조 예시
/features
├── auth/
│ ├── services/
│ │ └── authService.ts
│ ├── hooks/
│ │ └── useLogin.ts
📌 authService.ts 예시
export const login = async (email, password) => {
const res = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify({ email, password }),
});
if (!res.ok) throw new Error('Login failed');
return res.json();
};
📌 useLogin.ts 예시
import { useMutation } from '@tanstack/react-query';
import { login } from '../services/authService';
export const useLogin = () => {
return useMutation({
mutationFn: login,
});
};
➡️ UI와 로직을 철저히 분리해두면 컴포넌트는 “렌더링”에만 집중할 수 있고, 테스트와 유지보수가 훨씬 쉬워집니다.
5. ⚙️ 의존성 관리와 계층화 설계
✅ 의존성 방향
- 하위 계층이 상위 계층에 의존하면 안 됨
- 컴포넌트 → hooks → services → api
📦 디렉토리 기준 계층
/features
├── post/
│ ├── components/ // View
│ ├── hooks/ // ViewModel
│ ├── services/ // Domain Logic
│ ├── api/ // API Layer
│ └── types.ts
📌 이점
- 로직 재사용이 쉬움
- 외부 API가 바뀌어도 내부 코드 영향 최소화
- 리팩토링과 테스팅이 편리함
6. 🧠 상태 관리 전략 – 어디에 저장할 것인가?
✅ 상태 관리 대상 분류
- 🔄 UI 상태: 모달 열림, 탭 선택 등 → useState or useReducer
- 📡 서버 데이터: API 요청 → React Query or SWR
- 🔒 인증 상태, 사용자 정보 → Zustand, Context, Redux
📌 구조화 예시
/store
├── authStore.ts // 사용자 인증 정보
└── modalStore.ts // 모달 상태
/features
└── post/hooks/usePostQuery.ts
📦 Zustand 예시
import { create } from 'zustand';
export const useAuthStore = create((set) => ({
user: null,
setUser: (user) => set({ user }),
logout: () => set({ user: null }),
}));
✅ 서버 상태 캐싱
// post/hooks/usePostQuery.ts
import { useQuery } from '@tanstack/react-query';
export const usePostQuery = (id) => {
return useQuery(['post', id], () => fetchPost(id));
};
➡️ UI 상태와 서버 상태, 인증 상태를 각각 다른 도구로 분리하면 코드의 응집도와 유지보수성이 모두 향상됩니다.
7. 🔤 디렉토리 및 파일 네이밍 규칙
✅ 네이밍 컨벤션 예시
- 컴포넌트: PascalCase (예:
PostCard.tsx
) - hooks: camelCase (예:
usePostQuery.ts
) - API 파일: 동사 중심 camelCase (예:
fetchPost.ts
,createUser.ts
) - 디렉토리: 소문자 + kebab-case or camelCase
📌 일관성 유지가 핵심
네이밍은 어떤 방식이든 좋지만 모든 팀원이 같은 기준을 공유하는 것이 중요합니다.
8. 🔄 리팩토링을 위한 구조화 팁
✅ 모든 기능은 “컴포넌트/훅/서비스”로 나눈다
// 기존: 컴포넌트 안에 fetch + 로직 + 렌더링
// 개선: fetch → service, 로직 → hook, 렌더링만 남기기
✅ 공통 로직은 utils로 분리
/utils/date.ts → 날짜 포맷
/utils/validate.ts → 유효성 검사
/utils/slug.ts → URL slug 변환
✅ 관심사 분리
- 🧠 컴포넌트: 렌더링만
- ⚙️ 훅: 데이터 + 로직
- 📡 서비스: 외부 통신
- 📦 스토어: 전역 상태
9. ✅ 폴더 구조 & 아키텍처 실무 체크리스트
📌 기본 구조 체크
- ✔️ App Router 기반 디렉토리 사용
- ✔️ 기능 단위 폴더 구조 적용 (feature-based)
- ✔️ 서비스 계층 분리
📌 설계 패턴 체크
- ✔️ Atomic Design 개념 일부 반영
- ✔️ 상태 관리 위치 구분 (UI/서버/인증)
- ✔️ 재사용 가능한 훅/hooks 구조 확보
📌 확장성 체크
- ✔️ 폴더 및 파일 네이밍 일관성
- ✔️ 중복 로직은 공통 모듈로 추출
- ✔️ 테스트/스토리북/문서화 고려된 구조
긴 글 읽어주셔서 감사합니다! 공감, 댓글, 공유는 다음 글 제작에 큰 힘이 됩니다 🙌
반응형