Next.js는 React 기반의 웹 애플리케이션 프레임워크로, 다양한 규모와 유형의 프로젝트에 사용할 수 있습니다. 이 글에서는 Next.js 프로젝트를 구성할 수 있는 여러 디렉토리 구조 유형을 살펴보겠습니다.
이번 글에서 다루는 기술 스택은 다음과 같습니다:
- Next.js (App Router)
- TypeScript
- Tailwind CSS
- PostgreSQL
1. 기본 Next.js 프로젝트 디렉토리 구조
가장 기본적인 Next.js 프로젝트 구조로, 소규모 프로젝트나 빠른 프로토타이핑에 적합합니다.
project-root/
├── app/ # App Router 기본 디렉토리
│ ├── api/ # API 라우트
│ │ └── route.ts
│ ├── favicon.ico # 파비콘
│ ├── globals.css # 전역 스타일 (Tailwind 포함)
│ ├── layout.tsx # 루트 레이아웃
│ └── page.tsx # 홈페이지
│
├── components/ # 재사용 가능한 컴포넌트
│ ├── ui/ # UI 컴포넌트
│ └── common/ # 공통 컴포넌트
│
├── lib/ # 유틸리티 및 헬퍼 함수
│ ├── db.ts # 데이터베이스 연결
│ └── utils.ts # 일반 유틸리티 함수
│
├── types/ # TypeScript 타입 정의
│ └── index.ts # 공통 타입 내보내기
│
├── prisma/ # Prisma ORM 관련 파일
│ ├── schema.prisma # 데이터베이스 스키마
│ └── migrations/ # 마이그레이션 파일
│
├── public/ # 정적 파일
│
├── middleware.ts # Next.js 미들웨어
├── next.config.js # Next.js 설정
├── package.json # 의존성 및 스크립트
├── postcss.config.js # PostCSS 설정 (Tailwind용)
├── tailwind.config.ts # Tailwind CSS 설정
└── tsconfig.json # TypeScript 설정
이 구조는 간단하면서도 효율적으로 프로젝트를 관리할 수 있게 해줍니다. 모든 페이지는 app
디렉토리에 위치하고, 재사용 가능한 컴포넌트는 components
디렉토리에 모아둡니다.
2. 단일 프로젝트 내 다중 기능 구조 (모놀리식)
여러 기능(인증, 대시보드, 마이페이지, 도구 등)을 하나의 프로젝트에서 관리하는 모놀리식 구조입니다. 중간 규모의 프로젝트나 빠른 개발 속도가 필요한 경우에 적합합니다.
monolithic-project/
├── app/
│ ├── (auth)/ # 인증 관련 라우트 그룹
│ │ ├── login/
│ │ │ └── page.tsx
│ │ ├── register/
│ │ │ └── page.tsx
│ │ └── layout.tsx # 인증 페이지용 레이아웃
│ │
│ ├── (dashboard)/ # 대시보드 관련 라우트 그룹
│ │ ├── dashboard/
│ │ │ └── page.tsx
│ │ ├── analytics/
│ │ │ └── page.tsx
│ │ └── layout.tsx # 대시보드 페이지용 레이아웃
│ │
│ ├── (my)/ # 마이페이지 관련 라우트 그룹
│ │ ├── profile/
│ │ │ └── page.tsx
│ │ ├── settings/
│ │ │ └── page.tsx
│ │ └── layout.tsx # 마이페이지용 레이아웃
│ │
│ ├── (tools)/ # 도구 관련 라우트 그룹
│ │ ├── calculator/
│ │ │ └── page.tsx
│ │ ├── converter/
│ │ │ └── page.tsx
│ │ └── layout.tsx # 도구 페이지용 레이아웃
│ │
│ ├── api/ # API 라우트
│ │ ├── auth/
│ │ │ └── [...]/
│ │ ├── dashboard/
│ │ │ └── [...]/
│ │ ├── my/
│ │ │ └── [...]/
│ │ └── tools/
│ │ └── [...]/
│ │
│ ├── layout.tsx # 메인 레이아웃
│ └── page.tsx # 홈페이지
│
├── components/
│ ├── ui/ # 기본 UI 컴포넌트
│ │ ├── Button/
│ │ └── [...]/
│ │
│ ├── auth/ # 인증 관련 컴포넌트
│ ├── dashboard/ # 대시보드 관련 컴포넌트
│ ├── my/ # 마이페이지 관련 컴포넌트
│ └── tools/ # 도구 관련 컴포넌트
│
├── lib/
│ ├── db/ # 데이터베이스 관련
│ │ ├── client.ts # Prisma 클라이언트
│ │ └── queries/ # 데이터베이스 쿼리
│ │
│ ├── auth.ts # 인증 유틸리티
│ ├── dashboard.ts # 대시보드 유틸리티
│ └── tools.ts # 도구 관련 유틸리티
│
├── hooks/ # 커스텀 훅
│ ├── useAuth.ts
│ └── [...].ts
│
├── types/ # 타입 정의
│ ├── auth.ts
│ ├── dashboard.ts
│ ├── user.ts
│ └── tools.ts
│
├── prisma/ # Prisma ORM
│ └── schema.prisma
│
├── middleware.ts # 전역 미들웨어
└── [기타 설정 파일들]
이 구조는 Next.js App Router의 라우트 그룹 기능(괄호로 표시)을 활용하여 관련 페이지를 논리적으로 그룹화합니다. 각 기능별로 컴포넌트, 유틸리티, 타입 등을 구분하여 코드 구성을 명확하게 합니다.
3. 다중 프로젝트 분리 구조 (마이크로서비스)
여러 기능을 별도의 프로젝트로 분리한 마이크로서비스 아키텍처입니다. 대규모 프로젝트나 여러 팀이 독립적으로 작업하는 경우에 적합합니다.
microservices/
├── auth-service/ # 인증 서비스
│ ├── app/
│ │ ├── api/
│ │ │ └── auth/
│ │ │ ├── login/
│ │ │ │ └── route.ts
│ │ │ └── register/
│ │ │ └── route.ts
│ │ ├── login/
│ │ │ └── page.tsx
│ │ ├── register/
│ │ │ └── page.tsx
│ │ ├── layout.tsx
│ │ └── page.tsx
│ │
│ ├── components/
│ ├── lib/
│ ├── prisma/
│ │ └── schema.prisma # 인증 관련 스키마만 포함
│ └── [설정 파일들]
│
├── dashboard-service/ # 대시보드 서비스
│ ├── app/
│ │ ├── api/
│ │ │ └── dashboard/
│ │ ├── dashboard/
│ │ │ └── page.tsx
│ │ ├── analytics/
│ │ │ └── page.tsx
│ │ ├── layout.tsx
│ │ └── page.tsx
│ │
│ ├── components/
│ ├── lib/
│ ├── prisma/
│ │ └── schema.prisma # 대시보드 관련 스키마만 포함
│ └── [설정 파일들]
│
├── my-service/ # 마이페이지 서비스
│ ├── app/
│ │ ├── api/
│ │ │ └── my/
│ │ ├── profile/
│ │ │ └── page.tsx
│ │ ├── settings/
│ │ │ └── page.tsx
│ │ ├── layout.tsx
│ │ └── page.tsx
│ │
│ ├── components/
│ ├── lib/
│ ├── prisma/
│ │ └── schema.prisma # 사용자 관련 스키마만 포함
│ └── [설정 파일들]
│
├── tools-service/ # 도구 서비스
│ ├── app/
│ │ ├── api/
│ │ │ └── tools/
│ │ ├── calculator/
│ │ │ └── page.tsx
│ │ ├── converter/
│ │ │ └── page.tsx
│ │ ├── layout.tsx
│ │ └── page.tsx
│ │
│ ├── components/
│ ├── lib/
│ ├── prisma/
│ │ └── schema.prisma # 도구 관련 스키마만 포함
│ └── [설정 파일들]
│
├── frontend/ # 메인 프론트엔드 (선택 사항)
│ ├── app/
│ │ └── [...]/ # 통합 UI
│ ├── components/
│ └── [설정 파일들]
│
├── shared/ # 공유 라이브러리 (선택 사항)
│ ├── ui/ # 공통 UI 컴포넌트
│ ├── utils/ # 공통 유틸리티
│ └── types/ # 공통 타입 정의
│
├── infrastructure/ # 인프라 설정
│ ├── docker-compose.yml
│ ├── nginx/ # API 게이트웨이
│ └── [...]/
│
└── README.md
이 구조에서는 각 서비스가 완전히 독립적인 Next.js 애플리케이션으로 작동합니다. 서비스 간 통신은 API를 통해 이루어지며, 각 서비스는 자신의 데이터베이스 스키마를 관리합니다.
4. 모노레포 구조
여러 프로젝트를 하나의 저장소에서 관리하되, 독립적으로 빌드/배포 가능한 구조입니다. 코드 재사용이 많고 일관된 개발 경험을 유지하고 싶은 경우에 적합합니다.
monorepo-project/
├── apps/
│ ├── auth/ # 인증 앱
│ │ ├── app/
│ │ ├── components/
│ │ └── [설정 파일들]
│ │
│ ├── dashboard/ # 대시보드 앱
│ │ ├── app/
│ │ ├── components/
│ │ └── [설정 파일들]
│ │
│ ├── my/ # 마이페이지 앱
│ │ ├── app/
│ │ ├── components/
│ │ └── [설정 파일들]
│ │
│ ├── tools/ # 도구 앱
│ │ ├── app/
│ │ ├── components/
│ │ └── [설정 파일들]
│ │
│ └── web/ # 통합 웹 앱 (선택 사항)
│ ├── app/
│ ├── components/
│ └── [설정 파일들]
│
├── packages/
│ ├── ui/ # 공유 UI 라이브러리
│ │ ├── components/
│ │ └── package.json
│ │
│ ├── utils/ # 공유 유틸리티
│ │ ├── src/
│ │ └── package.json
│ │
│ ├── database/ # 데이터베이스 접근 라이브러리
│ │ ├── prisma/
│ │ │ └── schema.prisma # 통합 스키마
│ │ ├── src/
│ │ └── package.json
│ │
│ └── types/ # 공유 타입 정의
│ ├── src/
│ └── package.json
│
├── turbo.json # Turborepo 설정
├── package.json # 루트 패키지
└── [기타 설정 파일들]
모노레포 구조에서는 각 앱이 독립적인 Next.js 애플리케이션으로 작동하며, 공통 코드는 packages
디렉토리에 있는 공유 라이브러리로 분리됩니다. Turborepo와 같은 도구를 사용하여 빌드 프로세스를 최적화할 수 있습니다.
5. 기능별 분리 구조 (수직 슬라이스 아키텍처)
하나의 프로젝트 내에서 기능별로 완전히 분리된 구조입니다. 도메인 주도 설계(DDD) 접근법을 선호하는 경우에 적합합니다.
vertical-slice-project/
├── app/
│ ├── layout.tsx # 전역 레이아웃
│ ├── page.tsx # 홈페이지
│ │
│ ├── auth/ # 인증 기능
│ │ ├── login/
│ │ │ └── page.tsx
│ │ ├── register/
│ │ │ └── page.tsx
│ │ └── api/
│ │ └── [...]/
│ │
│ ├── dashboard/ # 대시보드 기능
│ │ ├── page.tsx
│ │ ├── analytics/
│ │ │ └── page.tsx
│ │ └── api/
│ │ └── [...]/
│ │
│ ├── my/ # 마이페이지 기능
│ │ ├── profile/
│ │ │ └── page.tsx
│ │ ├── settings/
│ │ │ └── page.tsx
│ │ └── api/
│ │ └── [...]/
│ │
│ └── tools/ # 도구 기능
│ ├── calculator/
│ │ └── page.tsx
│ ├── converter/
│ │ └── page.tsx
│ └── api/
│ └── [...]/
│
├── features/ # 기능별 관련 코드
│ ├── auth/ # 인증 관련
│ │ ├── components/ # 인증 전용 컴포넌트
│ │ ├── hooks/ # 인증 전용 훅
│ │ ├── types/ # 인증 전용 타입
│ │ └── services/ # 인증 관련 서비스
│ │
│ ├── dashboard/ # 대시보드 관련
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── types/
│ │ └── services/
│ │
│ ├── my/ # 마이페이지 관련
│ │ ├── components/
│ │ ├── hooks/
│ │ ├── types/
│ │ └── services/
│ │
│ └── tools/ # 도구 관련
│ ├── components/
│ ├── hooks/
│ ├── types/
│ └── services/
│
├── shared/ # 공유 코드
│ ├── components/ # 공통 컴포넌트
│ ├── hooks/ # 공통 훅
│ ├── types/ # 공통 타입
│ └── utils/ # 공통 유틸리티
│
├── lib/ # 핵심 라이브러리
│ ├── db.ts # 데이터베이스 클라이언트
│ └── api.ts # API 유틸리티
│
├── prisma/ # Prisma ORM
│ └── schema.prisma
│
└── [설정 파일들]
이 구조에서는 각 기능이 완전히 독립적으로 유지되며, 관련된 모든 코드(컴포넌트, 훅, 서비스 등)가 해당 기능 디렉토리 안에 위치합니다. 공통 코드만 shared
디렉토리에 분리됩니다.
각 구조의 적합한 사용 사례
- 기본 구조: 소규모 프로젝트, 개인 프로젝트, 빠른 프로토타입 개발
- 모놀리식 구조: 중간 규모 프로젝트, 빠른 개발 속도가 중요한 경우, 팀 규모가 작은 경우
- 마이크로서비스 구조: 대규모 프로젝트, 여러 팀이 독립적으로 작업, 각 서비스의 독립적 확장이 필요한 경우
- 모노레포 구조: 코드 재사용이 많고, 여러 앱을 관리하지만 일관된 개발 경험을 유지하고 싶은 경우
- 수직 슬라이스 구조: 도메인 주도 설계(DDD) 접근법을 선호하는 경우, 기능별 책임이 명확히 분리되어야 하는 경우
결론
프로젝트의 디렉토리 구조는 개발 생산성과 코드 유지보수에 큰 영향을 미칩니다. 이 글에서 소개한 다양한 디렉토리 구조는 프로젝트의 규모, 팀 구성, 개발 목표에 따라 적절하게 선택하면 됩니다. 또한 하이브리드 방식으로 여러 구조의 장점을 조합해 사용할 수도 있습니다.
프로젝트를 시작할 때 미래의 확장성을 고려하여 디렉토리 구조를 신중하게 선택하고, 팀 내에서 일관된 규칙을 정하는 것이 중요합니다.