Contents
see List개요
Next.js 15는 App Router를 정식 출시하며 React Server Components를 기반으로 한 새로운 렌더링 패러다임을 제공합니다. 이 가이드에서는 App Router의 핵심 개념부터 실전 활용법까지 상세히 다룹니다.
핵심 개념
App Router는 app 디렉토리를 기반으로 하며, 파일 시스템 기반 라우팅을 제공합니다. 주요 특징은 다음과 같습니다:
- 서버 컴포넌트 우선: 기본적으로 모든 컴포넌트는 서버에서 렌더링됩니다.
- 레이아웃 시스템: 중첩된 레이아웃으로 공통 UI를 재사용할 수 있습니다.
- 스트리밍 SSR: Suspense 경계를 활용한 점진적 렌더링이 가능합니다.
- 데이터 페칭: 서버 컴포넌트에서 직접 async/await를 사용할 수 있습니다.
파일 구조와 라우팅
App Router는 특별한 파일명 규칙을 따릅니다:
app/
layout.tsx # 루트 레이아웃
page.tsx # 홈페이지
loading.tsx # 로딩 UI
error.tsx # 에러 UI
blog/
page.tsx # /blog 페이지
[slug]/
page.tsx # /blog/:slug 동적 라우트
(auth)/ # 라우트 그룹 (URL에 포함 안 됨)
login/
page.tsx # /login
서버 컴포넌트 활용
서버 컴포넌트에서는 직접 데이터베이스에 접근할 수 있습니다:
// app/blog/page.tsx
import { db } from '@/lib/db';
export default async function BlogPage() {
const posts = await db.post.findMany({
orderBy: { createdAt: 'desc' },
take: 10,
});
return (
<div>
<h1>블로그</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
);
}
클라이언트 컴포넌트와 상호작용
클라이언트 인터랙션이 필요한 경우 'use client' 지시자를 사용합니다:
'use client';
import { useState } from 'react';
export function LikeButton({ postId }: { postId: string }) {
const [likes, setLikes] = useState(0);
const handleLike = async () => {
const res = await fetch(`/api/posts/${postId}/like`, {
method: 'POST',
});
const data = await res.json();
setLikes(data.likes);
};
return (
<button onClick={handleLike}>
좋아요 {likes}
</button>
);
}
데이터 페칭 패턴
Next.js 15는 향상된 캐싱 전략을 제공합니다:
// 기본: fetch 결과는 자동으로 캐시됨
const data = await fetch('https://api.example.com/posts');
// 재검증 주기 설정
const data = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 } // 1시간마다 재검증
});
// 캐시 사용 안 함 (항상 최신 데이터)
const data = await fetch('https://api.example.com/posts', {
cache: 'no-store'
});
스트리밍과 Suspense
대용량 데이터를 효율적으로 로드하기 위해 스트리밍을 활용합니다:
import { Suspense } from 'react';
async function Posts() {
const posts = await fetchPosts(); // 느린 쿼리
return <PostList posts={posts} />;
}
export default function Page() {
return (
<div>
<h1>블로그</h1>
<Suspense fallback={<PostsSkeleton />}>
<Posts />
</Suspense>
</div>
);
}
메타데이터 관리
SEO를 위한 메타데이터는 정적 또는 동적으로 생성할 수 있습니다:
// 정적 메타데이터
export const metadata = {
title: '블로그',
description: '기술 블로그입니다',
};
// 동적 메타데이터
export async function generateMetadata({ params }) {
const post = await fetchPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
images: [post.coverImage],
},
};
}
활용 팁
- 서버 컴포넌트에서 최대한 많은 로직을 처리하여 클라이언트 번들 크기를 최소화하세요.
- 레이아웃을 활용하여 공통 UI와 상태를 효율적으로 관리하세요.
- 병렬 라우트와 인터셉트 라우트를 사용하면 모달과 같은 고급 UI를 구현할 수 있습니다.
- 서버 액션을 활용하면 API 라우트 없이도 폼 제출을 처리할 수 있습니다.
- React.cache()를 사용하여 동일한 요청의 중복을 방지하세요.
마무리
Next.js 15 App Router는 React의 최신 기능을 최대한 활용하여 성능과 개발 경험을 모두 향상시켰습니다. 서버 컴포넌트와 스트리밍을 적절히 활용하면 빠르고 효율적인 웹 애플리케이션을 구축할 수 있습니다.
javascript
| No | 작성일 | Title |
|---|---|---|
| 1180 | 2016. 11. 28. | [ AngularJS ] angularJs jquery selector |
| 1141 | 2016. 11. 01. | [ AngularJS ] ng-if 의 경우 상위 디렉브를 생성한다. |
| 1139 | 2016. 10. 21. | [ javascript ] 반응형 웹에서 PC 버전보기 구현 |
| 1076 | 2016. 09. 09. | [ AngularJS ] promise then 사용 |
| 1075 | 2016. 09. 07. | [ AngularJS ] 형제 태그 ng-repeat |
| 1074 | 2016. 09. 07. | [ AngularJS ] 의 이벤트 전파 |
| 1041 | 2016. 08. 18. | [ AngularJS ] json parsing spring ajax (and $$hashKey error ) |
| 1040 | 2016. 08. 18. | [ AngularJS ] select option ng-options |
| 1039 | 2016. 08. 18. | [ AngularJS ] ng-repeat 에서 ng-model 사용시 제대로 작동안할때 |
| 1038 | 2016. 08. 16. | [ AngularJS ] 어느 위치에서나 scope 에 접근하기 (전역,지역) |