개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Next.js 프로젝트 구조 — 실무 폴더 구성 방법

2025년 6월 8일
Next.js프로젝트 구조app 폴더componentslib

Next.js 프로젝트가 커질수록 폴더 구조가 유지보수성을 좌우한다. 파일을 어디에 두느냐에 따라 코드 탐색 속도, 팀원 간 협업 난이도, 빌드 최적화 여부가 달라진다. 아래는 실무에서 자주 쓰이는 구조를 기준으로 각 폴더의 역할을 설명한다.

전체 폴더 트리

my-app/
├── app/
│   ├── (auth)/
│   │   ├── login/
│   │   │   └── page.tsx
│   │   └── layout.tsx
│   ├── dashboard/
│   │   └── page.tsx
│   ├── api/
│   │   └── users/
│   │       └── route.ts
│   ├── layout.tsx
│   └── page.tsx
├── components/
│   ├── ui/
│   │   ├── Button.tsx
│   │   └── Input.tsx
│   └── shared/
│       └── Header.tsx
├── lib/
│   ├── db.ts
│   └── utils.ts
├── hooks/
│   └── useAuth.ts
├── types/
│   └── index.ts
└── public/
    └── images/

app/ 폴더

app/ 은 Next.js 13부터 도입된 App Router의 핵심이다. 폴더 이름이 곧 URL 경로가 되며, page.tsx 파일이 있는 폴더만 라우트로 노출된다.

(auth) 처럼 괄호로 감싼 폴더는 Route Group으로, URL에는 나타나지 않지만 공통 layout.tsx를 공유할 때 사용한다. API 엔드포인트는 app/api/ 아래 route.ts 파일로 정의한다.

Route Group: 폴더를 URL 세그먼트로 노출하지 않고 레이아웃만 묶는 App Router 기능.

components/ 폴더

재사용 가능한 React 컴포넌트를 모아두는 곳이다. 실무에서는 두 가지로 나누는 패턴이 많다.

하위 폴더용도
ui/버튼, 인풋 등 순수 UI 컴포넌트 (비즈니스 로직 없음)
shared/Header, Footer 등 여러 페이지에서 공유하는 컴포넌트

ui/ 컴포넌트는 props만 받고 외부 상태에 의존하지 않아야 테스트와 재사용이 쉽다.

lib/ 폴더

lib/ 에는 특정 컴포넌트에 묶이지 않는 유틸리티와 외부 연동 코드를 둔다.

// lib/db.ts — Prisma 클라이언트 싱글턴
import { PrismaClient } from "@prisma/client";

const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };

export const prisma =
  globalForPrisma.prisma ?? new PrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

DB 연결, 날짜 포맷 함수, 암호화 유틸 등이 lib/의 전형적인 내용이다.

hooks/ 와 types/

hooks/ 에는 use로 시작하는 커스텀 훅을 모은다. 컴포넌트에서 비즈니스 로직을 분리하는 기본 수단이다.

// hooks/useAuth.ts
import { useSession } from "next-auth/react";

export function useAuth() {
  const { data: session, status } = useSession();
  return { user: session?.user, isLoading: status === "loading" };
}

types/ 는 프로젝트 전역에서 공유하는 TypeScript 타입 정의를 담는다. 페이지나 API Route마다 같은 타입을 중복 선언하는 것을 막는다.

커스텀 훅(Custom Hook): React 훅을 조합해 만든 재사용 가능한 상태·로직 단위.

public/ 폴더

정적 파일(이미지, 폰트, robots.txt 등)을 두는 곳이다. public/images/logo.png는 코드에서 /images/logo.png로 참조된다. Next.js가 빌드 시 이 경로를 그대로 서빙하므로 별도 import 없이 사용 가능하다.

폴더 배치 원칙

  • page 전용 컴포넌트는 해당 app/ 경로 아래에 함께 두어 응집도를 높인다.
  • 두 곳 이상에서 쓰이는 코드만 components/, lib/, hooks/로 올린다.
  • 파일이 늘어날수록 components/ui/, components/shared/ 처럼 기능 단위로 하위 분리한다.
← 이전 글Next.js 배포 — Vercel과 self-hosting 옵션
다음 글 →Next.js 성능 최적화 — 번들 크기와 렌더링 최적화