Next.js 13+ App Router ✅ Layout, Page, Loading, Metadata

기존 pages/ 라우터와 달리, App Router는 디렉터리 구조 자체가 라우팅 규칙이 됩니다.
app/ 디렉토리 안의 폴더마다 페이지, 레이아웃, 로딩, 에러 처리, 메타데이터를 담당하는 파일이 존재하죠.
🧩 1. App Router 기본 구조
app/
├─ layout.tsx # 공통 레이아웃
├─ page.tsx # 루트 페이지
├─ loading.tsx # 로딩 상태
├─ error.tsx # 에러 페이지
├─ about/
│ ├─ page.tsx # /about
│ ├─ layout.tsx # about 전용 레이아웃
│ ├─ loading.tsx # about 로딩 UI
│ └─ error.tsx # about 에러 핸들링
└─ posts/
├─ page.tsx # /posts
└─ [id]/
└─ page.tsx # /posts/:id
📌 app/ 폴더 내부 구조 = 곧 URL 구조
🧱 2. layout.tsx – 공통 레이아웃
레이아웃은 해당 디렉토리의 모든 하위 페이지에 공통 적용됩니다.
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body>
<header>Header 영역</header>
<main>{children}</main>
<footer>Footer 영역</footer>
</body>
</html>
);
}
📌 children은 현재 라우트의 page.tsx 내용이 들어가는 자리
🪄 3. page.tsx – 실제 페이지 컴포넌트
// app/about/page.tsx
export default function AboutPage() {
return <h1>회사 소개 페이지</h1>;
}
📌 각 폴더에 page.tsx가 있으면, 그 경로가 자동으로 라우팅됩니다.
예: /about/page.tsx → https://domain.com/about
⏳ 4. loading.tsx – 로딩 상태 UI
React Suspense를 기반으로 한 서버 컴포넌트 로딩 UI
// app/posts/loading.tsx
export default function Loading() {
return <p>게시글을 불러오는 중입니다...</p>;
}
📌 fetch()가 지연되면 자동으로 loading.tsx가 표시됨
💥 5. error.tsx – 에러 처리
페이지 렌더링 중 오류 발생 시 자동 실행
"use client";
export default function Error({ error, reset }: { error: Error; reset: () => void }) {
return (
<div>
<h2>문제가 발생했습니다 😢</h2>
<p>{error.message}</p>
<button onClick={() => reset()}>다시 시도</button>
</div>
);
}
📌 use client가 꼭 필요함 (클라이언트 측에서 동작)
📌 reset()을 호출하면 다시 시도
🪶 6. metadata – SEO 및 메타태그 설정
App Router에서는 페이지별로 metadata를 설정 가능
// app/about/page.tsx
export const metadata = {
title: "회사 소개 | My Website",
description: "우리 회사는 최고의 서비스를 제공합니다.",
};
📌 결과적으로 <head> 영역에 자동 반영됨
<title>회사 소개 | My Website</title>
<meta name="description" content="우리 회사는 최고의 서비스를 제공합니다.">
⚙️ 7. 중첩 레이아웃 (Nested Layout)
app/about/layout.tsx 파일을 추가하면,
/about 이하 경로에만 적용되는 하위 레이아웃 구현 가능
// app/about/layout.tsx
export default function AboutLayout({ children }: { children: React.ReactNode }) {
return (
<section>
<h1>About 영역</h1>
{children}
</section>
);
}
📌 app/layout.tsx → app/about/layout.tsx 순으로 중첩 적용됨
🔄 8. 서버 컴포넌트 + 클라이언트 컴포넌트
App Router는 기본적으로 서버 컴포넌트(Server Component) 구조입니다.
클라이언트 전용 로직을 쓰려면 상단에 "use client" 선언 필요
// app/components/Counter.tsx
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>클릭: {count}</button>;
}
📊 9. 폴더 기반 라우팅의 장점
| 기능 | Pages Router | App Router |
| 라우팅 구조 | 파일 이름 기반 | 디렉토리 기반 |
| 레이아웃 | 직접 import | 자동 중첩 |
| 데이터 패칭 | getStaticProps/getServerSideProps | fetch() 내장 지원 |
| 로딩/에러 핸들링 | 직접 처리 | 파일 기반 자동 처리 |
| SEO 설정 | next/head | metadata 내장 |
🧠 10. 실무 팁
✅ loading.tsx와 error.tsx는 폴더 단위 관리
✅ 컴포넌트는 기본적으로 서버, 동적 UI는 "use client"로 분리
✅ 라우트 경로는 폴더 구조만 봐도 설계 파악 가능
✅ SSG, ISR은 fetch() 옵션(next.revalidate)으로 설정
📝 마무리 정리
- layout.tsx → 공통 UI
- page.tsx → 페이지 콘텐츠
- loading.tsx → Suspense 기반 로딩
- error.tsx → 에러 UI
- metadata → SEO 최적화
- 모든 구조가 폴더 기반으로 자동 라우팅
👉 “라우트 설계 = 디렉터리 구조 설계”
이제 Next.js에서 폴더 하나면 페이지 하나, 관리가 훨씬 직관적입니다 💪