본문으로 건너뛰기

안동민 개발노트

본문 시작

프로젝트 구조

src/app·public·설정 파일·빌드 산출물의 책임을 구분하고 폴더와 page.tsx가 URL을 만드는 규칙을 익힙니다.

Next.js 16 프로젝트 생성과 실행을 확인했으니, 이제 프로젝트 내부 구조를 살펴봅니다.

각 디렉터리와 파일의 역할을 알면 라우트, 컴포넌트, 설정 파일의 책임을 구분하기 쉽습니다.

앞서 create-next-app으로 프로젝트를 생성할 때 src/ 디렉터리 사용을 선택했으므로, 그에 맞춰 src 폴더를 기준으로 설명을 진행하겠습니다.

먼저 최상위 폴더를 소스 코드, 정적 파일, 설정, 설치 패키지, 빌드 결과물로 나눠 읽어 봅니다.

Next.js 프로젝트는 소스 코드, 정적 자산, 설정 파일, 설치 패키지, 빌드 결과물로 나눠 읽는다

처음에는 파일 이름을 모두 외우기보다 어느 영역을 직접 수정하고 어느 영역을 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/와 같이 불필요하거나 용량이 큰 파일/폴더는 여기에 포함되어 있습니다.

아래 다이어그램은 프로젝트 구조를 볼 때 각 파일의 역할과 수정·추적 여부를 함께 판단할 수 있도록 정리한 것입니다.

파일은 영향 범위와 생성 주체로 수정 여부를 판단한다

이름을 외우기보다 누가 만들고 어디까지 영향을 주는지로 분류한다.

  1. 한 URL
    page.tsx

    해당 route의 화면과 data 읽기

  2. 하위 URL 공통
    layout.tsx

    공유 UI와 provider 경계

  3. 앱 전체
    globals.css · 설정 파일

    전역 style은 globals.css, lint는 eslint.config.mjs, Next 동작은 next.config.ts에서 관리한다.

  4. 도구 생성
    .next/

    원인을 소스에서 고치고 다시 생성


App Router의 라우팅 기본 원리

App Router에서는 폴더가 URL 세그먼트가 되고, 그 안의 page.tsx가 실제 페이지가 되는 규칙이 핵심입니다.

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가 읽힌다.

책임권장 위치담는 것주의할 점
라우팅 UIsrc/apppage, layout, loading, errorURL과 폴더명이 연결됨
공용 컴포넌트src/components버튼, 카드, 폼 같은 재사용 UI라우트 전용 UI와 섞지 않기
도메인/유틸src/lib 또는 src/featuresAPI 호출, 검증, 포맷 함수서버 전용 코드 노출 주의
정적 자산public이미지, 아이콘, 다운로드 파일경로가 루트 기준으로 노출됨
설정과 명령프로젝트 루트package.json, next.config.ts, eslint.config.mjs, tsconfig.json팀 전체 동작에 영향

프로젝트 구조를 볼 때는 직접 수정할 소스, 자동 생성물, 설정 파일을 구분해야 이후 문제 원인을 빠르게 좁힐 수 있습니다.

폴더나 설정을 바꾸면 URL, import, 빌드, 정적 파일 경로가 함께 영향을 받는다

구조를 바꿀 때는 화면이 열리는지만 보지 말고 어느 연결이 달라지는지 확인해야 한다.

변경영향받는 것확인 방법대표 실수
app 폴더 이동라우팅 기준원하는 URL이 열리는지 확인src 사용 여부와 예제 경로 혼동
page.tsx 이름/위치 변경페이지 존재 여부404 또는 해당 화면 확인폴더만 만들고 page를 빠뜨림
layout.tsx 수정하위 페이지 공통 UI여러 URL에서 공통 영역 확인children 누락
alias 설정 변경import 경로개발 서버와 타입 오류 확인tsconfig paths와 실제 폴더 불일치
public 파일 이름 변경이미지/정적 파일 URL브라우저에서 직접 URL 열기public을 경로에 포함해서 씀

마지막으로 주요 디렉터리의 역할을 URL 생성, 정적 자산, 빌드 결과, 설정 책임으로 묶어 봅니다.

주요 디렉터리는 URL 생성, 정적 자산 제공, 빌드 결과, 프로젝트 설정으로 역할이 갈린다

구조를 기억할 때는 경로 이름보다 책임을 먼저 떠올리면 다음 장의 라우팅과 컴포넌트 분리가 쉬워진다.

기억할 질문보는 위치다음 학습 연결
이 URL의 화면은 어디 있나src/app/**/page.tsx폴더 경로가 URL이고 page가 화면라우팅
모든 페이지 공통 UI는 어디 있나layout.tsxchildren을 감싸는 공통 구조중첩 레이아웃
이미지 파일은 어디 두나public루트 경로에서 직접 제공이미지와 정적 파일
실행 명령은 어디서 보나package.json scriptsdev, build, start 같은 명령개발 서버와 빌드
직접 수정하면 안 되는 곳은 어디인가node_modules, .next설치/빌드가 다시 만드는 영역문제 해결과 재설치