Next.js 교재 · 3편 · 폴더 구조

App Router 폴더 구조 한눈에 보기

폴더가 곧 라우트, 파일 이름이 곧 역할. 한 번 외워두면 평생.

app 디렉토리의 폴더 트리가 라우트로 펼쳐지는 컨셉 아이소메트릭 일러스트

2편에서 create-next-app 으로 첫 프로젝트를 만들었다. 열어보면 app/ 안에 layout.tsx·page.tsx·globals.css 같은 파일이 들어있다. 보기엔 단순한데 이 셋이 Next.js App Router 의 전부를 결정한다.

이번 편은 app/ 안에서 자주 쓰는 특수 파일 이름을 정리한다. 이름이 정해져 있어서 외워야 하는데, 7개 정도라 30분이면 끝난다. 한 번 외우면 다음 챕터부터 폴더 보는 눈이 달라진다.

1. 핵심 원칙 — 폴더 = 라우트, 파일 = 역할

App Router 의 룰은 두 줄로 끝난다.

  • 폴더를 만들면 URL 경로가 생긴다. app/about//about.
  • 그 폴더 안의 파일 이름이 역할을 결정한다. page.tsx 는 페이지, layout.tsx 는 공통 레이아웃.

이게 끝이다. 폴더만 만들고 페이지 파일을 안 두면 그 경로는 안 생긴다 (404). 폴더 없이 파일만 두면? 아무 일도 안 일어난다.

예시app/blog/page.tsx 만 있으면 /blog 한 페이지. 거기에 app/blog/[slug]/page.tsx 를 추가하면 /blog/hello-world 같은 동적 페이지가 생긴다. 폴더 이름의 [slug] 가 변수임을 뜻한다(5편에서 자세히).

2. 특수 파일 7가지 — 이게 사전이다

App Router 가 알아보는 파일 이름은 정해져 있다. 그 외 이름은 그냥 일반 모듈(컴포넌트·헬퍼) 일 뿐, 라우팅에 관여하지 않는다.

파일역할사용 빈도
page.tsx이 경로의 실제 페이지 UI★★★ 필수
layout.tsx자식 페이지들을 감싸는 공통 레이아웃★★★ 매우 자주
loading.tsx데이터 불러오는 동안 보여줄 UI★★ 자주
error.tsx에러 발생 시 대체 UI★★ 자주
not-found.tsx404 시 보여줄 UI★ 가끔
template.tsxlayout 과 비슷하지만 매번 새로 마운트드뭄
route.tsAPI 엔드포인트 (HTML 아님)★ API 만들 때

이 7개만 알면 App Router 의 90% 가 끝난다. 나머지는 14편 (Route Handlers) 까지 가면서 하나씩 만져본다.

3. layout 과 page — 가장 자주 만지는 둘

layout.tsxpage.tsx 는 이름이 비슷한데 역할이 완전히 다르다.

page.tsx — 그 경로의 본문

// app/about/page.tsx export default function AboutPage() { return ( <main> <h1>소개</h1> <p>이 사이트는 …</p> </main> ); }

app/about/page.tsx/about URL 의 본문이 된다. 함수 이름은 자유, export default 가 핵심.

layout.tsx — 자식들을 감싸는 옷

// app/layout.tsx (루트 레이아웃, 필수) export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="ko"> <body> <header>공통 헤더</header> {children} <footer>공통 푸터</footer> </body> </html> ); }

{children} 자리에 page.tsx 또는 더 안쪽 layout 이 끼워진다. 헤더·푸터·사이드바를 한 번만 적어두면 모든 페이지에 자동으로 들어간다.

레이아웃은 중첩이 가능하다. app/blog/layout.tsx 를 추가하면 /blog/* 페이지들만 그 layout 으로 감싸진다. 루트 layout → 블로그 layout → 페이지 — 양파처럼.

루트 layout 의 함정app/layout.tsx 는 무조건 <html><body> 를 포함해야 한다. 빠뜨리면 빌드 에러. create-next-app 이 자동으로 만들어주니까 굳이 지우지 말 것.

4. loading 과 error — UX 의 끝판왕

이 두 파일이 App Router 가 옛 Pages Router 보다 좋은 결정적 이유.

loading.tsx — 데이터 기다리는 화면

app/blog/loading.tsx 를 만들고 스피너 컴포넌트를 두면, app/blog/page.tsx 가 데이터를 받는 동안 자동으로 그 스피너가 화면에 뜬다. 별도 useState 안 써도 된다 — Next 가 알아서 Suspense 로 감싸 준다.

// app/blog/loading.tsx export default function Loading() { return <p>블로그 글을 불러오는 중…</p>; }

error.tsx — 망가졌을 때 안전망

페이지 안에서 예외가 던져졌을 때 화면이 통째로 깨지지 않게 막아준다. 사용자에겐 친절한 메시지 + "다시 시도" 버튼이 뜨고, 다른 페이지로 이동은 가능하다.

// app/blog/error.tsx 'use client'; export default function Error({ error, reset, }: { error: Error; reset: () => void }) { return ( <div> <p>뭔가 잘못됐어요: {error.message}</p> <button onClick={() => reset()}>다시 시도</button> </div> ); }

error.tsx 는 반드시 'use client' 가 필요하다 (버튼이 클라이언트에서 동작해야 하니까). 11편에서 더 깊게 다룬다.

5. 라우트 그룹과 동적 세그먼트 — 폴더 이름의 트릭

폴더 이름에 괄호를 넣어 라우팅을 컨트롤한다.

폴더 패턴의미
(marketing)라우트 그룹 — URL 에 영향 X, 폴더만 묶음app/(marketing)/about/page.tsx/about
[slug]동적 세그먼트 — 한 단어 변수app/blog/[slug]/page.tsx/blog/hello
[...slug]catch-all — 나머지 경로 통째로/docs/a/b/c 같은 거 다 받음
_private언더스코어 시작 — 라우팅 제외 (헬퍼·유틸 보관용)app/_components/Button.tsx

5편에서 동적 라우팅을 깊게 다루니까 여기선 "이런 게 있다" 정도만 보고 넘어가자.

요약 — 3편 좌표

App Router 의 룰 두 줄 — 폴더가 곧 URL, 파일 이름이 곧 역할. 외워야 할 특수 파일은 7개(page·layout·loading·error·not-found·template·route), 그중 일상에서 자주 만지는 건 page + layout + loading + error 4개. 폴더 이름에 괄호·대괄호를 쓰면 그룹·동적 세그먼트가 된다. 다음 편에선 page.tsx·layout.tsx 를 직접 여러 개 만들어 사이트 골격을 잡는다.

다음 편 예고 — 페이지와 레이아웃 작성하기

page.tsx·layout.tsx 를 손으로 만들며 사이트 골격을 잡는다. 4편.

© 2026 주나이테크(주) @JUNAITECH