본문으로 건너뛰기
개발 머꼬
개발 노트Next.js
hohyeon.dev18

revalidate를 지웠는데 페이지가 빌드 시점 데이터로 굳어 있던 이유

  • #Common Pitfall
  • #Engineering Note
  • #Next.js

문제 발생

DB에서 목록을 읽는 sitemap.ts가 새 글을 반영하지 않았습니다. 배포할 때마다 그 시점의 목록으로 고정됐습니다.

revalidate 설정을 지웠는데도 그대로였고, 결국 DB에 접속할 수 없는 Docker 빌드 환경에서 빌드가 실패하면서야 원인이 드러났습니다. 빌드 중에 DB를 읽고 있었던 것입니다.

원인 분석

Next.js는 기본값(dynamic = 'auto')에서 가능한 한 많이 캐시합니다. 공식 문서의 표현대로 "어떤 컴포넌트도 동적 동작을 선택하지 못하게 막지 않으면서 최대한 캐시하는" 것이 기본 옵션입니다.

여기서 중요한 것은 무엇이 라우트를 동적으로 만드는가입니다. cookies(), headers(), searchParams 같은 요청 시점(Request-time) API를 쓰거나 캐시되지 않은 데이터를 가져오면 동적이 됩니다. 그런 신호가 하나도 없으면 Next.js는 그 라우트를 정적으로 판단하고 빌드 시점에 한 번 실행해 결과를 굳힙니다.

sitemap.ts 안에는 그런 API 호출이 전혀 없었습니다. DB 조회는 fetch가 아니라 드라이버 호출이라 Next.js가 "동적"이라고 볼 근거가 없습니다. 그래서 revalidate를 지우는 것만으로는 동적이 되지 않고, 오히려 정적으로 되돌아갔습니다.

로컬에서는 .env.local의 DB가 항상 연결되므로 빌드가 조용히 성공해서 이 차이가 드러나지 않았습니다.

해결 방안

  1. 매 요청 실행이 필요하면 명시합니다. 추측에 맡기지 않습니다.
export const dynamic = "force-dynamic";

문서 기준 이 값은 요청 시점마다 사용자별로 라우트를 렌더하도록 강제하며, 레이아웃/페이지의 모든 fetch{ cache: 'no-store', next: { revalidate: 0 } }를 설정하고 fetchCache = 'force-no-store'를 설정한 것과 같습니다.

  1. 네 값의 뜻을 구분합니다.
동작
'auto' (기본)동적 선택을 막지 않는 선에서 최대한 캐시
'force-dynamic'요청 시점마다 렌더
'error'정적 렌더를 강제하고, 요청 시점 API나 캐시되지 않은 데이터를 쓰면 오류
'force-static'정적 렌더를 강제하고 cookies()·headers()·useSearchParams()빈 값을 반환하게 함
  1. 'force-static'의 부작용을 압니다. 오류가 아니라 빈 값이 돌아옵니다. 쿠키를 읽어 분기하는 코드가 조용히 "로그아웃 상태"로 동작합니다.

  2. 정적이어야 하는 페이지에는 'error'가 좋은 안전장치입니다. 실수로 요청 시점 API가 들어오면 빌드에서 막힙니다.

  3. revalidate는 다른 축입니다. false(기본)는 사실상 무기한 캐시, 0요청 시점 API나 캐시되지 않은 fetch가 없어도 항상 동적으로 렌더하게 만들고, 숫자는 그 초만큼의 재검증 주기입니다. 값은 정적으로 분석 가능해야 해서 revalidate = 600은 되지만 revalidate = 60 * 10은 안 됩니다.

  4. next build 출력으로 실제 결과를 확인합니다. 의도와 실제가 다른지는 여기서만 드러납니다.

○  (Static)   prerendered as static content
ƒ  (Dynamic)  server-rendered on demand
  1. 개발 서버로는 확인되지 않습니다. 문서도 명시하듯 개발 환경에서 페이지는 항상 요청 시점에 렌더되고 캐시되지 않습니다. 정적/동적 판정은 next build로만 보입니다.

  2. 버전 조건을 확인합니다. Next.js 16에서 cacheComponents 플래그를 켜면 dynamic·dynamicParams·revalidate·fetchCache 라우트 세그먼트 설정이 제거됩니다. 이 글은 그 플래그를 쓰지 않는 프로젝트 기준입니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.