Next.js 캐시 무효화 실전 가이드: ISR, revalidateTag, CDN 캐시를 한 번에 정리
💡 Key Takeaways
- 캐시 문제는 성능 문제가 아니라 데이터 신뢰 문제로 이어지기 때문에, 무효화 전략을 먼저 설계해야 합니다.
- ISR, 데이터 캐시, CDN 캐시는 서로 다른 계층이므로 각 계층별로 갱신 트리거를 분리해야 안전합니다.
- revalidateTag를 도입하면 콘텐츠 타입 단위로 갱신 범위를 제어할 수 있어 과도한 전체 무효화를 줄일 수 있습니다.
- 운영 단계에서는 캐시 히트율보다 오래된 데이터 노출 시간을 KPI로 관리하는 것이 실용적입니다.
Next.js 캐시 무효화 실전 가이드
Next.js 프로젝트를 운영하다 보면, 초반에는 "정말 빠르다"는 감탄이 먼저 나오지만 일정 규모를 넘기면 반대 문제가 생깁니다. 페이지는 빠른데, 데이터가 늦게 갱신됩니다. 특히 공지, 가격, 재고, 이벤트 일정처럼 시간 민감도가 높은 데이터가 캐시에 오래 남아 있으면 사용자 신뢰가 빠르게 무너집니다. 그래서 캐시 전략은 단순한 성능 최적화가 아니라, 제품 신뢰를 다루는 운영 설계에 가깝습니다.
실무에서 가장 많이 보던 실수는 "캐시를 끄면 해결된다"는 접근입니다. 단기적으로는 맞지만, 트래픽이 늘면 서버 비용과 응답 지연이 곧바로 올라갑니다. 반대로 캐시를 과하게 켜면 운영팀이 데이터 갱신 이슈를 매번 수동으로 처리하게 됩니다. 정답은 둘 중 하나가 아니라, 어떤 데이터를 얼마나 오래 신뢰할 수 있는지를 기준으로 계층별 무효화 규칙을 분리하는 것입니다.
1. 캐시 계층을 먼저 분리해 이해하기
Next.js에서 흔히 말하는 캐시는 하나가 아닙니다. 페이지 생성 결과(ISR), 서버에서 가져온 데이터(fetch 캐시), 그리고 CDN 엣지 캐시가 동시에 동작합니다. 문제는 이 세 계층이 같은 시점에 갱신되지 않는다는 점입니다. 예를 들어 ISR이 갱신돼도 CDN 캐시가 남아 있으면 사용자에게는 여전히 이전 화면이 보일 수 있습니다.
운영 관점에서 권장하는 방법은 데이터 도메인별 TTL을 먼저 정의하는 것입니다. 예를 들어 블로그 본문은 30분, 가격 정보는 1분, 관리자 공지는 즉시 반영처럼 기준을 명시해 두면 팀 전체가 같은 룰로 움직일 수 있습니다. 이 기준이 없으면 개발자마다 revalidate 값을 다르게 넣어서, 나중에 어느 경로가 stale 데이터를 뿌리는지 추적하기 어려워집니다.
2. ISR과 on-demand revalidation의 역할 분담
ISR은 "주기적 재생성"에 강하고, on-demand revalidation은 "이벤트 기반 즉시 갱신"에 강합니다. 둘 중 하나만 쓰기보다, 콘텐츠 특성에 따라 역할을 나누는 것이 안전합니다. 예를 들어 기사/문서 페이지는 ISR로 관리하고, 운영자가 게시 상태를 변경하는 순간에는 webhook으로 revalidate를 호출해 즉시 반영하도록 설계할 수 있습니다.
여기서 중요한 점은 모든 페이지를 즉시 갱신 대상으로 만들지 않는 것입니다. 실시간성이 필요 없는 페이지까지 즉시 무효화하면 빌드/렌더링 부하가 급격히 증가합니다. 저는 보통 "사용자 오판 가능성"이 있는 데이터만 즉시 갱신 대상으로 묶고, 나머지는 주기 갱신으로 유지합니다. 이 방식이 장애와 비용을 모두 줄여줍니다.
3. revalidateTag를 도입할 때의 기준
App Router에서는 revalidateTag를 활용해 태그 단위 무효화를 적용할 수 있습니다. 이 기능의 장점은 명확합니다. URL 전체를 무효화하지 않고, 특정 도메인 데이터만 갱신할 수 있어 과도한 캐시 파괴를 막을 수 있습니다. 예를 들어 tag:product:123처럼 설계하면 해당 상품 관련 화면만 선택적으로 갱신할 수 있습니다.
다만 태그 설계가 너무 세밀하면 운영 복잡도가 올라갑니다. 반대로 너무 넓으면 거의 전체 무효화와 다를 바가 없습니다. 저는 보통 site, section, entity 3단계로 시작합니다. 예를 들어 공통 네비게이션은 site:nav, 카테고리 목록은 section:blog, 개별 상세는 entity:post:slug처럼 나누면 추적성과 성능의 균형을 맞추기 쉽습니다.
4. CDN 캐시까지 포함한 점검 루틴
개발 단계에서 로컬 서버만 보고 "갱신된다"고 판단하면 운영에서 자주 사고가 납니다. 실제 서비스는 CDN이 앞단에 있으므로, 캐시 헤더와 재검증 조건까지 함께 점검해야 합니다. 특히 stale-while-revalidate를 사용할 때는 사용자에게 얼마나 오래된 화면이 보여질 수 있는지 팀이 이해하고 있어야 합니다.
운영 체크리스트는 단순합니다. 첫째, 콘텐츠 수정 직후 관리자 계정과 일반 사용자 계정에서 동시에 갱신 여부를 확인합니다. 둘째, 모바일 네트워크 환경에서 첫 요청과 재요청을 비교합니다. 셋째, CDN 대시보드에서 purge 이력이 실제 트래픽 감소와 연결되는지 봅니다. 이 세 단계만 매 릴리스마다 반복해도 "갱신됐다고 했는데 왜 안 보이죠" 같은 문의가 크게 줄어듭니다.
5. 지표는 히트율보다 오래된 데이터 노출 시간
팀이 캐시 전략을 잘 운영하고 있는지 보려면 단순 히트율보다 사용자 관점 지표가 필요합니다. 제가 추천하는 핵심 지표는 "변경 후 최신 데이터가 사용자에게 반영되기까지 걸린 시간"입니다. 이 값을 엔터티별로 추적하면, 어떤 도메인이 캐시 정책 때문에 신뢰 리스크를 만들고 있는지 명확하게 보입니다.