프로젝트 구조
src/app·public·설정 파일·빌드 산출물의 책임을 구분하고 폴더와 page.tsx가 URL을 만드는 규칙을 익힙니다.
Next.js 16 프로젝트 생성과 실행을 확인했으니, 이제 프로젝트 내부 구조를 살펴봅니다.
각 디렉터리와 파일의 역할을 알면 라우트, 컴포넌트, 설정 파일의 책임을 구분하기 쉽습니다.
앞서 create-next-app으로 프로젝트를 생성할 때 src/ 디렉터리 사용을 선택했으므로, 그에 맞춰 src 폴더를 기준으로 설명을 진행하겠습니다.
먼저 최상위 폴더를 소스 코드, 정적 파일, 설정, 설치 패키지, 빌드 결과물로 나눠 읽어 봅니다.
처음에는 파일 이름을 모두 외우기보다 어느 영역을 직접 수정하고 어느 영역을 Next.js가 관리하는지 구분하는 것이 중요하다.
| 영역 | 대표 위치 | 역할 | 처음 할 일 |
|---|---|---|---|
| 소스 코드 | src/app | 페이지, 레이아웃, 라우트 UI 작성 | page.tsx와 layout.tsx 위치 확인 |
| 정적 자산 | public | 이미지, 폰트, favicon 제공 | 루트 URL로 직접 접근됨을 기억 |
| 설정 파일 | package.json, tsconfig.json, eslint.config.mjs, next.config.ts | 명령, 타입, lint, 프레임워크 동작 제어 | scripts와 paths만 먼저 읽기 |
| 설치 패키지 | node_modules | 프로젝트 의존성 저장 | 직접 편집하지 않고 재설치로 복구 |
| 빌드 결과 | .next | 개발/빌드 cache와 산출물 | 문제 시 삭제 후 재생성 가능 |
주요 디렉터리 및 파일
Next.js 프로젝트의 핵심은 src 디렉터리 안에 있는 app 디렉터리입니다.
이 외에도 몇 가지 중요한 최상위 디렉터리와 파일들이 있습니다.
src/ 디렉터리
프로젝트의 소스 코드가 위치하는 곳입니다.
create-next-app에서 src/ 디렉터리 사용을 선택했다면, 모든 애플리케이션 코드는 이 안에 작성됩니다.
src/app/ 디렉터리 (App Router의 핵심)
이 디렉터리는 Next.js 16의 App Router가 작동하는 방식의 핵심입니다.
app 디렉터리 내의 파일 및 폴더 구조가 애플리케이션의 라우팅을 정의합니다.
-
src/app/page.tsx(또는.js,.jsx)- 애플리케이션의 루트 페이지를 나타냅니다. 즉,
http://localhost:3000/로 접속했을 때 가장 먼저 보이는 페이지입니다. - 각 라우트 세그먼트(폴더) 안에
page.tsx파일이 있으면 해당 라우트의 UI가 렌더링됩니다. - 이 파일은 기본적으로 서버 컴포넌트(Server Component)로 동작합니다.
- 애플리케이션의 루트 페이지를 나타냅니다. 즉,
-
src/app/layout.tsx(또는.js,.jsx)- 애플리케이션의 공통 레이아웃을 정의하는 파일입니다.
<html>및<body>태그와 같이 모든 페이지에 걸쳐 공유되는 UI를 여기에 정의합니다.- 이 교재의 단일 라우트 트리에서는
src/app/layout.tsx가 Root Layout이며<html lang="ko">와<body>를 포함합니다. 라우트 그룹 등으로 여러 루트 트리를 구성할 때는 각 트리의 최상위layout.tsx가 이 역할을 맡을 수 있습니다. layout.tsx파일은 기본적으로 서버 컴포넌트로 동작합니다.
-
src/app/globals.css- 애플리케이션 전체에 적용되는 전역 스타일을 정의하는 CSS 파일입니다.
layout.tsx파일에서 이 CSS 파일을 임포트하여 사용합니다.
-
라우트 세그먼트 폴더 (예:
src/app/dashboard/page.tsx)app디렉터리 안에 새로운 폴더를 생성하면, 해당 폴더 이름이 URL 경로의 세그먼트가 됩니다.- 예를 들어,
src/app/dashboard/page.tsx는/dashboard경로에 매핑됩니다. - 폴더 안에
page.tsx파일이 없으면 해당 경로는 유효한 페이지가 아닙니다.
-
loading.tsx(선택 사항)- 특정 라우트 세그먼트의 콘텐츠가 로딩되는 동안 보여줄 UI를 정의합니다.
- Next.js의 Suspense 기능과 함께 작동하여 사용자 경험을 향상시킵니다.
-
error.tsx(선택 사항)- 특정 라우트 세그먼트에서 에러가 발생했을 때 보여줄 UI를 정의합니다.
- React Error Boundary와 유사하게 작동하여 애플리케이션의 안정성을 높입니다.
-
not-found.tsx(선택 사항)- 해당 라우트에서 콘텐츠를 찾을 수 없을 때 보여줄 UI를 정의합니다. (404 페이지)
public/ 디렉터리
이미지, 폰트, favicon.ico 등 웹 서버에서 직접 제공되어야 하는 정적 파일들을 저장하는 곳입니다.
이 디렉터리 안의 파일들은 애플리케이션의 루트 경로에서 바로 접근할 수 있습니다.
예를 들어, public/logo.png 파일은 /logo.png 경로로 접근할 수 있습니다.
node_modules/ 디렉터리
npm install 또는 yarn add 명령어를 통해 설치된 모든 Node.js 패키지(라이브러리)들이 저장되는 곳입니다.
이 폴더는 용량이 매우 크므로, Git과 같은 버전 관리 시스템에는 포함시키지 않는 것이 일반적입니다. (.gitignore 파일에 이미 설정되어 있습니다.)
.next/ 디렉터리
Next.js가 애플리케이션을 빌드(Build)할 때 생성되는 빌드 결과물, 캐시, 최적화된 파일 등이 저장되는 곳입니다.
이 디렉터리의 내용은 Next.js에 의해 관리되므로, 개발자가 직접 수정할 필요는 없습니다.
주요 설정 파일
프로젝트의 최상위 디렉터리에는 Next.js 애플리케이션의 동작을 제어하는 몇 가지 중요한 설정 파일들이 있습니다.
-
package.json- 프로젝트의 이름, 버전, 설명 등 메타데이터를 정의합니다.
dependencies에는 프로젝트 실행에 필요한 라이브러리 목록이,devDependencies에는 개발 시에만 필요한 라이브러리 목록이 정의됩니다.scripts섹션에는npm run dev,npm run build,npm run start와 같이 자주 사용하는 명령어가 정의되어 있습니다.
-
next.config.ts- Next.js 애플리케이션의 커스텀 설정을 정의하는 파일입니다.
- 이미지 최적화, 환경 변수 설정, 웹팩(Webpack) 설정 변경 등 Next.js의 기본 동작을 변경하거나 확장할 때 사용합니다.
-
tsconfig.json(TypeScript 사용 시)- TypeScript 프로젝트에서 TypeScript 컴파일러의 설정을 정의하는 파일입니다.
- 어떤 버전의 JavaScript로 컴파일할지, 어떤 모듈 시스템을 사용할지 등을 설정합니다.
-
eslint.config.mjs(ESLint 사용 시)- ESLint의 코드 스타일 및 정적 분석 규칙을 정의하는 파일입니다.
- 코드의 일관성을 유지하고 잠재적인 오류를 미리 발견하는 데 도움을 줍니다.
-
.gitignore- Git 버전 관리 시스템에서 추적하지 않을 파일이나 디렉터리를 지정하는 파일입니다.
node_modules/,.next/와 같이 불필요하거나 용량이 큰 파일/폴더는 여기에 포함되어 있습니다.
아래 다이어그램은 프로젝트 구조를 볼 때 각 파일의 역할과 수정·추적 여부를 함께 판단할 수 있도록 정리한 것입니다.
이름을 외우기보다 누가 만들고 어디까지 영향을 주는지로 분류한다.
- 한 URLpage.tsx
해당 route의 화면과 data 읽기
- 하위 URL 공통layout.tsx
공유 UI와 provider 경계
- 앱 전체globals.css · 설정 파일
전역 style은 globals.css, lint는 eslint.config.mjs, Next 동작은 next.config.ts에서 관리한다.
- 도구 생성.next/
원인을 소스에서 고치고 다시 생성
App Router의 라우팅 기본 원리
App Router에서는 폴더가 URL 세그먼트가 되고, 그 안의 page.tsx가 실제 페이지가 되는 규칙이 핵심입니다.
폴더만 만든다고 페이지가 생기는 것은 아니다. 각 세그먼트의 특수 파일이 어떤 책임을 갖는지 함께 봐야 한다.
| 구조 | URL/역할 | 필수 여부 | 읽는 법 |
|---|---|---|---|
| src/app/page.tsx | / 루트 페이지 | 루트 화면에 필요 | 폴더 경로가 URL이 되고 page가 화면이 됨 |
| src/app/dashboard/page.tsx | /dashboard 페이지 | 해당 URL에 필요 | dashboard 폴더가 URL 세그먼트 |
| src/app/products/[id]/page.tsx | /products/123 같은 동적 페이지 | 동적 경로에 필요 | 대괄호 폴더가 URL 값을 받음 |
| layout.tsx | 하위 페이지 공통 껍데기 | 최상위는 필수 | children을 감싸며 중첩됨 |
| loading/error/not-found.tsx | 상태별 보조 UI | 선택 | 해당 세그먼트의 로딩, 오류, 404를 담당 |
App Router는 파일 시스템 기반 라우팅을 사용하지만, Pages Router와는 다르게 page.tsx 파일이 있는 폴더가 라우트 세그먼트가 됩니다.
- 루트 라우트:
src/app/page.tsx - 중첩 라우트:
src/app/dashboard/page.tsx->/dashboard - 동적 라우트:
src/app/products/[id]/page.tsx->/products/123(여기서[id]는 동적인 값)
이러한 구조를 통해 Next.js는 라우트 세그먼트별로 독립적인 레이아웃, 로딩 UI, 에러 UI를 정의할 수 있게 합니다.
아래 다이어그램은 프로젝트 구조를 실제 수정 지점과 자동 생성물 기준으로 다시 묶어 보여줍니다.
화면 오류, 설치 오류, 빌드 오류는 서로 다른 위치에서 출발한다. 위치를 나누면 원인 추적이 빨라진다.
| 분류 | 대표 파일 | 문제가 보이는 신호 | 대응 |
|---|---|---|---|
| 내가 쓴 소스 | src/app/page.tsx, layout.tsx | 화면 문구, 컴포넌트, 라우팅 오류 | 최근 수정 코드와 import 확인 |
| 전역 스타일 | globals.css | 전체 화면 여백, 색, 폰트 변화 | 전역 선택자와 class 충돌 확인 |
| 설정 | package.json, tsconfig.json, eslint.config.mjs, next.config.ts | 명령, lint, alias, 타입 오류 | scripts, paths, lint 규칙, Next 설정 확인 |
| 설치 결과 | node_modules, lockfile | 패키지 import 실패 | install 재실행, lockfile 충돌 확인 |
| 빌드 cache | .next | 이전 화면이 남거나 빌드 산출 오류 | 서버 재시작 또는 cache 재생성 |
다음 다이어그램은 Next.js 프로젝트 폴더를 라우팅, 재사용, 서버 로직, 정적 자산 책임으로 나누어 읽는 지도입니다.
초기 프로젝트에는 최소 구조만 있지만, 커질수록 책임별 폴더를 분리해야 경로와 import가 읽힌다.
| 책임 | 권장 위치 | 담는 것 | 주의할 점 |
|---|---|---|---|
| 라우팅 UI | src/app | page, layout, loading, error | URL과 폴더명이 연결됨 |
| 공용 컴포넌트 | src/components | 버튼, 카드, 폼 같은 재사용 UI | 라우트 전용 UI와 섞지 않기 |
| 도메인/유틸 | src/lib 또는 src/features | API 호출, 검증, 포맷 함수 | 서버 전용 코드 노출 주의 |
| 정적 자산 | public | 이미지, 아이콘, 다운로드 파일 | 경로가 루트 기준으로 노출됨 |
| 설정과 명령 | 프로젝트 루트 | package.json, next.config.ts, eslint.config.mjs, tsconfig.json | 팀 전체 동작에 영향 |
프로젝트 구조를 볼 때는 직접 수정할 소스, 자동 생성물, 설정 파일을 구분해야 이후 문제 원인을 빠르게 좁힐 수 있습니다.
구조를 바꿀 때는 화면이 열리는지만 보지 말고 어느 연결이 달라지는지 확인해야 한다.
| 변경 | 영향받는 것 | 확인 방법 | 대표 실수 |
|---|---|---|---|
| app 폴더 이동 | 라우팅 기준 | 원하는 URL이 열리는지 확인 | src 사용 여부와 예제 경로 혼동 |
| page.tsx 이름/위치 변경 | 페이지 존재 여부 | 404 또는 해당 화면 확인 | 폴더만 만들고 page를 빠뜨림 |
| layout.tsx 수정 | 하위 페이지 공통 UI | 여러 URL에서 공통 영역 확인 | children 누락 |
| alias 설정 변경 | import 경로 | 개발 서버와 타입 오류 확인 | tsconfig paths와 실제 폴더 불일치 |
| public 파일 이름 변경 | 이미지/정적 파일 URL | 브라우저에서 직접 URL 열기 | public을 경로에 포함해서 씀 |
마지막으로 주요 디렉터리의 역할을 URL 생성, 정적 자산, 빌드 결과, 설정 책임으로 묶어 봅니다.
구조를 기억할 때는 경로 이름보다 책임을 먼저 떠올리면 다음 장의 라우팅과 컴포넌트 분리가 쉬워진다.
| 기억할 질문 | 보는 위치 | 답 | 다음 학습 연결 |
|---|---|---|---|
| 이 URL의 화면은 어디 있나 | src/app/**/page.tsx | 폴더 경로가 URL이고 page가 화면 | 라우팅 |
| 모든 페이지 공통 UI는 어디 있나 | layout.tsx | children을 감싸는 공통 구조 | 중첩 레이아웃 |
| 이미지 파일은 어디 두나 | public | 루트 경로에서 직접 제공 | 이미지와 정적 파일 |
| 실행 명령은 어디서 보나 | package.json scripts | dev, build, start 같은 명령 | 개발 서버와 빌드 |
| 직접 수정하면 안 되는 곳은 어디인가 | node_modules, .next | 설치/빌드가 다시 만드는 영역 | 문제 해결과 재설치 |