Next.js 캐시·CDN 전략 가이드: App Router 라우트별 Cache-Control·RSC·브라우저 캐시 기준

결론부터 말하면, Next.js 캐시·CDN 전략은 ‘빠르게 보이게 할 화면’과 ‘절대 섞이면 안 되는 데이터’를 먼저 분리하는 일입니다. 랜딩 페이지, 블로그, 문서형 페이지는 서버 캐시와 CDN 캐시를 적극 활용해도 됩니다. 반대로 로그인 기반 SaaS 대시보드, 결제·권한·관리자 화면은 공유 CDN 캐시를 기본적으로 피하고, 사용자별 데이터가 섞이지 않도록 no-store, private, 태그 기반 서버 재검증을 구분해야 합니다.
실무에서 문제가 되는 지점은 대부분 ‘캐시를 켰다/껐다’가 아닙니다. 가격표는 빠르게 보여주고 싶지만 수정 즉시 반영되어야 하고, 관리자에서 공지를 저장했는데 랜딩에는 예전 문구가 남아 있으며, SaaS 대시보드에서는 고객사별 데이터가 절대 섞이면 안 됩니다. 이 글은 Next.js App Router를 기준으로 서버 캐시, CDN 캐시, 브라우저 캐시, RSC 응답 캐시 키, revalidateTag·revalidatePath 무효화 절차를 운영 관점에서 나눠 정리합니다.
1. 먼저 캐시를 다섯 층으로 나눠야 한다
App Router에서 캐시는 하나가 아닙니다. 브라우저 HTTP 캐시, Next.js Router Cache, 서버 데이터 캐시, Full Route Cache 또는 prerender output, CDN 캐시가 서로 다른 위치에서 동작합니다. 특히 RSC payload는 일반 HTML과 다르게 라우팅 상태와 요청 헤더에 따라 응답 변형이 생길 수 있으므로, CDN이 캐시 키를 잘못 잡으면 화면 깨짐이나 오래된 데이터 노출로 이어집니다. Next.js 문서도 CDN 앞단에서 rsc, next-router-state-tree, next-router-prefetch, _rsc 쿼리 처리를 명확히 다루고 있습니다. ([nextjs.org](https://nextjs.org/docs/app/guides/cdn-caching?utm_source=openai))

| 계층 | 저장 위치 | 주로 캐싱할 것 | 대표 위험 |
|---|---|---|---|
| 브라우저 HTTP 캐시 | 사용자 기기 | 해시가 붙은 JS·CSS·이미지, 폰트 | HTML을 길게 캐시해 배포 후에도 예전 화면이 보임 |
| Next.js Router Cache | 브라우저 메모리 | 방문·prefetch된 RSC route segment | 저장 후 client navigation에서 이전 payload가 재사용됨 |
| 서버 데이터 캐시 | Next.js 서버 또는 플랫폼 cache | CMS 글, 가격표, 공통 코드, 제품 카탈로그 | 태그 설계가 없으면 필요한 데이터만 무효화하기 어려움 |
| Full Route Cache·Prerender | Next.js 서버·배포 산출물 | 공개 랜딩, 블로그 상세, 문서 페이지 | 로그인·쿠키·권한 데이터가 섞이면 안 됨 |
| CDN 캐시 | 엣지 네트워크 | 공개 HTML, RSC variant, API 응답, 정적 자산 | RSC와 HTML을 같은 캐시 키로 저장하거나 revalidate와 따로 놀 수 있음 |
PM과 창업자가 기억할 기준은 간단합니다. ‘모든 사용자에게 같은 응답인가?’, ‘몇 분 정도 늦게 반영되어도 되는가?’, ‘수정 이벤트를 시스템이 알고 있는가?’, ‘권한·쿠키·테넌트에 따라 달라지는가?’ 네 가지 질문에 답하지 못하면 캐시 TTL부터 정하면 안 됩니다.
2. 라우트별 권장 정책: 공개 화면과 로그인 화면은 같은 규칙을 쓰지 않는다
Next.js 캐시 정책은 컴포넌트 단위로 세밀하게 조정할 수 있지만, 운영 문서는 라우트 단위로 먼저 작성하는 편이 좋습니다. 아래 표는 SaaS·업무자동화·관리자 화면을 함께 운영하는 팀에서 출발점으로 쓰기 좋은 기준입니다.

| 라우트 예시 | 캐싱 방향 | 권장 구현 | 무효화 방식 | 주의점 |
|---|---|---|---|---|
/, /features, /about | 공개 페이지. CDN 캐시 적극 사용 | 정적 prerender 또는 긴 cacheLife, CDN 전용 s-maxage | 배포 또는 콘텐츠 변경 시 태그 무효화와 CDN purge | HTML에 브라우저 max-age를 길게 주지 말 것 |
/pricing, /notice | 공개지만 즉시성 요구가 큼 | cacheTag('pricing'), 짧은 TTL 또는 CMS webhook | revalidateTag와 CDN 태그 purge 병행 | 가격·공지 변경권자가 누구인지 운영 절차로 남길 것 |
/blog/[slug], /docs/[slug] | ISR·CDN에 적합 | 글 목록·상세를 각각 태그화 | 발행·수정·비공개 전환 시 관련 tag 재검증 | 목록 tag와 상세 tag를 분리해야 과도한 purge를 줄임 |
/app/dashboard | 공유 CDN 캐시 금지에 가깝다 | HTML·RSC는 동적 렌더링, 공통 코드만 서버 캐시 | 저장 후 updateTag, router.refresh, 경로 재검증 | tenantId·role·plan에 따라 응답이 달라지면 public cache 금지 |
/admin/* | 신선도와 권한이 우선 | no-store 또는 private, no-cache | mutation 직후 즉시 만료, 감사 로그 기록 | 관리자가 본 화면과 고객이 본 공개 화면의 캐시를 따로 검증 |
/api/public/catalog | 공개 API라면 CDN 가능 | GET·HEAD, set-cookie 없음, Authorization 없음 | 상품·카테고리 tag purge | 나중에 개인화가 들어가면 캐시 정책을 다시 작성 |
/api/me, /api/admin/* | 공유 캐시 금지 | private, no-store, 권한 체크 | 요청마다 원천 데이터 확인 또는 private 서버 캐시 | 응답에 사용자 정보가 있으면 CDN 캐시 대상이 아님 |
Vercel CDN은 함수 응답을 캐시하려면 s-maxage 등 캐시 지시어가 필요하고, Authorization 헤더가 있는 요청, set-cookie가 있는 응답, private·no-cache·no-store 응답은 CDN 캐시 조건에서 제외됩니다. 이는 SaaS 화면에서 ‘혹시 빨라질까’라는 이유로 public 캐시를 걸면 안 되는 운영상 근거입니다. ([vercel.com](https://vercel.com/docs/caching/cdn-cache?utm_source=openai))
3. 서버 캐시: Cache Components 모델과 이전 fetch 모델을 구분한다
Next.js 프로젝트마다 캐시 모델이 다를 수 있습니다. Cache Components를 켠 프로젝트는 'use cache', cacheLife, cacheTag, revalidateTag, updateTag 중심으로 설계합니다. 공식 문서 기준으로 use cache의 기본 프로필은 client-side stale 5분, server-side revalidate 15분, expire는 시간상 만료 없음으로 설명되어 있으나, 실제 운영에서는 라우트별로 명시하는 편이 낫습니다. ([nextjs.org](https://nextjs.org/docs/app/api-reference/directives/use-cache?utm_source=openai))
예를 들어 가격표는 모든 사용자에게 같지만 즉시 수정 가능성이 있는 데이터입니다. 이 경우 ‘짧은 TTL로 계속 새로고침’보다 ‘충분히 캐시하되 수정 이벤트에서 정확히 무효화’가 더 안정적입니다. 개념상 코드는 다음처럼 읽히면 됩니다. getPricing() 안에서 'use cache'를 선언하고, cacheTag('pricing')과 cacheLife('hours')를 붙인 뒤, 관리자 저장 액션에서 revalidateTag('pricing', 'max') 또는 즉시성이 필요하면 updateTag('pricing')를 호출합니다.
이전 모델이나 혼합 프로젝트에서는 fetch('/api/pricing', { next: { tags: ['pricing'], revalidate: 3600 } }), cache: 'force-cache', cache: 'no-store', next.revalidate를 사용합니다. Next.js의 fetch 확장은 서버 사이드 요청이 프레임워크의 Data Cache와 어떻게 상호작용할지 정하는 기능이며, 같은 URL이라도 revalidate 값이 충돌하면 더 낮은 값이 적용될 수 있습니다. ([nextjs.org](https://nextjs.org/docs/app/api-reference/functions/fetch?utm_source=openai))
태그와 경로 재검증을 이렇게 나눈다
| 기능 | 적합한 상황 | 운영 판단 |
|---|---|---|
revalidateTag | 블로그, 가격표, 상품 목록처럼 약간의 지연 허용 | stale-while-revalidate 방식이므로 다음 요청에서 stale이 한 번 보일 수 있음을 공지·운영팀이 알아야 함 |
updateTag | 사용자가 저장 직후 자신이 바꾼 값을 바로 봐야 하는 경우 | Server Action 중심. 관리자 저장, 프로필 수정, 설정 변경에 적합 |
revalidatePath | 어떤 tag가 연결됐는지 모를 때 특정 경로를 넓게 갱신 | 편하지만 과도하게 무효화될 수 있어, 장기적으로는 tag 기반으로 옮기는 편이 좋음 |
router.refresh | 현재 사용자의 Router Cache를 비우고 서버에서 다시 가져와야 할 때 | 브라우저 메모리의 RSC payload 문제를 함께 해결할 때 사용 |
더 깊은 ISR 구조와 webhook 설계는 기존 글인 Next.js ISR·온디맨드 재검증 전략을 함께 보면 좋습니다. 이 글에서는 ISR 자체보다 CDN과 브라우저 캐시까지 포함한 운영 분리를 중심으로 봅니다.
4. CDN 캐시: revalidate가 CDN을 자동으로 지운다고 생각하면 안 된다
가장 흔한 오해는 revalidateTag 또는 revalidatePath를 호출하면 앞단 CDN 캐시까지 즉시 사라진다고 보는 것입니다. Next.js 공식 CDN 문서는 CDN-level caching만으로는 on-demand revalidation을 지원하지 않으며, revalidate 호출은 Next.js 서버 캐시를 무효화하지만 CDN은 s-maxage가 끝날 때까지 기존 응답을 계속 줄 수 있다고 설명합니다. 별도 CDN을 두거나 직접 Cache-Control을 설정했다면 서버 캐시 무효화와 CDN purge를 한 트랜잭션처럼 설계해야 합니다. ([nextjs.org](https://nextjs.org/docs/app/guides/cdn-caching?utm_source=openai))
Vercel에서는 Vercel-CDN-Cache-Control, CDN-Cache-Control, Cache-Control의 우선순위가 다릅니다. Vercel 전용 TTL, 다른 CDN용 TTL, 브라우저용 TTL을 분리할 수 있다는 뜻입니다. 또한 Vercel은 stale-while-revalidate 같은 CDN 지시어를 처리한 뒤 브라우저 응답에서는 다르게 노출할 수 있으므로, 브라우저 개발자도구에 보이는 헤더만 보고 전체 캐시 정책을 판단하면 안 됩니다. ([vercel.com](https://vercel.com/docs/caching/cache-control-headers?utm_source=openai))
RSC 응답은 CDN 캐시 키 검증이 필수다
App Router는 같은 URL이라도 HTML document 요청과 RSC payload 요청이 다릅니다. Next.js는 Vary와 _rsc 쿼리 파라미터를 통해 응답 변형을 구분하도록 설계되어 있습니다. CDN이 쿼리를 제거하거나 rsc 헤더를 전달하지 않거나 HTML과 RSC를 같은 cache key로 저장하면, 브라우저가 HTML을 기대하는 상황에서 RSC payload가 내려와 화면이 깨질 수 있습니다. Cloudflare 문서도 Next.js RSC 헤더를 별도 cache key나 변환 규칙으로 구분하는 예시를 별도로 제시합니다. ([nextjs.org](https://nextjs.org/docs/app/guides/cdn-caching?utm_source=openai))
- CDN이
_rsc쿼리를 cache key에 포함하는지 확인합니다. rsc헤더가 origin까지 전달되는지 확인합니다.next-router-prefetch가 있는 요청에서 prefetch variant가 HTML과 섞이지 않는지 확인합니다.- Cloudflare, Fastly, CloudFront처럼 범용 CDN을 쓴다면 기본 캐시 규칙이 Next.js App Router를 이해한다고 가정하지 않습니다.
- 장애 대응용 전체 purge는 마지막 수단으로 두고, 가능하면 tag 또는 URL 단위 purge를 사용합니다.
Edge에서 인증, 리다이렉트, A/B 테스트까지 함께 다룬다면 캐시 키가 더 복잡해집니다. 관련 경계는 Next.js Edge Functions 운영 가이드에서 인증·프록시·런타임 선택 기준과 함께 검토할 수 있습니다.
5. 브라우저 캐시: 정적 파일은 길게, HTML과 로그인 응답은 짧게
브라우저 캐시는 사용자 기기에 남습니다. 따라서 해시가 붙은 JS·CSS·이미지처럼 URL이 바뀌는 자산에는 긴 캐시가 적합하지만, 같은 URL로 최신 내용을 보여줘야 하는 HTML에는 긴 max-age를 주면 운영 사고가 됩니다. Next.js는 해시가 포함된 immutable asset에 public, max-age=31536000, immutable을 설정할 수 있으며, 이런 파일은 파일명이 바뀌므로 길게 저장해도 안전한 편입니다. 반대로 메인 HTML은 URL이 그대로라 cache busting이 어렵기 때문에 no-cache나 CDN 전용 TTL을 분리하는 접근이 안전합니다. ([nextjs.org](https://nextjs.org/docs/pages/api-reference/config/next-config-js/headers?utm_source=openai))
no-cache와 no-store도 구분해야 합니다. no-cache는 저장 자체를 금지한다기보다 재사용 전에 서버 검증을 요구하는 의미이고, no-store는 응답 저장을 하지 말라는 지시입니다. 개인화된 로그인 응답은 shared cache에 저장되면 안 되므로 private를 함께 고려해야 합니다. MDN은 개인화 응답에 private가 필요하다는 점과, HTML 같은 main resource에는 무조건 no-store만 쓰기보다 목적에 따라 no-cache를 쓰는 패턴을 설명합니다. ([developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching?utm_source=openai))
| 대상 | 브라우저 캐시 방향 | CDN 캐시 방향 | 설명 |
|---|---|---|---|
| 해시 파일 JS·CSS | 길게. immutable 가능 | 길게 | 파일명이 바뀌므로 새 배포와 충돌 가능성이 낮음 |
| 공개 HTML | 짧게 또는 재검증 | s-maxage로 CDN만 캐시 | 사용자는 최신 문서를 봐야 하므로 브라우저 장기 캐시는 피함 |
| 로그인 HTML·RSC | private, no-cache 또는 no-store | 공유 캐시 금지 | 사용자별 권한과 데이터가 들어갈 수 있음 |
| 공개 이미지·폰트 | 길게 가능 | 길게 가능 | 파일명·변환 URL 변경 정책이 있어야 함 |
| 관리자 API 응답 | 저장 금지 또는 private | 공유 캐시 금지 | 권한 변경, 감사 로그, 개인정보 이슈를 우선 |
6. SaaS·관리자 화면에서 특히 조심할 것
SaaS 대시보드는 ‘모든 사용자에게 같은 화면’처럼 보여도 실제로는 플랜, 역할, 조직, 권한, 설정값에 따라 응답이 달라지는 경우가 많습니다. 이때 캐시 키에 tenantId나 userId가 빠진 상태로 서버 캐시를 쓰면 고객사 데이터가 섞일 수 있고, CDN public 캐시는 더 위험합니다. 인증·권한 설계와 캐시 설계는 분리할 수 없으므로, 로그인 화면을 운영한다면 Next.js App Router 인증 권한 설계 가이드의 라우트 보호 기준과 함께 검토해야 합니다.
- 사용자별 데이터: CDN public cache 금지. 필요 시 private 서버 캐시 또는 요청마다 조회.
- 테넌트 공통 설정: tenantId가 캐시 키와 tag에 반드시 들어가야 함. 예:
tenant:123:settings. - 권한에 따라 달라지는 메뉴: role 또는 permission version이 바뀌면 즉시 무효화.
- 관리자 저장 후 공개 페이지 반영: 관리자 화면 캐시와 공개 랜딩 캐시를 별도로 무효화.
- 클라이언트 prefetch: 관리자에서 초 단위 신선도가 중요하면 일부 링크는 prefetch를 끄거나 저장 후 refresh를 명시.
AgentMit이 BizMit 같은 SaaS·업무자동화·관리자 대시보드를 설계할 때도 캐시 설정을 마지막 성능 튜닝으로 보지 않습니다. 라우트 그룹을 (public), (app), (admin)처럼 나누고, 각 그룹의 데이터 소유자·권한·변경 이벤트·무효화 담당자를 먼저 정한 뒤 구현합니다. 이 방식은 정부지원사업 MVP처럼 초기 배포 후 빠르게 데모와 운영을 오가야 하는 프로젝트에서도 장애 대응 시간을 줄여 줍니다.
7. 운영 무효화 플레이북: TTL보다 이벤트를 먼저 설계한다
TTL은 ‘언젠가 새로워지는’ 장치일 뿐입니다. 가격 수정, 공지 발행, 블로그 비공개, 고객사 설정 변경처럼 서비스가 이미 알고 있는 이벤트가 있다면, TTL을 짧게 줄이는 것보다 이벤트 기반 무효화가 낫습니다.

- 라우트 인벤토리 작성: 공개, 로그인, 관리자, API, 이미지·파일로 나눕니다.
- 데이터 신선도 등급 지정: 즉시, 1분 이내, 5분 이내, 하루 이내처럼 운영자가 이해할 수 있는 단위로 정합니다.
- 캐시 tag 네이밍 확정:
page:home,post:slug,pricing,tenant:123:settings처럼 충돌 없는 규칙을 둡니다. - mutation과 무효화를 같은 업무 흐름에 배치: 저장 API, Server Action, CMS webhook, 관리자 버튼 중 어디서
revalidateTag와 CDN purge를 호출할지 정합니다. - 검증 명령 표준화: 배포 전후
curl -I로Cache-Control,Vary,x-vercel-cache,_rsc포함 여부를 확인합니다. - 장애 시 fallback 결정: 원본 장애 때 stale 응답을 허용할지, 민감 화면은 에러를 내더라도 stale을 금지할지 정합니다.
| 변경 이벤트 | 서버 캐시 | CDN 캐시 | 브라우저·Router Cache |
|---|---|---|---|
| 블로그 글 발행 | revalidateTag('posts'), 상세 tag 갱신 | 목록·상세 URL 또는 tag purge | 일반 사용자는 다음 이동 또는 새로고침에서 반영 |
| 가격표 수정 | updateTag('pricing') 또는 revalidateTag | pricing 관련 cache tag purge | 가격 페이지 강제 새로고침 안내가 필요할 수 있음 |
| 고객사 설정 저장 | tenant:id:settings tag 만료 | 공유 CDN 캐시 없음 | 저장 후 router.refresh |
| 관리자 공지 비공개 | 공지 목록·상세 tag 즉시 만료 | 해당 URL purge. 전체 purge는 지양 | 편집자 화면은 즉시 refresh |
| 권한 변경 | 사용자·테넌트 권한 cache 만료 | 공유 CDN 캐시 없음 | 세션·쿠키 갱신과 Router Cache 무효화 |
8. 자가 호스팅과 다중 인스턴스라면 캐시 저장소도 요구사항이다
Vercel 같은 통합 플랫폼이 아니라 Docker, Kubernetes, 자체 VM, 별도 CDN 조합으로 Next.js를 운영한다면 캐시 저장소와 태그 동기화가 별도 요구사항이 됩니다. Next.js self-hosting 문서는 기본 캐시가 서버 인스턴스의 로컬 파일시스템이나 메모리에 있을 수 있고, 여러 인스턴스를 운영하면 Redis·S3 같은 공유 저장소나 custom cache handler를 검토해야 한다고 설명합니다. 특히 한 인스턴스에서 revalidateTag를 호출해도 다른 인스턴스가 계속 stale을 줄 수 있어 tag coordination이 필요합니다. ([nextjs.org](https://nextjs.org/docs/app/guides/self-hosting?utm_source=openai))
자가 호스팅 팀의 체크포인트는 세 가지입니다. 첫째, 여러 컨테이너가 같은 build id와 Server Actions encryption key를 쓰는가. 둘째, Data Cache와 prerender cache가 어느 저장소에 있는가. 셋째, CDN이 Next.js의 Cache-Control, Vary, _rsc를 존중하는가. 이 세 가지가 문서화되어 있지 않으면 트래픽 증가 시 캐시 hit ratio보다 데이터 일관성 문제가 먼저 드러납니다.
9. 배포 전 체크리스트
- 공개 라우트와 로그인 라우트가 route group 또는 middleware 정책상 분리되어 있는가?
- 모든 public CDN 캐시 대상 응답에 사용자별 데이터, 쿠키, 권한별 문구가 없는가?
- HTML은 브라우저 장기 캐시가 아니라 CDN 캐시 중심으로 설계했는가?
- RSC 요청의
_rsc쿼리와rsc헤더가 CDN cache key에 반영되는가? revalidateTag,updateTag,revalidatePath중 어떤 함수를 어느 이벤트에서 호출하는지 정해져 있는가?- CDN purge가 필요한 라우트는 서버 revalidate와 함께 실행되는가?
- 관리자 저장 후 관리자 화면, 공개 화면, API 응답을 각각 확인하는 QA 시나리오가 있는가?
- 장애 상황에서 stale 응답을 허용할 라우트와 절대 허용하지 않을 라우트가 구분되어 있는가?
- 브라우저 개발자도구뿐 아니라
curl -I와 CDN 로그로 실제 edge cache 상태를 확인하는가? - 자가 호스팅이라면 다중 인스턴스 캐시 동기화와 tag refresh 절차가 구현되어 있는가?
10. 의사결정 요약
랜딩·블로그·문서형 페이지는 CDN과 ISR의 이점을 적극적으로 가져가야 합니다. 다만 가격표, 공지, 프로모션처럼 비즈니스 변경 이벤트가 있는 데이터는 TTL만으로 운영하지 말고 tag와 purge를 설계해야 합니다. SaaS 대시보드와 관리자 화면은 속도보다 격리가 먼저입니다. 공유 캐시를 끄고, 공통 데이터만 제한적으로 캐시하며, 저장 직후 사용자에게 최신 값을 보장하는 흐름을 만들어야 합니다.
캐시는 개발자가 성능을 위해 나중에 붙이는 옵션이 아니라 PM, 마케터, 운영자가 함께 합의해야 하는 데이터 신선도 정책입니다. AgentMit은 AI 서비스 개발, SaaS, 업무자동화, 관리자 대시보드, 정부지원 MVP를 구현할 때 이 정책을 요구사항 정의 단계에서 함께 정리합니다. 이미 운영 중인 Next.js 프로젝트에서 ‘어떤 화면은 빨라졌는데 어떤 화면은 오래된다’는 문제가 반복된다면, 코드 수정 전에 라우트별 캐시 표와 무효화 플레이북부터 만드는 것이 우선입니다.
FAQ
Q1. Next.js App Router에서 랜딩 페이지는 전부 ISR로 만들면 되나요?
아닙니다. 자주 바뀌지 않는 회사소개·문서·블로그는 ISR과 CDN 캐시가 잘 맞지만, 가격표·공지·프로모션처럼 즉시 반영 요구가 있는 영역은 cacheTag와 revalidateTag, 또는 CDN purge 절차를 함께 설계해야 합니다. HTML을 브라우저에 길게 저장하는 설정은 피하는 편이 안전합니다.
Q2. revalidatePath나 revalidateTag를 호출하면 CDN 캐시도 바로 지워지나요?
일반적으로 Next.js 서버 캐시를 무효화하는 것과 CDN에 이미 저장된 HTTP 응답을 지우는 것은 별개입니다. 별도 CDN이나 직접 설정한 s-maxage 응답을 쓰면 revalidate 호출과 CDN purge 또는 태그 무효화를 같이 실행해야 합니다.
Q3. SaaS 대시보드에서 사용자별 데이터를 캐싱해도 되나요?
공유 CDN 캐시에는 올리면 안 됩니다. 사용자별·테넌트별 데이터는 no-store 또는 private, no-cache를 기본으로 두고, 정말 캐시가 필요하면 캐시 키에 tenantId·userId·권한 버전을 명확히 포함한 서버 측 private cache나 데이터 캐시로 제한해야 합니다.
Q4. 브라우저 캐시 때문에 고객이 오래된 화면을 보는 문제는 어떻게 막나요?
해시가 붙은 정적 JS·CSS·이미지는 길게 캐시하고, HTML·RSC·로그인 화면은 길게 캐시하지 않는 것이 기본입니다. 앱 내부 이동에서 Router Cache가 남을 수 있으므로 저장 후 router.refresh나 Server Action 기반 재검증도 함께 봐야 합니다.
Q5. Vercel이 아닌 Cloudflare나 AWS CloudFront 앞단에 Next.js를 둘 때 가장 위험한 설정은 무엇인가요?
HTML과 RSC payload를 같은 캐시 키로 취급하거나, _rsc 쿼리와 RSC 관련 헤더를 제거하는 설정입니다. CDN이 Vary와 쿼리 기반 cache key를 어떻게 처리하는지 먼저 검증해야 합니다.
참고한 공식 문서와 검토 기준
- Next.js CDN Caching 문서: App Router의
Cache-Control, RSC variant,_rsccache key, CDN purge 필요성을 확인했습니다. ([nextjs.org](https://nextjs.org/docs/app/guides/cdn-caching?utm_source=openai)) - Next.js Revalidating·use cache 문서:
cacheLife,cacheTag,revalidateTag,updateTag기준을 확인했습니다. ([nextjs.org](https://nextjs.org/docs/app/getting-started/revalidating?utm_source=openai)) - Vercel CDN·Cache-Control 문서: CDN 전용 헤더 우선순위와 캐시 가능 조건을 확인했습니다. ([vercel.com](https://vercel.com/docs/caching/cache-control-headers?utm_source=openai))
- MDN HTTP Caching 문서:
private,no-cache,no-store, immutable 자산 캐시 기준을 확인했습니다. ([developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching?utm_source=openai)) - Cloudflare Cache 문서: 범용 CDN에서 Next.js RSC 헤더를 cache key에 반영하는 방식을 확인했습니다. ([developers.cloudflare.com](https://developers.cloudflare.com/cache/advanced-configuration/serve-tailored-content/?utm_source=openai))

