
@next/codemod CLI은 Next.js 버전을 쉽게 업그레이드할 수 있는 CLI입니다. 코드베이스를 최신 안정 버전이나 사전 릴리스 버전으로 업그레이드할 수 있게하며, 주요 릴리즈에 맞춰 기존 코드를 자동으로 변환해주는 도구입니다.
npm @next.codemod@canary upgrade latest
기존의 일부 API가 비동기 API로 변경되었습니다. 데이터 요청이 필요 없는 컴포넌트를 비동기로 처리하여 초기 로드 속도를 높이는 방법으로 변경되었습니다.
변경된 API는 cookies, headers, params, searchParams, drafMode 입니다.
이러한 변경으로 인해, 해당 API들을 사용할 때는 await 키워드를 사용하여 비동기적으로 접근해야 합니다.
Next.js 14 버전
import { cookies } from 'next/headers';
export async function AdminPanel() {
const cookieStore = cookies();
const token = cookieStore.get('token');
//...
}
Next.js 15 버전
import { cookies } from 'next/headers';
export async function AdminPanel() {
const cookieStore = await cookies();
const token = cookieStore.get('token');
//...
}
기존 캐싱 기능이 변경되었습니다. Route Handlers와 Client Router Cache의 기본 설정이 '캐싱됨'에서 '캐싱되지 않음'으로 변경되었습니다.
Next.js 14
app/api/* 경로에서 작성한 Route Handlers가 기본적으로 캐싱됨(cache: 'force-cache') 상태였습니다.
클라이언트 측에서 페이지 전환 시, Router Cache가 페이지 데이터를 미리 저장하거나 재사용했습니다.
Next.js 15
Route Handlers (GET, POST, etc)는 기본적으로 cache: 'no-store' 설정이 됩니다.
Client Router Cache 또한 기본값이 'disabled'로 바뀌었습니다.
즉, API 응답이나 페이지 전환 시 매번 새로 요청되고, 캐시가 되지 않습니다.
💡 캐시를 유지하고 싶다면?
Router Handler 캐싱
1 ) 단일 fetch 호출에서 캐시 옵션을 force-cache로 설정
fetch('https://...', { cache: 'force-cache' });
2 ) 단일 라우트에 대해 dynamic route config 옵션을 force-static으로 설정
export const dynamic = 'force-static';
3 ) Layout 또는 Page에서 모든 fetch 요청이 force-cache를 사용하도록 fetchCache route config 옵션을 default-cache로 설정
export const fetchCache = 'default-cache';
Client Router 캐싱
export const dynamic = 'force-static'; // SSG
// 또는
export const revalidate = 30; // ISR (Incremental Static Regeneration)
React 19와의 호환성을 지원하며, React 18과도 일부 하위 호환이 유지됩니다.
React 19의 자세한 내용은 이 React 19 변경 사항을 참고해주세요.
<form> 요소를 확장한 최적화 컴포넌트로, 제출 경로를 프리패칭(Prefetching)하고 제출 데이터를 쿼리스트링으로 보존합니다.
Form Comonent 주요 기능
<Form action={myAction}>으로 바로 연결 가능합니다.'use client';
import { createUserAction } from './actions';
import { Form } from 'next/form';
export default function CreateUserForm() {
return (
<Form action={createUserAction}>
<input type="text" name="name" placeholder="이름" />
<button type="submit">생성</button>
</Form>
);
}
👉 여기서 createUserAction은 use server로 선언된 Server Action 함수입니다.
사용자가 <Form>을 렌더링하면 Next.js는 제출 경로를 자동으로 프리패칭합니다.
미리 해당 경로의 코드를 불러와서 전송 후 빠르게 처리 가능합니다.
폼을 제출하면, URL 쿼리스트링이 그대로 유지되며, 유저 경험의 연속성을 제공합니다.
서버 액션과의 연결을 통해 API 없이도 바로 서버 코드 실행이 가능해집니다.
next dev --turbo 모드가 안정화되어, 더 빠른 개발 환경과 반응 속도를 제공합니다.
이전까지는 실험적(Experimental)이었지만, 이제는 공식적으로 사용할 수 있습니다.
next dev --turbo
Turbopack 장점
| 내용 | 효과 |
|---|---|
| 🔥 핫 리로딩 속도 향상 | 파일 변경 시 반영 속도가 매우 빠름 |
| 🧊 콜드 스타트 개선 | 처음 next dev 실행 시 대기 시간 단축 |
| 🧩 모듈 캐싱 최적화 | 변경되지 않은 모듈은 다시 컴파일하지 않음 |
| 🔍 더 나은 에러 디버깅 | Stack trace와 모듈 트래킹 기능 향상 |
개발 중에 경로가 사전 렌더링되는지 여부를 화면 하단 모서리에 시작적으로 표시(⚡ Static route)합니다.
이 시각적 표시를 통해 페이지 렌더링 방식을 파악하여 성능을 더욱 쉽게 최적화할 수 있습니다.

실험적 기능으로 스트리밍이 완료된 후 비동기적으로 추가 작업을 처리할 수 있는 새로운 API입니다.
이 API는 서버 렌더링이 완료되어 사용자에게 HTML이 전송된 뒤에도 백그라운드에서 추가 처리를 할 수 있도록 도와줍니다.
즉, 사용자 경험에는 영향을 주지 않고, 필요한 후처리를 서버에서 비동기적으로 진행할 수 있는 구조입니다.
unstable_after API를 사용시 next.config.js에 아래와 같이 설정을 추가해야 합니다.
const nextConfig = {
experimental: {
after: true,
},
};
export default nextConfig;
// app/page.tsx
import { unstable_after } from 'next/server';
export default async function HomePage() {
// 페이지가 렌더링 완료된 후 실행될 비동기 작업 정의
unstable_after(async () => {
await fetch('https://api.example.com/log?page=home');
console.log('Home page viewed - log sent');
});
// 사용자에게는 바로 이 내용이 렌더링됨
return (
<main>
<h1>Welcome to the homepage</h1>
</main>
);
}
서버 생명주기를 관찰하여 성능을 모니터링 하고 오류를 추적할 수 있습니다.
instrumentation.js 파일은 /src/instrumentation.js 또는 /app/instrumentation.js 경로에 위치해야 합니다.
instrumentation.js 파일에서 register() API를 사용하면 Next.js 서버의 생명주기(라이프사이클)를 모니터링할 수 있으며, 이를 통해 성능을 모니터링하고 오류를 추적할 수 있습니다.
export async function register() {
return {
async onRequestStart(context) {
console.log('🚀 요청 시작:', context.pathname);
},
async onRequestEnd(context) {
console.log('✅ 요청 종료:', context.pathname);
},
async onError(error, context) {
console.error('❌ 에러 발생:', context.pathname, error);
// 예: Sentry 전송
},
};
}
TypeScript를 사용하는 next.config 설정 파일을 지원하며 자동 완성과 타입 안전성도 보장됩니다.
// next.config.ts
import { NextConfig } from 'next';
const nextConfig: NextConfig = {
reactStrictMode: true,
images: {
domains: ['example.com'],
},
experimental: {
serverActions: true,
},
};
export default nextConfig;
Cache-Control 헤더에 대한 더 많은 제어가 가능해졌으며, 이미지 최적화 성능이 향상되었습니다.
이제 정적 자산(예: HTML, JS, CSS, 이미지 등)에 대해 더 정밀하게 캐시 정책을 설정할 수 있습니다.
Next.js는 기본적으로 자동 캐시 정책을 설정하지만, self-hosting 시 직접 설정이 필요한 경우에 유용합니다.
// next.config.ts
import { NextConfig } from 'next';
const nextConfig: NextConfig = {
headers: async () => [
{
source: '/(.*)', // 전체 경로
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=3600, stale-while-revalidate=86400',
},
],
},
],
};
export default nextConfig;
self-hosting 시 이미지 최적화를 위해 sharp을 수동 설치하지 않아도 Next.js 15 에서는 서버 실행 시 자동으로 sharp을 활용하여 이미지 최적화를 지원합니다.
Next.js 15에서는 Server Actions의 보안이 크게 강화되었습니다. 특히 불필요한 코드 제거 및 안전한 식별자(ID) 생성 기능이 도입되면서, 코드 최적화와 보안을 동시에 확보할 수 있게 되었습니다.
'use server';
export async function submitForm(data: FormData) {
// 실제 사용하는 Server Action
const name = data.get('name');
console.log(`Form submitted: ${name}`);
}
// 아래 함수는 사용되지 않으면 빌드 시 제거됨
export async function unusedAction() {
console.log('This will be tree-shaken in production.');
}
Next.js 15에서는 next.config.ts에서 외부 NPM 패키지를 번들링할 수 있는 옵션이 추가되어, 런타임 성능 최적화 또는 특정 환경에서의 의존성 통제가 훨씬 쉬워졌습니다.
기본적으로 외부 패키지는 node_modules에서 제외되며 서버에서 런타임 시 로드됩니다.
새로운 설정 옵션 experimental.serverComponentsExternalPackages를 통해 특정 패키지를 직접 번들링할 수 있습니다.
서버리스 환경, Vercel 배포, 또는 자체 호스팅에 따라 번들 방식을 제어할 수 있습니다.
// next.config.ts
const nextConfig = {
experimental: {
serverComponentsExternalPackages: ['uuid'],
},
};
export default nextConfig;
uuid는 서버 컴포넌트의 번들에 포함됩니다.
서버 실행 시 외부에서 동적으로 가져오는 대신, 번들 안에 포함되어 더 빠르게 실행됩니다.
Next.js 15에서는 ESLint 9이 공식적으로 지원됩니다. 이는 최신 JavaScript 및 TypeScript 규칙에 맞춘 린팅 기능을 제공하며, 코드 품질 향상과 안정성에 크게 기여합니다.
import js from '@eslint/js';
import next from 'eslint-config-next';
export default [
js.configs.recommended,
next,
{
rules: {
'no-console': 'warn',
'@next/next/no-img-element': 'off',
},
},
];
Next.js 15에서는 개발과 빌드 프로세스 모두에 대해 더 빠르고 효율적인 성능 최적화가 적용되었습니다. 특히 정적 페이지 생성(Static Generation) 속도 개선과 서버 컴포넌트의 HMR(Hot Module Replacement) 기능이 크게 강화되었습니다.
// app/page.jsx (Server Component)
export default async function Page() {
const res = await fetch('https://api.example.com/posts', {
next: { revalidate: 60 }, // ISR 사용
});
const data = await res.json();
return <div>{data.title}</div>;
}
🔁 개발 중 HMR이 작동하면 이 fetch 요청의 응답을 재사용하여 불필요한 API 호출을 줄이고 HMR 속도도 향상됩니다.
// next.config.ts
const nextConfig = {
experimental: {
staticGenerationRetryCount: 1, // 생성 실패 시 최대 1회 재시도
staticGenerationMaxConcurrency: 8, // 워커 하나당 최대 8페이지 처리
staticGenerationMinPagesPerWorker: 25, // 워커 생성 최소 기준
},
};
export default nextConfig;
💡 이 설정은 다음과 같은 상황에서 유용합니다 :