This post is only available in Korean.
Next.js App Router 완벽 가이드
Next.js 15의 App Router를 사용하여 현대적인 웹 애플리케이션을 구축하는 방법을 알아봅니다.
•Awaik
#Next.js#React#개발#튜토리얼
Next.js App Router 완벽 가이드
Next.js 15에서 도입된 App Router는 React Server Components를 기반으로 한 새로운 라우팅 시스템입니다. 이 가이드에서는 App Router의 핵심 개념과 실제 사용 방법을 알아보겠습니다.
App Router vs Pages Router
기존의 Pages Router와 비교했을 때 App Router의 주요 차이점:
| 특징 | Pages Router | App Router |
|---|---|---|
| 파일 위치 | pages/ | app/ |
| 라우팅 | 파일 기반 | 폴더 기반 |
| 서버 컴포넌트 | ❌ | ✅ |
| 레이아웃 | _app.js | layout.tsx |
| 로딩 상태 | 수동 구현 | loading.tsx |
기본 라우트 만들기
App Router에서는 폴더가 URL 경로를 정의합니다:
// app/blog/page.tsx
export default function BlogPage() {
return <h1>Blog</h1>;
}
위 코드는 /blog 경로에 매핑됩니다.
동적 라우트
대괄호를 사용하여 동적 라우트를 만들 수 있습니다:
// app/blog/[slug]/page.tsx
export default async function BlogPostPage({
params
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
return <h1>Post: {slug}</h1>;
}
서버 컴포넌트와 클라이언트 컴포넌트
서버 컴포넌트 (기본)
// 기본적으로 모든 컴포넌트는 서버 컴포넌트
async function BlogList() {
const posts = await fetchPosts();
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
클라이언트 컴포넌트
'use client';
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
레이아웃과 템플릿
레이아웃
레이아웃은 여러 페이지에서 공유되는 UI입니다:
// app/layout.tsx
export default function RootLayout({
children
}: {
children: React.ReactNode;
}) {
return (
<html lang="ko">
<body>
<nav>내비게이션</nav>
{children}
<footer>푸터</footer>
</body>
</html>
);
}
데이터 페칭
서버 컴포넌트에서
async function Posts() {
const res = await fetch('https://api.example.com/posts', {
cache: 'no-store' // 캐시 없이 항상 최신 데이터
});
const posts = await res.json();
return <PostList posts={posts} />;
}
병렬 데이터 페칭
async function Page() {
const [posts, comments] = await Promise.all([
fetchPosts(),
fetchComments()
]);
return (
<>
<Posts data={posts} />
<Comments data={comments} />
</>
);
}
스트리밍과 Suspense
import { Suspense } from 'react';
export default function Page() {
return (
<>
<Header />
<Suspense fallback={<PostsLoading />}>
<Posts />
</Suspense>
<Suspense fallback={<CommentsLoading />}>
<Comments />
</Suspense>
</>
);
}
메타데이터
정적 메타데이터
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "블로그",
description: "개발 블로그입니다",
};
동적 메타데이터
export async function generateMetadata({
params,
}: {
params: Promise<{ slug: string }>;
}): Promise<Metadata> {
const { slug } = await params;
const post = await getPost(slug);
return {
title: post.title,
description: post.description,
};
}
에러 핸들링
// app/blog/error.tsx
'use client';
export default function Error({
error,
reset
}: {
error: Error;
reset: () => void;
}) {
return (
<div>
<h2>문제가 발생했습니다!</h2>
<button onClick={reset}>다시 시도</button>
</div>
);
}
로딩 상태
// app/blog/loading.tsx
export default function Loading() {
return <div>로딩 중...</div>;
}
결론
App Router는 Next.js의 미래입니다. Server Components와 Suspense를 활용하여 더 나은 사용자 경험과 성능을 제공할 수 있습니다.
핵심 포인트:
- ✅ 서버 컴포넌트를 기본으로 사용
- ✅ 클라이언트 컴포넌트는 필요할 때만
- ✅ Suspense로 점진적 로딩
- ✅ 병렬 데이터 페칭으로 성능 최적화
더 자세한 내용은 Next.js 공식 문서를 참고하세요!