- Published on
Next.js 16 완벽 가이드 - 새로운 기능과 주요 변경사항 총정리
목차
- 들어가며
- 1. Turbopack: 이제 기본 번들러로
- 2. Cache Components와 "use cache" 지시어
- 3. cacheLife 프로필
- 4. 새로운 캐싱 API
- 5. proxy.ts - middleware.ts의 새로운 이름
- 6. Next.js DevTools MCP
- 7. React Compiler 안정화
- 8. Enhanced Routing & Navigation
- 9. Breaking Changes
- 10. 추가 개선사항
- 11. 마이그레이션 가이드
- 12. 실전 예시
- 마치며
- 참고 자료
들어가며
2025년 10월, Next.js 16이 정식 릴리즈되었다. 이번 메이저 버전은 Turbopack의 안정화, 혁신적인 캐싱 시스템, AI 기반 디버깅 도구 등 대규모 변경사항을 포함하고 있다.
이 글에서는 Next.js 16의 모든 주요 기능과 Breaking Changes를 상세히 다룬다.
1. Turbopack: 이제 기본 번들러로
성능 혁신
Turbopack이 모든 새 Next.js 프로젝트의 기본 번들러가 되었다:
- Fast Refresh: 최대 10배 향상
- 프로덕션 빌드: 2-5배 빠른 빌드 속도
- 파일 시스템 캐싱: 재시작 시 더 빠른 컴파일 (베타)
마이그레이션
기존 webpack 설정이 있다면 플래그로 우회 가능:
# 개발
next dev --webpack
# 프로덕션
next build --webpack
파일 시스템 캐싱 활성화
const nextConfig = {
experimental: {
turbopackFileSystemCacheForDev: true,
},
}
export default nextConfig
2. Cache Components와 "use cache" 지시어
명시적 캐싱 모델
Next.js 16은 opt-in 캐싱 모델을 도입한다. 이전과 달리 동적 코드는 기본적으로 요청마다 실행된다.
활성화 방법
const nextConfig = {
cacheComponents: true,
}
export default nextConfig
"use cache" 지시어 사용
import { cacheLife } from 'next/cache'
export default async function BlogPost({ params }) {
'use cache'
cacheLife('days')
const { slug } = await params
const post = await fetchBlogPost(slug)
return <article>{post.content}</article>
}
컴파일러가 자동으로 캐시 키를 생성하며, Partial Pre-Rendering(PPR)과 통합되어 혼합 렌더링이 가능하다.
3. cacheLife 프로필
내장 프로필
Next.js 16은 7가지 내장 프로필을 제공한다:
| 프로필 | 용도 | stale | revalidate | expire |
|---|---|---|---|---|
default | 표준 콘텐츠 | 5분 | 15분 | 1년 |
seconds | 실시간 데이터 | 30초 | 1초 | 1분 |
minutes | 빈번한 업데이트 | 5분 | 1분 | 1시간 |
hours | 하루 중 여러 번 업데이트 | 5분 | 1시간 | 1일 |
days | 일일 업데이트 | 5분 | 1일 | 1주 |
weeks | 주간 업데이트 | 5분 | 1주 | 30일 |
max | 거의 변하지 않는 콘텐츠 | 5분 | 30일 | 1년 |
커스텀 프로필 정의
const nextConfig = {
cacheComponents: true,
cacheLife: {
blog: {
stale: 3600, // 1시간
revalidate: 900, // 15분
expire: 86400, // 1일
},
biweekly: {
stale: 60 * 60 * 24 * 14, // 14일
revalidate: 60 * 60 * 24, // 1일
expire: 60 * 60 * 24 * 14, // 14일
},
},
}
export default nextConfig
인라인 프로필 사용
'use cache';
import { cacheLife } from 'next/cache';
export default async function Page() {
cacheLife({
stale: 3600,
revalidate: 900,
expire: 86400,
});
return <div>Page</div>;
}
cacheTag와 조합
import { cacheLife, cacheTag } from 'next/cache';
async function getPostContent(slug: string) {
'use cache';
const post = await fetchPost(slug);
cacheTag(`post-${slug}`);
if (!post) {
cacheLife('minutes');
return null;
}
cacheLife('days');
return post.data;
}
4. 새로운 캐싱 API
revalidateTag() - Stale-While-Revalidate
이제 cacheLife 프로필을 두 번째 인수로 필수로 받는다:
import { revalidateTag } from 'next/cache';
// ✅ 추천
revalidateTag('blog-posts', 'max');
// 다른 내장 프로필
revalidateTag('news-feed', 'hours');
revalidateTag('analytics', 'days');
// 커스텀 시간
revalidateTag('products', { expire: 3600 });
특징: 사용자는 캐시된 데이터를 즉시 받고, 백그라운드에서 새로고침된다.
사용 시점: 정적 콘텐츠로 최종 일관성(eventual consistency)을 허용할 수 있을 때
updateTag() - Read-Your-Writes
Server Actions 전용으로 즉시 새로고침을 제공한다:
'use server';
import { updateTag } from 'next/cache';
export async function updateUserProfile(userId: string, profile: Profile) {
await db.users.update(userId, profile);
// 캐시 만료 및 즉시 새로고침
updateTag(`user-${userId}`);
}
특징: 동일 요청 내에서 캐시를 만료하고 즉시 최신 데이터를 읽는다.
사용 시점: 폼 제출, 사용자 설정 등 즉시 피드백이 필요한 상호작용
refresh() - 캐시 무관 데이터 새로고침
Server Actions 전용으로 캐시되지 않은 데이터만 새로고친다:
'use server';
import { refresh } from 'next/cache';
export async function markNotificationAsRead(notificationId: string) {
await db.notifications.markAsRead(notificationId);
// 캐시하지 않은 데이터만 새로고침
refresh();
}
용도: 알림 수, 실시간 지표 같은 캐시되지 않은 동적 데이터 갱신
5. proxy.ts - middleware.ts의 새로운 이름
변경 사항
middleware.ts가 proxy.ts로 이름이 변경되었다:
import { NextRequest, NextResponse } from 'next/server'
export default function proxy(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url))
}
export const config = {
matcher: '/about/:path*',
}
주요 차이점
- 파일명:
middleware.ts→proxy.ts - 함수명:
middleware→proxy - 목적: 애플리케이션의 네트워크 경계를 명확하게 표현
- 런타임: Node.js 런타임에서만 실행
middleware.ts는 여전히 Edge 런타임용으로 지원되지만 deprecated되었다.
6. Next.js DevTools MCP
AI 기반 디버깅
Model Context Protocol(MCP) 통합으로 AI가 개발 워크플로우 내에서 문제를 진단한다:
주요 기능:
- Next.js 지식: 라우팅, 캐싱, 렌더링 동작 이해
- 통합 로그: 브라우저와 서버 로그를 한 곳에서 확인
- 자동 오류 접근: 스택 추적을 수동으로 복사할 필요 없음
- 페이지 인식: 현재 라우트 컨텍스트 이해
AI 에이전트가 직접 애플리케이션 컨텍스트를 활용해 설명과 해결책을 제공한다.
7. React Compiler 안정화
활성화 방법
const nextConfig = {
reactCompiler: true,
}
export default nextConfig
npm install babel-plugin-react-compiler@latest
주요 기능
- 컴포넌트를 자동으로 메모이제이션
- 불필요한 리렌더링 감소
주의사항
- 기본적으로 활성화되지 않음 (성능 데이터 수집 중)
- Babel 의존성으로 인해 개발/빌드 시간 증가 가능
8. Enhanced Routing & Navigation
Layout Deduplication
50개의 상품 링크가 있는 페이지에서 레이아웃을 1번만 다운로드한다 (이전: 50번).
Incremental Prefetching
- 캐시에 없는 부분만 미리 로드
- 뷰포트를 벗어나면 요청 취소
- 호버/재진입 시 우선순위 부여
- 캐시 무효화 시 자동 재미리로드
트레이드오프: 더 많은 개별 prefetch 요청이 발생할 수 있지만, 총 전송 크기는 훨씬 낮다.
9. Breaking Changes
필수 버전 요구사항
| 요구사항 | 이전 | Next.js 16 |
|---|---|---|
| Node.js | 18+ | 20.9+ (LTS) |
| TypeScript | 4.5+ | 5.1+ |
| 브라우저 | Chrome 108+ | Chrome 111+, Edge 111+, Firefox 111+, Safari 16.4+ |
제거된 기능
| 제거됨 | 대체 방법 |
|---|---|
| AMP 지원 | 완전 제거 |
next lint | Biome/ESLint 직접 사용 |
serverRuntimeConfig, publicRuntimeConfig | 환경 변수 (.env) |
devIndicators 설정 옵션 | 제거됨 |
experimental.ppr | Cache Components로 통합 |
experimental.dynamicIO | cacheComponents로 재명명 |
unstable_rootParams() | 대안 개발 중 |
자동 scroll-behavior: smooth | 제거됨 |
next lint 마이그레이션
npx @next/codemod@canary next-lint-to-eslint-cli .
비동기 Props 필수화
모든 동적 props가 비동기로 변경되었다:
// ❌ Next.js 15
export default function Page({ params, searchParams }) {
const { slug } = params;
const { query } = searchParams;
}
// ✅ Next.js 16
export default async function Page({ params, searchParams }) {
const { slug } = await params;
const { query } = await searchParams;
}
동일하게 적용:
// 모두 await 필요
const cookieStore = await cookies();
const headersList = await headers();
const { isEnabled } = await draftMode();
next/image 기본값 변경
| 설정 | 이전 | Next.js 16 |
|---|---|---|
minimumCacheTTL | 60초 | 4시간 (14400초) |
imageSizes | [16, 32, 48, ...] | [32, 48, ...] (16 제거) |
qualities | [1-100] | [75] (이제 필수 설정) |
dangerouslyAllowLocalIP | 허용 | 기본 차단 (보안 강화) |
maximumRedirects | 무제한 | 3으로 제한 (보안 강화) |
중요: qualities는 이제 필수 설정이며, 설정하지 않으면 악의적인 사용자가 의도하지 않은 품질 최적화를 요청할 수 있다.
Parallel Routes: default.js 필수
모든 슬롯에 명시적인 default.js 파일이 필요하다:
export default function Default() {
return null
// 또는 notFound()
}
없으면 404 에러가 발생한다.
revalidateTag() 시그니처 변경
// ❌ 구식
revalidateTag('blog-posts');
// ✅ SWR 동작
revalidateTag('blog-posts', 'max');
// ✅ 즉시 업데이트 필요 시
import { updateTag } from 'next/cache';
updateTag('user-id');
10. 추가 개선사항
로깅 강화
개발 요청과 빌드에서 시간 소비를 상세히 표시:
GET /dashboard 200 in 1.2s
Compile: 450ms
Render: 750ms
병렬 실행
next dev와 next build를 동시에 실행할 수 있도록 출력 디렉토리 분리
Lockfile
동일 프로젝트의 중복 인스턴스 방지
Sass
sass-loader v16으로 현대 문법 지원
11. 마이그레이션 가이드
자동 업그레이드 (권장)
npx @next/codemod@canary upgrade latest
자동으로 다음을 처리한다:
- 패키지 버전 업그레이드
- Breaking changes 수정
- 설정 파일 업데이트
수동 업그레이드
npm install next@latest react@latest react-dom@latest
이후 Breaking Changes를 수동으로 수정:
- 비동기 props 변환:
params,searchParams,cookies(),headers(),draftMode()에await추가 - revalidateTag() 수정: 두 번째 인자로 cacheLife 프로필 추가
- Parallel routes: 모든 슬롯에
default.js추가 - middleware.ts 이름 변경:
proxy.ts로 변경 (선택사항) - Node.js 20.9+ 업그레이드
- TypeScript 5.1+ 업그레이드
12. 실전 예시
블로그 포스트 캐싱
import { cacheLife, cacheTag } from 'next/cache'
export default async function BlogPost({ params }) {
'use cache'
const { slug } = await params
const post = await fetchPost(slug)
cacheTag(`post-${slug}`)
if (!post) {
cacheLife('minutes') // 404는 짧게 캐싱
return notFound()
}
cacheLife('days') // 정상 포스트는 일일 갱신
return <article>{post.content}</article>
}
사용자 프로필 업데이트
'use server'
import { updateTag } from 'next/cache'
export async function updateProfile(userId: string, data: ProfileData) {
await db.users.update(userId, data)
// 즉시 UI 반영
updateTag(`user-${userId}`)
}
실시간 알림 카운트
'use server'
import { refresh } from 'next/cache'
export async function markAsRead(notificationId: string) {
await db.notifications.markAsRead(notificationId)
// 캐시되지 않은 알림 수만 새로고침
refresh()
}
마치며
Next.js 16은 성능, 개발자 경험, 캐싱 제어에서 큰 발전을 이뤘다:
- Turbopack 안정화로 10배 빠른 개발 경험
- 명시적 캐싱 모델로 예측 가능한 동작
- AI 기반 디버깅으로 문제 해결 시간 단축
다만 Breaking Changes가 많으므로 마이그레이션 시 충분한 테스트가 필요하다. 자동 codemod를 활용하면 대부분의 변경사항을 안전하게 처리할 수 있다.