Intro
Next.js를 사용하면 전체 사이트를 다시 빌드할 필요 없이 특정 정적 경로를 업데이트할 수 있다. 재검증( Incremental Static Regeneration이라고도 함)을 사용하면 수 백만 페이지로 확장하면서도 정적의 이점을 유지할 수 있다.
Next.js에는 두 가지 유형의 revalidation이 있다.
- Background: 특정 시간 간격으로 데이터의 유효성을 재검증한다.
- On-demand: 업데이트와 같은 이벤트를 기반으로 데이터의 유효성을 재검증한다.
TOC
Background Revalidation
특정 간격으로 캐시된 데이터의 유효성을 재검증하려면 fetch()
의 next.revalidate
옵션을 사용하여 리소스의 cache
수명(초)을 설정할 수 있다.
fetch('https://...', { next: { revalidate: 60 } })
fetch
를 사용하지 않는 데이터(예: 외부 패키지 또는 쿼리 빌더 사용)의 유효성을 다시 확인하려면 route segment config을 사용할 수 있다.
export const revalidate = 60 // revalidate this page every 60 seconds
fetch
외에도 캐시를 사용하여 데이터의 유효성을 다시 검사할 수도 있다.
어떻게 작동하는지 살펴보기.
- 빌드 시점에 정적으로 렌더링된 경로에 대한 요청이 이루어지면 처음에는 캐시된 데이터가 표시다.
- 최초 요청 이후, 60초 이전의 경로에 대한 모든 요청도 캐시되어 즉시 표시된다.
- 60초가 지난 후에도 다음 요청에는 캐시된(오래된) 데이터가 계속 표시된다.
- Next.js는 백그라운드에서 데이터 regeneration을 트리거한다.
- 경로가 성공적으로 생성되면 Next.js는 캐시를 무효화하고 업데이트된 경로를 표시한다. 백그라운드 재생성이 실패하면 이전 데이터는 여전히 변경되지 않는다.
생성되지 않은 경로 세그먼트에 대한 요청이 이루어지면 Next.js는 첫 번째 요청에서 경로를 동적으로 렌더링한다. 이후 요청은 캐시에서 정적 경로 세그먼트를 제공한다.
upstream data provider가 기본적으로 캐싱을 활성화했는지 확인해야한다. 비활성화해야 할 수도 있다(예: useCdn: false
). 그렇지 않으면 재검증에서 새로운 데이터를 가져와서 ISR 캐시를 업데이트할 수 없다. 캐싱은 (요청 중인 엔드포인트에 대해) Cache-Control
헤더를 반환할 때 CDN에서 발생할 수 있다. Vercel의 ISR은 캐시를 전역적으로 유지하고 롤백을 처리한다.
On-demand Revalidation
revalidate
시간을 60
으로 설정하면 모든 방문자는 1분 동안 동일한 버전의 사이트를 볼 수 있다. 캐시를 무효화하는 유일한 방법은 1분 경과 후 누군가 페이지를 방문하는 경우다.
Next.js App Router는 경로 또는 캐시 태그를 기반으로 온디맨드 콘텐츠 재검증을 지원한다. 이를 통해 특정 가져오기에 대해 Next.js 캐시를 수동으로 제거할 수 있으므로 언제 사이트를 업데이트할지 쉽게 결정할 수 있다.
- headless CMS의 콘텐츠가 생성되거나 업데이트된다.
- 전자상거래 metadata(가격, 설명, 카테고리, 리뷰 등)가 변경된다.
Using On-Demand Revalidation
데이터는 경로(revalidatePath
) 또는 캐시 태그(revalidateTag
)를 통해 온디맨드 방식으로 재검증할 수 있다.
예를 들어, 다음 fetch
에 collection
태그를 추가한다.
export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
const data = await res.json()
// ...
}
이렇게 캐시된 데이터는 Route Handler에서 revalidateTag
를 호출하여 온디맨드 방식으로 재검증할 수 있다.
import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'
export async function GET(request: NextRequest) {
const tag = request.nextUrl.searchParams.get('tag')
revalidateTag(tag)
return NextResponse.json({ revalidated: true, now: Date.now() })
}