학습 문서/api reference/functions

revalidateTag#

학습 목표#

  • 특정 캐시 태그가 지정된 데이터를 온디맨드로 무효화하는 revalidateTag 함수의 사용법을 익힌다.
  • 백그라운드에서 데이터를 갱신하면서 이전 캐시를 즉시 서빙하는 Stale-While-Revalidate(SWR) 동작 메커니즘을 이해한다.
  • Next.js 최신 2인자 시그니처인 profile="max" 옵션과 웹훅용 { expire: 0 }의 역할을 파악한다.
  • Server Action 및 Route Handler(외부 CMS 웹훅 등)에서 태그 기반 revalidate을 구현한다.

핵심 개념 및 설명#

revalidateTag는 특정 캐시 태그와 연결된 캐시 데이터를 온디맨드로 무효화할 수 있게 해주는 함수다.

약간의 업데이트 지연이 허용되는 블로그 게시물, 상품 카탈로그, 문서 사이트 등에 이상적이다. 사용자는 백그라운드에서 새 데이터가 로드되는 동안 기존 캐시 콘텐츠를 지연 없이 즉시 제공받는다.

실행 환경 및 시그니처#

revalidateTag는 서버 환경인 Server FunctionRoute Handler에서만 실행할 수 있다.

ts
revalidateTag(tag: string, profile: string | { expire?: number }): void
  • tag: revalidate하려는 데이터와 연결된 캐시 태그 문자열(최대 256자, 대소문자 구분).
  • profile: revalidation 동작 방식을 지정하는 프로필이다.
  • `profile="max"` (권장): 태그 항목을 stale 상태로 표시하고, 다음 방문 시 백그라운드에서 새로고침을 수행하는 Stale-While-Revalidate 시맨틱을 제공한다.
  • `{ expire: 0 }`: 외부 웹훅 호출 시 즉각적인 만료가 필요한 경우 사용한다.
  • 단일 인자 형태 (더 이상 권장되지 않음): 인자 없이 revalidateTag(tag)만 호출하는 형태는 deprecated되었으며, 2인자 시그니처를 사용하거나 `updateTag`로 마이그레이션해야 한다.
알아두면 좋은 점 (revalidateTag 호출 규격 및 동작):
- 단일 인자 호출의 Deprecation: revalidateTag(tag)와 같이 1개 인자만 넘기는 형태는 deprecated되었다. TypeScript 환경에서는 수명 프로필('max')이나 옵션 객체({ expire: 0 })를 2번째 인자로 명시해야 한다.
- 즉시 만료 (`{ expire: 0 }`): Strapi, Contentful 등의 CMS 웹훅이나 실시간 업데이트가 필요한 경우, { expire: 0 }을 전달하여 캐시를 즉시 만료시킬 수 있다.
- `profile="max"` 동작: profile="max"를 사용할 때 revalidateTag는 태그 데이터를 stale로 표시하며, 사용자가 해당 페이지를 방문할 때 백그라운드에서 새로운 데이터를 가져온다 (SWR).
- `updateTag`와의 차이점: revalidateTag는 다음 방문 시 백그라운드에서 데이터를 갱신하는 반면, `updateTag`는 읽기 전용 캐시를 즉시 새 값으로 덮어쓴다.

데이터에 태그를 부여하는 방법#

  1. `fetch` 요청 시:
app/actions.tstsx
   fetch(url, { next: { tags: ['posts'] } })
  1. `'use cache'` 스코프 내부에서:
app/actions.tstsx
   import { cacheTag } from 'next/cache'

   async function getData() {
     'use cache'
     cacheTag('posts')
     return await fetchFromDb()
   }

예제#

1. Server Action에서 태그 revalidate#

app/actions.tsts
'use server'

import { revalidateTag } from 'next/cache'

export default async function submit() {
  await addPost()
  revalidateTag('posts', 'max')
}
app/actions.jsjs
'use server'

import { revalidateTag } from 'next/cache'

export default async function submit() {
  await addPost()
  revalidateTag('posts', 'max')
}

2. Route Handler에서 CMS 웹훅 처리#

