정적 속도와 충분히 새로운 데이터를 함께 얻어
시간 기반 재검증은 App Router의 ISR 방식이야. 페이지를 미리 렌더링해 캐시에서 빠르게 제공하되, 정해 둔 시간이 지나면 다음 요청이 백그라운드 갱신을 시작해. 그 요청을 보낸 사용자는 새 렌더링을 기다리지 않고 기존 캐시를 즉시 받아.
요청 하나와 라우트 전체 중 범위를 골라
| 범위 | 설정 |
|---|---|
특정 fetch() | fetch(url, { next: { revalidate: 60 } }) |
| 페이지나 레이아웃 구간 | export const revalidate = 60 |
수명 주기를 순서대로 보자
처음 요청은 렌더링한 결과를 캐시에 넣어. 재검증 시간 안의 요청은 그 결과를 곧바로 받아. 시간이 지난 뒤 첫 요청은 오래된 결과를 받으면서 백그라운드 갱신을 시작하고, 갱신이 끝난 다음 요청부터 새 결과를 받아. 그래서 사용자는 “새 콘텐츠를 만드는 중”이라는 spinner를 보지 않아.
초 단위 숫자는 제품 요구에서 나와야 해
재검증 간격이 짧을수록 새롭지만 계산량이 늘고, 길수록 싸지만 오래된 값을 보여 줄 가능성이 커져. 가격, 글, 재고처럼 데이터 종류마다 허용 가능한 지연을 먼저 정해.
재검증 간격은 콘텐츠 생산 주기보다 사용자에게 허용되는 지연으로 정해. 하루 한 번 편집해도 게시 직후 바로 보여야 한다면 긴 ISR과 요청형 무효화를 함께 쓸 수 있어. 캐시 응답의 나이와 백그라운드 갱신 실패를 관측해야 숫자가 실제로 지켜지는지도 알 수 있어.
ISR은 정확히 N초마다 자동 새로 만드는 cron이 아니야. 시간이 지난 뒤 들어온 다음 요청이 갱신을 시작하므로 트래픽이 없으면 새 결과도 만들어지지 않아. 정해진 시각에 반드시 갱신해야 하는 데이터는 별도 작업이나 webhook이 필요해. 짧은 재검증 간격을 설정하고 창 안과 밖에서 여러 번 요청해 stale 응답과 백그라운드 갱신 순서를 기록해. 창이 지나도 요청이 없으면 새 결과가 생기지 않는다는 점을 확인하고, 갱신이 실패했을 때 이전 캐시가 어떻게 제공되는지도 시험해. 재검증 중 동시에 여러 요청이 들어왔을 때 갱신 작업이 중복되는지도 관측해. 플랫폼과 배포 형태에 따라 캐시 공유 범위가 다르므로 개발 서버에서 본 한 번의 동작을 전 세계 production의 보장으로 확대하면 안 돼.