Next.js 15 vs 14 뭐가 달라졌나 총정리
Next.js 15, 늦게 봐도 핵심만 싹 정리

이 글은 2025-10-20 기준 Next.js v15.5.x 라인(문서 상 Latest 15.5.6)을 전제로, 14에서 15로 넘어오며 생긴 “실제 영향이 있는” 변화를 정리한 가이드입니다. 공식 블로그와 문서, React 19 릴리스 노트를 기반으로 합니다. (nextjs.org)
한 줄 요약: 캐싱 기본값이 “캐시 안 함”으로 바뀌었고, React 19 정식 지원(15.1), Turbopack 개발 서버 안정화(15.0) + 빌드 알파(15.3), 에러 DX/메타데이터/보안·관측성이 크게 개선됐습니다. (nextjs.org)
왜 지금 Next.js 15를 봐야 할까요?
- 15.0(2024-10-21)은 안정(stable)으로 공개되었고, 이후 15.1/15.2/15.3에서 실사용 DX가 계속 보강됐습니다. 특히 React 19 정식 지원(15.1), 스트리밍 메타데이터(15.2), 빌드 단계 Turbopack 알파(15.3)가 눈에 띕니다. (nextjs.org)
- 최소 Node 버전이 18.18.0으로 올라가며(14는 18.17) CI/런타임 환경 점검이 필요합니다. (nextjs.org)
- 15에서는 “요청/라우팅/클라이언트 내비게이션” 전반의 캐싱 기본값이 바뀌었기 때문에, 마이그레이션 시 동작 차이를 반드시 확인해야 합니다. (nextjs.org)
참고: 본문 곳곳에 공식 문서/블로그 링크가 있으며, 문장 끝의 인용 표시는 출처입니다. 예: Next.js 15 릴리스 노트 참고. (nextjs.org)
주요 변화 한눈에 보기
| 항목 | Next.js 14 | Next.js 15 |
|---|---|---|
| 릴리스(기점) | 2023-10-26 | 2024-10-21(15.0), 15.1/15.2/15.3로 지속 개선 |
| React 지원 | App Router는 React canary 기반, Server Actions 안정화 | 15.1에서 React 19 정식 지원(App/Pages 모두), App Router는 15.0 시점에 19 RC 기반 → 15.1에 정식, Pages는 18/19 병행 지원 가이드 제공 |
| 캐싱 기본값 | fetch/GET/Client Router Cache가 기본 캐시(상황 의존) | fetch/GET Route Handler/Client Router Cache 기본 “비캐시(no-store/0s)”로 전환 |
| Turbopack | dev에서 대규모 테스트 진행(안정화 준비) | dev 안정화(15.0), 빌드 알파(15.3, next build --turbopack) |
| 메타데이터 | viewport 등 분리 작업 진행(14에서 예고) | 15.2 스트리밍 메타데이터 도입, 15.3에서 viewport 옵션 분리 완료 |
| 에러 DX | 기본 개선 | 15.1~15.2에서 에러 UI/오너 스택 등 대폭 개선 |
| 보안/관측 | - | Server Actions 보안 강화(난수 ID, 미사용 제거), instrumentation.js 안정화, instrumentation-client 도입(15.3) |
| 기타 DX | - | next.config.ts 지원, ESLint 9 지원, Static Route Indicator, <Form> 컴포넌트 강화 |
출처: 14/15 릴리스 노트 및 15.1/15.2/15.3 블로그, React 19 블로그. (nextjs.org)
1) 캐싱 모델이 “기본 비캐시”로 바뀌었습니다
- 무엇이 바뀌었나
- fetch 요청, GET Route Handler, Client Router Cache(페이지 세그먼트)가 “기본적으로 캐시하지 않음”으로 변경되었습니다. 즉, 명시적으로 캐시에 “opt-in”해야 합니다. (nextjs.org)
- Router Cache의 Page segment
staleTime기본값이 0초가 되어, 내비게이션 시 항상 최신 데이터를 반영합니다(레이아웃은 재요청 안 함, 뒤로/앞으로 탐색은 스크롤 복원을 위해 캐시 사용, loading.js는 5분 유지). (nextjs.org)
핵심 메시지: 성능 최적화를 위해 “자동 캐시”를 널리 쓰던 14와 달리, 15는 “명시적 캐시” 철학을 강화했습니다. PPR(Partial Prerendering)과의 상호작용, 외부 라이브러리 사용 시 일관성을 고려한 결정입니다. (nextjs.org)
- 기존 코드에서 확인할 것(체크리스트)
- 서버 컴포넌트에서
fetch기본값 의존 여부 점검 후 필요한 곳에cache: 'force-cache'또는next: { revalidate: n }를 명시합니다. (nextjs.org) - GET Route Handler가 캐시될 것을 기대했다면, 라우트 설정에
export const dynamic = 'force-static'등으로 명시합니다. (nextjs.org) - 클라이언트 내비게이션에서 “페이지 데이터가 남아있을 것”이라는 가정을 제거하고, 필요하면
staleTimes설정으로 이전 동작을 복구합니다. (nextjs.org)
- 이전 동작으로 되돌리기(옵션)
// next.config.ts
const nextConfig = {
experimental: {
staleTimes: {
// Page segment를 예전처럼 캐시
dynamic: 30,
},
},
};
export default nextConfig;
위 설정은 공식 릴리스 노트의 예시와 동일한 의미입니다. (nextjs.org)
2) React 19 채택과 API 변화
- 15.1에서 React 19 “정식” 지원이 공지되었습니다(15.0 시점엔 App Router가 React 19 RC에 맞춰 릴리스). Pages Router는 18을 계속 쓸 수 있으나, 혼합 사용은 권장되지 않습니다. (nextjs.org)
- React 19의 공식 릴리스는 2024-12-05입니다(업그레이드 가이드/변경점은 React 블로그 참고). (react.dev)
- 폼/액션 관련해서는
useFormState가useActionState로 대체되는 흐름이 문서에 정리되어 있습니다. (nextjs.org)
참고 링크: React 19 블로그, Next.js 15 React 19 관련 섹션. (react.dev)
3) Turbopack: dev 안정화(15.0) → build 알파(15.3)
- 15.0에서
next dev --turbo가 안정화되어 대규모 앱에서도 체감 성능이 좋아졌습니다(시작 최대 76.7%↑, Fast Refresh 최대 96.3%↑ 등 내부 사례). (nextjs.org) - 15.3에서는
next build --turbopack알파가 공개되어 프로덕션 빌드 단계까지 영역을 확장했습니다(통합 테스트 99% 통과). 미션 크리티컬 환경에서는 도입 전 충분한 검증 권장. (nextjs.org)
4) DX 향상: 에러, 메타데이터, 폼, 내비게이션, 관측성
- 에러 DX
- 15.1~15.2에서 에러 UI/스택 트레이스가 크게 개선되었습니다(오너 스택 등). (nextjs.org)
- 스트리밍 메타데이터(15.2)
generateMetadata가 느려도 초기 UI 스트리밍을 막지 않도록 개선. (nextjs.org)<Form>컴포넌트- URL 파라미터를 갱신하는 GET 폼을 만들 때, 로딩 UI 프리패치/클라이언트 내비게이션 등 보일러플레이트를 줄입니다. App/Pages 모두 지원합니다. (nextjs.org)
- 내비게이션 훅(15.3)
useLinkStatus로 링크 단위 로딩 상태를 제어하고,onNavigate로 SPA 내비게이션 시점에만 실행되는 로직을 연결할 수 있습니다. (nextjs.org)- 관측성/보안
instrumentation.js안정화 및onRequestError훅, Server Actions의 난수 ID/미사용 제거로 보안·성능 강화. 15.3에서는 클라이언트 조기 실행용instrumentation-client.(js|ts)추가. (nextjs.org)
5) 마이그레이션 가이드: 14 → 15 필수 점검
A. 요청 기반 API가 비동기화됨(브레이킹)
다음 API는 async로 전환되었습니다: cookies, headers, draftMode, params/searchParams(일부 파일/훅에서), 등. 코데모드가 제공됩니다. (nextjs.org)
// 변경 전 (14)
import { cookies } from 'next/headers';
export function AdminPanel() {
const token = cookies().get('token');
// ...
}
// 변경 후 (15)
import { cookies } from 'next/headers';
export async function AdminPanel() {
const cookieStore = await cookies();
const token = cookieStore.get('token');
// ...
}
명령형 전환이 어렵다면 npx @next/codemod@canary next-async-request-api .를 사용하세요. (nextjs.org)
B. 캐싱 기본값 변경 반영
- fetch/GET/Router Cache의 기본 비캐시 전환을 전제하고, 필요한 곳에만 캐시를 켭니다. (nextjs.org)
C. 런타임/도구 체인
- Node 최소 버전: 18.18.0(14는 18.17.0). CI 이미지/런타임을 점검하세요. (nextjs.org)
- ESLint 9 지원(플랫 설정 자동 이스케이프 등),
next.config.ts타입 지원을 도입하세요. (nextjs.org)
6) 실제로 써보는 15 기능들
6-1. after API(응답 이후 작업 실행)
15.1에서 after()가 안정화되어 응답 스트리밍 이후 실행할 로깅/분석을 안전하게 예약할 수 있습니다. (nextjs.org)
// app/layout.tsx
import { after } from 'next/server';
import { log } from '@/lib/observability';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
after(() => {
// 응답이 끝난 뒤 실행
log('render-finished');
});
return <>{children}</>;
}
공식 레퍼런스: after 함수. (nextjs.org)
6-2. <Form> 컴포넌트로 검색 폼 구성
// app/page.tsx
import Form from 'next/form';
export default function Page() {
return (
<Form action="/search">
<input name="q" placeholder="검색어" />
<button type="submit">검색</button>
</Form>
);
}
// app/search/page.tsx
export default async function SearchPage({
searchParams,
}: {
searchParams: Promise<{ q?: string }>;
}) {
const { q } = await searchParams;
// q를 사용해 데이터 로드...
return <div>결과: {q}</div>;
}
기본적으로 폼이 뷰포트에 들어오면 대상 경로의 레이아웃/로딩 UI를 프리패치하고, 제출 시 클라이언트 내비게이션을 수행합니다. (nextjs.org)
6-3. 링크 단위 로딩 상태: useLinkStatus
// app/ui/LinkHint.tsx
'use client';
import { useLinkStatus } from 'next/link';
export function LinkHint() {
const { pending } = useLinkStatus();
return (
<span aria-hidden className={pending ? 'opacity-100' : 'opacity-0'}>
…
</span>
);
}
// app/Header.tsx
import Link from 'next/link';
import { LinkHint } from './ui/LinkHint';
export default function Header() {
return (
<header>
<Link href="/dashboard" prefetch={false}>
대시보드 <LinkHint />
</Link>
</header>
);
}
useLinkStatus는 링크 클릭 시점의 로딩 상태를 세밀하게 제어할 때 유용합니다. (nextjs.org)
7) 14 ↔ 15 차이 더 보기(공식 출처 요약)
- Next.js 14(2023-10-26): Server Actions 안정화, PPR 프리뷰, Turbopack dev 대규모 테스트. 최소 Node 18.17.0. (nextjs.org)
- Next.js 15(2024-10-21): 캐싱 기본값 전환, 요청 API 비동기화, Turbopack dev 안정화, Static Route Indicator, Server Actions 보안 강화, next.config.ts/ESLint9, self-hosting 개선 등. 최소 Node 18.18.0. (nextjs.org)
- Next.js 15.1(2024-12-10): React 19 정식 지원,
after안정화,forbidden/unauthorized(실험) 추가. (nextjs.org) - Next.js 15.2(2025-02-26): 에러 DX/스트리밍 메타데이터/Turbopack 성능/뷰 트랜지션(실험)/Node 미들웨어(실험). (nextjs.org)
- Next.js 15.3(2025-04-09):
next build --turbopack알파, 네비게이션 훅/클라이언트 계측 파일 도입 등. (nextjs.org)
8) 자주 하는 질문(FAQ)
- Pages Router는 React 18을 계속 써도 되나요?
- 15에서는 Pages Router에 한해 18 호환을 열어뒀지만, App/Pages 혼합 버전은 권장되지 않습니다. 장기적으로 19 전환을 권합니다. (nextjs.org)
- Turbopack 빌드를 지금 써도 될까요?
- 15.3 기준 알파이며, 미션 크리티컬 환경에선 단계적 도입을 추천합니다. (nextjs.org)
9) 실무 체크리스트(요약)
- Node를 18.18+로, CI 이미지를 업데이트. (nextjs.org)
-
cookies/headers/...호출부 async 전환(코데모드 사용 권장). (nextjs.org) - 캐싱 가정 제거: fetch/GET/Router Cache의 기본 비캐시 전환 반영. (nextjs.org)
- ESLint 9/
next.config.ts로 DX 개선. (nextjs.org) - React 19 업그레이드 타이밍 수립(특히 App Router). (nextjs.org)
코드 스니펫 모음
GET Route Handler 캐싱 명시
// app/api/feed/route.ts
export const dynamic = 'force-static'; // 이 라우트는 정적으로 캐시
export async function GET() {
const data = await fetch('https://api.example.com/feed', {
cache: 'force-cache',
});
return Response.json(await data.json());
}
15에서는 GET이 기본적으로 캐시되지 않으므로, 캐시가 필요하면 명시합니다. (nextjs.org)
Server Actions: 불필요 액션 제거/난수 ID
// app/actions.ts
'use server';
export async function updateUser(formData: FormData) {
// 사용되는 액션 → 안전한 난수 ID가 생성되어 클라이언트에서 참조
}
export async function unusedAction(formData: FormData) {
// 미사용 시 빌드에서 제거되어 공개 엔드포인트가 생성되지 않음
}
보안/번들 크기 측면에서 이점이 있습니다. (nextjs.org)
마무리
Next.js 15는 “캐싱 전략의 전환”과 “React 19 정식화”, “Turbopack 확장”을 중심으로 실무 체감 변화를 만들어냈습니다. 특히 기존 코드가 암묵적 캐시에 기대고 있다면, 15 업그레이드 전에 캐싱/동적성 가정을 전수 점검하세요. 공식 문서와 업그레이드 가이드를 함께 참고하시면 안전합니다: Next.js 15 릴리스 노트, 업그레이드 가이드, React 19 블로그. (nextjs.org)
읽어주셔서 감사합니다! 도움이 되셨다면 공유/피드백 부탁드립니다. 궁금한 점이나 “우리 프로젝트에서 이 부분이 문제인데?” 같은 사례가 있다면 댓글로 남겨주세요. 다음 포스트에서 더 깊이 다뤄보겠습니다.