외부 CMS에서 콘텐츠가 발행되었을 때 웹훅 엔드포인트를 통해 태그를 무효화할 수 있다:

app/api/revalidate/route.tsts
import type { NextRequest } from 'next/server'
import { revalidateTag } from 'next/cache'

export async function POST(request: NextRequest) {
  const secret = request.nextUrl.searchParams.get('secret')
  if (secret !== process.env.REVALIDATION_SECRET) {
    return Response.json({ message: '유효하지 않은 토큰입니다' }, { status: 401 })
  }

  const { tag } = await request.json()
  if (tag) {
    // 웹훅을 통한 즉시 만료는 { expire: 0 } 사용 가능
    revalidateTag(tag, 'max')
    return Response.json({ revalidated: true, now: Date.now() })
  }

  return Response.json({ revalidated: false, message: '태그가 누락되었습니다' })
}
app/api/revalidate/route.jsjs
import { revalidateTag } from 'next/cache'

export async function POST(request) {
  const secret = request.nextUrl.searchParams.get('secret')
  if (secret !== process.env.REVALIDATION_SECRET) {
    return Response.json({ message: '유효하지 않은 토큰입니다' }, { status: 401 })
  }

  const { tag } = await request.json()
  if (tag) {
    revalidateTag(tag, 'max')
    return Response.json({ revalidated: true, now: Date.now() })
  }

  return Response.json({ revalidated: false, message: '태그가 누락되었습니다' })
}

Version History#

버전변경 사항
v16.0.0profile을 요구하는 2인자 시그니처 도입 및 단일 인자 형태 deprecated 안내
v13.0.0revalidateTag 도입

예제 및 데모 설계#

  • Strapi/Contentful 등의 CMS 글 수정 웹훅을 수신하여 revalidateTag('posts', 'max')를 실행하고, 다음 페이지 접근 시 백그라운드 revalidation이 일어나는 과정을 검증한다.
  • profile="max" 적용 시 기존 캐시가 즉시 응답되고 이후 백그라운드 갱신 데이터로 교체되는 SWR 시나리오를 테스트한다.
  • updateTagrevalidateTag의 응답 대기 시간 차이를 비교한다.

연습 문제#

  1. revalidateTag('articles', 'max')를 호출했을 때의 동작 방식으로 올바른 것은?
  • A. 'articles' 태그가 지정된 모든 페이지를 즉시 빌드하여 서버가 멈춘다.
  • B. 해당 태그를 stale 상태로 표시하고, 다음 방문 시 이전 캐시를 서빙하면서 백그라운드에서 새 데이터를 가져온다.
  • C. 데이터베이스의 모든 레코드를 삭제한다.
  • D. 클라이언트의 브라우저 쿠키를 삭제한다.
정답 보기

정답: B 해설: profile="max" 옵션과 함께 revalidateTag를 호출하면 태그 항목이 stale로 마킹되어, 다음 요청 시 이전 캐시를 우선 반환하고 백그라운드에서 revalidation을 수행한다.

  1. Next.js 최신 버전에서 revalidateTag의 권장 시그니처 형태는?
  • A. revalidateTag(tag) (단일 인자)
  • B. revalidateTag(tag, profile) (2인자 형태)
  • C. revalidateTag(path, type)
  • D. revalidateTag(url, headers)
정답 보기

정답: B 해설: Next.js에서는 revalidation 수명 프로필을 명시하는 2인자 시그니처(revalidateTag(tag, profile)) 사용이 권장된다.

챕터 요약#

  • revalidateTag는 특정 캐시 태그와 연결된 데이터를 온디맨드로 무효화하는 함수다.
  • profile="max"를 전달하여 백그라운드 갱신(Stale-While-Revalidate) 방식으로 원활한 사용자 경험을 제공한다.
  • fetchnext: { tags: [...] } 또는 'use cache' 내부의 cacheTag()로 태그를 부여한다.
  • Server Action과 Route Handler에서 안전하게 호출할 수 있다.
  • 폼 제출 후 즉각적인 최신 데이터 조회가 필요한 경우는 updateTag를 사용하는 것이 권장된다.

이 문서의 실습 데모