고민보단 실천을

Next.js App Router 캐싱 정리: fetch cache, revalidate, no-store로 데이터 최신화하기 본문

카테고리 없음

Next.js App Router 캐싱 정리: fetch cache, revalidate, no-store로 데이터 최신화하기

Just-Do-It 2026. 2. 28. 14:59

Next.js App Router 캐싱 정리: fetch cache, revalidate, no-store로 데이터 최신화하기

Next.js App Router에서 가장 많이 검색되는 문제는 이겁니다: 배포했는데 데이터가 안 바뀐다. 원인은 대개 캐싱/재검증(revalidate) 설정이 의도와 다르게 걸려서입니다. 이 글은 App Router 기준으로 fetch 캐싱을 실무 관점에서 정리합니다.

Next.js caching flow
Server Component에서 fetch 옵션이 캐시/재검증 정책을 결정합니다.

핵심 개념 3개

App Router에서 데이터 최신화는 보통 3가지 축으로 제어합니다: 1) fetch 캐시 정책 2) revalidate 재검증 간격 3) 라우트/세그먼트 단위의 동적 렌더링 강제입니다. 여기서 가장 영향력이 큰 건 fetch 옵션입니다.

옵션/핵심 요소(3~6개)

항목의미언제 쓰는지(실무 상황)
next: { revalidate: N }N초마다 재검증뉴스/피드처럼 완전 실시간은 아니지만 자주 바뀌는 데이터
cache: 'no-store'항상 최신 요청사용자별 데이터, 결제/권한 등 캐시하면 사고 나는 데이터
revalidateTag/revalidatePath원하는 시점에 무효화CMS 발행/관리자 업데이트 후 즉시 반영해야 할 때
Dynamic 렌더링정적 최적화 방지요청마다 달라져야 하는 페이지(세션/쿠키 기반)
CDN 캐시엣지/프록시 캐시 영향서버 코드는 맞는데 사용자에겐 여전히 옛 데이터가 보일 때

실전 예시: 목록은 60초 캐시, 상세는 즉시 최신

목록 페이지는 60초 단위로만 갱신해도 충분한 경우가 많고, 상세 페이지는 수정 직후 바로 최신이 보여야 하는 경우가 많습니다. 이때 fetch 단위로 정책을 분리합니다.

// app/posts/page.tsx (Server Component)
const res = await fetch('https://api.example.com/posts', { next: { revalidate: 60 } })
const posts = await res.json()

// app/posts/[id]/page.tsx (Server Component)
const res2 = await fetch(`https://api.example.com/posts/${params.id}`, { cache: 'no-store' })
const post = await res2.json()

문제 상황(정확히 1개)

상황: 관리자에서 글을 수정했는데, Next.js 페이지에는 몇 분 동안 예전 내용이 계속 보인다.

원인: 목록/상세 중 어딘가의 fetch가 의도치 않게 캐시되고 있고, 무효화(revalidate)가 발생하지 않는다. 특히 기본값을 '항상 최신'으로 착각하는 경우가 많다.

해결: 즉시 최신이 필요한 요청은 cache: 'no-store'로 고정하고, 캐시가 필요한 요청은 next: { revalidate: N }로 명시한다. 업데이트 직후 반영이 필요하면 태그/경로 기반 무효화(revalidateTag/revalidatePath)를 붙인다.

예방 팁: 페이지 단위가 아니라 데이터 요청(fetch) 단위로 캐시 정책을 문서화하고, '이 데이터는 캐시 가능/불가'를 팀 규칙으로 정한다.

참고/출처

Comments