| name | jikime-framework-nextjs@16 |
| description | Next.js 16 upgrade guide with breaking changes from 15. 'use cache' directive, PPR stable, updateTag, enhanced streaming. |
| tags | ["framework","nextjs","version","use-cache","ppr","updateTag"] |
| triggers | {"keywords":["nextjs 16","next.js 16","use cache","PPR","updateTag","cacheLife","cacheTag"],"phases":["run"],"agents":["frontend"],"languages":["typescript"]} |
| progressive_disclosure | {"enabled":true,"level1_tokens":"~100","level2_tokens":"~2611"} |
| type | version |
| framework | nextjs |
| version | 16 |
| previous_version | 15 |
| user-invocable | false |
Next.js 16 Upgrade Guide (from 15)
Next.js 15์์ 16์ผ๋ก ์
๊ทธ๋ ์ด๋ ์ ํ์ํ ์๋ก์ด ๊ธฐ๋ฅ๊ณผ ๋ง์ด๊ทธ๋ ์ด์
ํจํด์ ์ ์ํฉ๋๋ค.
Version Info
| ํญ๋ชฉ | ๊ฐ |
|---|
| Version | 16.0.0+ (canary) |
| Release Date | 2025 (Expected) |
| Node.js | 20+ |
| React | 19+ |
Base Conventions (from Next.js 14)
๋ค์ ๊ท์น์ Next.js 14๋ถํฐ ๋์ผํ๊ฒ ์ ์ฉ๋ฉ๋๋ค. ์์ธ ๋ด์ฉ์ jikime-framework-nextjs@14๋ฅผ ์ฐธ์กฐํ์ธ์.
| ๊ท์น | ์์ฝ |
|---|
| ํ๋ก์ ํธ ๊ตฌ์กฐ | src/app/ ๊ธฐ๋ฐ App Router, src/app/api/[endpoint]/route.ts API ๋ผ์ฐํธ |
| ๋ค์ด๋ฐ ๊ท์น | ํด๋/ํ์ผ: kebab-case, ์ปดํฌ๋ํธ export: PascalCase |
| UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ | shadcn/ui ํ์ ์ฌ์ฉ, lucide-react ์์ด์ฝ |
| ์คํ์ผ๋ง | Tailwind CSS + CSS variables ๊ธฐ๋ฐ ํ
๋ง |
Project Initialization (Next.js 16)
์ ํ๋ก์ ํธ๋ฅผ ์์ํ ๋๋ ๋ค์ ์์๋ก ์์ฑํฉ๋๋ค:
npx create-next-app@latest my-app --typescript --tailwind --eslint --app --src-dir
cd my-app
npx shadcn@latest init
npx shadcn@latest add button card input form table
CRITICAL: npx shadcn@latest init์ ๊ธฐ์กด Next.js ํ๋ก์ ํธ์์๋ง ์คํํฉ๋๋ค. ํ๋ก์ ํธ ์์ฑ์ ๋ฐ๋์ create-next-app์ผ๋ก ๋จผ์ ํด์ผ ํฉ๋๋ค.
New Features Summary
| ๊ธฐ๋ฅ | ์ํ | ์ค๋ช
|
|---|
'use cache' | Stable | ์ธ๋ถํ๋ ์บ์ฑ ์ ์ด |
cacheLife() | Stable | ์บ์ ์๋ช
์ ์ด |
cacheTag() | Stable | ํ๊ทธ ๊ธฐ๋ฐ ์บ์ ๊ด๋ฆฌ |
updateTag() | Stable | ์ฆ์ ์บ์ ๋ฌดํจํ |
| PPR | Stable | Partial Prerendering |
| Turbopack | Stable (prod) | ํ๋ก๋์
๋น๋ ์ง์ |
1. 'use cache' Directive (NEW)
Before (Next.js 15) - unstable_cache
import { unstable_cache } from 'next/cache'
const getCachedUser = unstable_cache(
async (id: string) => {
return await db.user.findUnique({ where: { id } })
},
['user'],
{ revalidate: 3600, tags: ['user'] }
)
After (Next.js 16) - 'use cache'
async function getUser(id: string) {
'use cache'
return await db.user.findUnique({ where: { id } })
}
async function UserProfile({ userId }: { userId: string }) {
'use cache'
const user = await db.user.findUnique({ where: { id: userId } })
return <div>{user.name}</div>
}
With cacheLife and cacheTag
import { cacheLife, cacheTag } from 'next/cache'
async function getProduct(id: string) {
'use cache'
cacheLife('hours')
cacheTag(`product-${id}`)
return await db.product.findUnique({ where: { id } })
}
cacheLife Options
cacheLife('seconds')
cacheLife('minutes')
cacheLife('hours')
cacheLife('days')
cacheLife('weeks')
cacheLife('max')
cacheLife({ stale: 300, revalidate: 60 })
2. updateTag vs revalidateTag
revalidateTag (Existing - Background)
import { revalidateTag } from 'next/cache'
export async function updateProduct(id: string, data: ProductData) {
await db.product.update({ where: { id }, data })
revalidateTag(`product-${id}`)
}
updateTag (NEW - Immediate)
import { updateTag } from 'next/cache'
export async function updateProduct(id: string, data: ProductData) {
await db.product.update({ where: { id }, data })
updateTag(`product-${id}`)
}
When to Use
| ์๋๋ฆฌ์ค | ๊ถ์ฅ |
|---|
| ์ฌ์ฉ์๊ฐ ์ฆ์ ๊ฒฐ๊ณผ๋ฅผ ๋ด์ผ ํจ | updateTag |
| ๋ฐฑ๊ทธ๋ผ์ด๋ ๊ฐฑ์ OK | revalidateTag |
| ๋๋ ๋ฐ์ดํฐ ๊ฐฑ์ | revalidateTag (์ฑ๋ฅ) |
| ๋จ์ผ ๋ ์ฝ๋ ๊ฐฑ์ | updateTag |
3. Partial Prerendering (PPR) - Stable
Enable PPR
const nextConfig = {
experimental: {
ppr: true,
}
}
PPR Pattern
import { Suspense } from 'react'
export default async function ProductPage({
params
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
return (
<div>
{/* Static: Pre-rendered at build time */}
<Header />
<ProductInfo id={id} />
{/* Dynamic: Streamed at request time */}
<Suspense fallback={<ReviewsSkeleton />}>
<DynamicReviews productId={id} />
</Suspense>
{/* Static */}
<Footer />
</div>
)
}
async function DynamicReviews({ productId }: { productId: string }) {
const reviews = await fetch(`/api/reviews/${productId}`, {
cache: 'no-store'
}).then(r => r.json())
return <ReviewList reviews={reviews} />
}
4. Server Actions Enhancements
Immediate UI Update Pattern
'use client'
import { useOptimistic, useTransition } from 'react'
import { updateProduct } from './actions'
export function ProductEditor({ product }) {
const [optimisticProduct, setOptimisticProduct] = useOptimistic(product)
const [isPending, startTransition] = useTransition()
async function handleUpdate(formData: FormData) {
const newName = formData.get('name') as string
setOptimisticProduct({ ...product, name: newName })
startTransition(async () => {
await updateProduct(product.id, { name: newName })
})
}
return (
<form action={handleUpdate}>
<input name="name" defaultValue={optimisticProduct.name} />
<button disabled={isPending}>Save</button>
</form>
)
}
Server Action with updateTag
'use server'
import { updateTag } from 'next/cache'
export async function updateProduct(id: string, data: Partial<Product>) {
await db.product.update({ where: { id }, data })
updateTag(`product-${id}`)
updateTag('products')
}
5. Turbopack Production (Stable)
next dev --turbo
next build --turbo
const nextConfig = {
experimental: {
turbo: {
// Turbopack config
}
}
}
6. Enhanced Streaming
Streaming with Suspense Boundaries
import { Suspense } from 'react'
export default function Dashboard() {
return (
<div className="grid grid-cols-3 gap-4">
{/* Each streams independently */}
<Suspense fallback={<CardSkeleton />}>
<RevenueCard />
</Suspense>
<Suspense fallback={<CardSkeleton />}>
<UsersCard />
</Suspense>
<Suspense fallback={<CardSkeleton />}>
<OrdersCard />
</Suspense>
</div>
)
}
async function RevenueCard() {
'use cache'
cacheLife('minutes')
const revenue = await getRevenue()
return <Card title="Revenue" value={revenue} />
}
Migration from Next.js 15
Step 1: Update Dependencies
npm install next@16 react@19 react-dom@19
Step 2: Update Caching Strategy
import { unstable_cache } from 'next/cache'
const getData = unstable_cache(async () => {...}, ['key'], { revalidate: 60 })
async function getData() {
'use cache'
cacheLife('minutes')
cacheTag('data')
return ...
}
Step 3: Update Invalidation
revalidateTag('products')
updateTag('products')
revalidateTag('products')
Step 4: Enable PPR (Optional)
const nextConfig = {
experimental: {
ppr: true,
}
}
Migration Checklist
Caching
Performance
Testing
Common Patterns
Cached Data with Immediate Invalidation
import { cacheLife, cacheTag } from 'next/cache'
export async function getProducts() {
'use cache'
cacheLife('hours')
cacheTag('products')
return await db.product.findMany()
}
export async function getProduct(id: string) {
'use cache'
cacheLife('hours')
cacheTag(`product-${id}`)
cacheTag('products')
return await db.product.findUnique({ where: { id } })
}
'use server'
import { updateTag } from 'next/cache'
export async function createProduct(data: ProductData) {
await db.product.create({ data })
updateTag('products')
}
export async function updateProduct(id: string, data: Partial<Product>) {
await db.product.update({ where: { id }, data })
updateTag(`product-${id}`)
updateTag('products')
}
PPR with Auth
import { Suspense } from 'react'
import { auth } from '@/lib/auth'
export default async function DashboardPage() {
return (
<div>
{/* Static shell */}
<DashboardHeader />
{/* Dynamic: User-specific content */}
<Suspense fallback={<WelcomeSkeleton />}>
<WelcomeMessage />
</Suspense>
{/* Static */}
<DashboardNav />
{/* Dynamic: Real-time data */}
<Suspense fallback={<StatsSkeleton />}>
<LiveStats />
</Suspense>
</div>
)
}
async function WelcomeMessage() {
const session = await auth()
return <h1>Welcome, {session?.user?.name}</h1>
}
Related Skills
| ์คํฌ | ์ฉ๋ |
|---|
jikime-framework-nextjs@14 | Next.js 14 App Router ๊ธฐ๋ณธ ํจํด, ํ๋ก์ ํธ ๊ตฌ์กฐ, ๋ค์ด๋ฐ ๊ท์น, shadcn/ui |
jikime-framework-nextjs@15 | Next.js 15 ์
๊ทธ๋ ์ด๋ ๊ฐ์ด๋ (async params, fetch caching) |
jikime-platform-vercel | Vercel ๋ฐฐํฌ, Edge Functions, ISR |
jikime-library-shadcn | shadcn/ui ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ (Next.js ํ์) |
Version: 1.1.0
Last Updated: 2026-01-23
Previous Version: See jikime-framework-nextjs@15