Velog
Next.js의 전체 페이지 캐싱: 신선도를 잃지 않고 SSR 페이지를 캐시하는 방법
Next.js 15 App Router 에서 SSR 페이지를 캐시하는 4가지 전략(Cache-Control, Redis, Edge Middleware, ISR+Edge)과 디버깅·모범 사례 정리.
핵심 요약
전략 4가지:
| # | 도구 | 적합한 케이스 | 핵심 노브 |
|---|---|---|---|
| 1 | Cache-Control 헤더 (CDN) | 트래픽 많고 변동 적은 페이지 | s-maxage, stale-while-revalidate |
| 2 | Redis 수동 캐시 | self-hosted, 정밀 무효화 필요 | TTL, 캐시 키 |
| 3 | Edge Middleware | 지역/AB 등 변형 캐시 | URL rewrite + 헤더 |
| 4 | ISR + Edge | 블로그/제품 상세 | export const revalidate |
디버깅: x-vercel-cache 의 HIT/MISS/STALE. 함정: 쿠키가 캐시 우회 트리거, force-dynamic + 헤더 누락 시 캐시 0%, 캐시 카디널리티 폭발. 모범: no-store 남용 금지, stale-while-revalidate 로 블로킹 방지.
"SSR 캐시" 는 모순처럼 들리지만, 본질은 "신선도(freshness)와 부하(load)의 트레이드오프를 페이지마다 다른 노브로 조절한다" 다. 노브: s-maxage, stale-while-revalidate, revalidate, Edge Middleware 의 cache key, Redis TTL.
트래픽이 늘면 "DB 쿼리 200ms × 1만 RPS" 같은 단순 SSR 이 즉시 무너진다. 면접에서 "부하가 10배 됐을 때 어떻게 살리겠나" 는 단골 질문이고, 본문의 4전략 + 디버깅 헤더(x-vercel-cache) 까지 정리해 두면 구체 액션 플랜 으로 답할 수 있다.
학습 포인트
면접 답변으로 연결할 학습 포인트입니다.
`s-maxage` + `stale-while-revalidate` 의 의미를 정확히
Cache-Control: public, s-maxage=60, stale-while-revalidate=120
public: 공유 캐시(CDN/프록시)에 저장 가능s-maxage=60: CDN 은 60초간 fresh 로 간주stale-while-revalidate=120: 그 이후 120초까지는 stale 응답을 즉시 반환하면서 백그라운드에서 갱신
즉 사용자는 절대 재생성을 기다리지 않는다.
max-age 만 쓰고 s-maxage 누락. CDN 이 캐시 안 한다.
쿠키 한 줄이 전체 페이지 캐시를 죽인다
Vercel 기준 next-auth.session-token 같은 인증 쿠키가 요청에 포함되면 CDN 이 전체 캐시 우회. 공개 마케팅 페이지에 불필요한 쿠키가 묻어 있으면 HIT 률이 0% 가 된다.
curl -I https://example.com/
x-vercel-cache: MISS # 의심: 쿠키?
분석 스크립트가 심은 쿠키가 전 페이지에 퍼지는 것. 공개 페이지에서는 도메인/경로 단위로 쿠키 잘라내기.
변형(variant) 캐시는 "분리" 하되 폭발시키지 마라
Edge Middleware 로 geo 별 URL rewrite (/landing → /us/landing) 하면 country 별로 cache key 가 갈리지만, country × language × device × A/B 처럼 곱하면 카디널리티가 폭발한다. 규칙: "UX 가 정말 다른 변형" 만 분리, 나머지는 client-side personalisation.
모든 사용자 속성을 cache key 에 넣어 사실상 캐시 무효화. 캐시 hit 률을 항상 모니터링.
읽는 순서
- 1이론
Vercel Cache-Control 문서 에서
s-maxage/stale-while-revalidate/Vary의미를 표로 정리. - 2구현
Next.js 15 App Router 페이지에
Cache-Control헤더를 직접 설정 후curl -I로x-vercel-cache변화를 관찰. - 3실무
현재 프로젝트의 트래픽 상위 5개 SSR 경로를 "캐시 가능 / 사용자 의존 / 변형 필요" 3축으로 분류하고, 본문 4전략 중 무엇을 적용할지 1쪽 분량 의사결정 문서 작성.
- 4설명
"부하가 10배 됐을 때 SSR 페이지 어떻게 살릴까" 5분 발표. 4전략 +
x-vercel-cache디버깅 + 쿠키 함정 사례 1개.
면접 연결 질문
[좋은 답변] ① 요청에 인증 쿠키 / 사용자 식별 헤더가 묻어 캐시 우회, ② 응답이 Set-Cookie 를 반환해 CDN 이 캐시 거부, ③ Vercel 의 캐시 정책상 force-dynamic + 동적 데이터 fetch 조합 시 자동 우회. x-vercel-cache: MISS + Vary 헤더로 진단.
[좋은 답변] ① on-demand 무효화가 잦은 상품 가격 페이지 : 가격 변경 시 단일 키만 invalidate. ② self-hosted Node/Express, CDN 없음. ③ partial cache 가 필요한 대시보드 — page-level 이 아니라 query-level 캐시.
[좋은 답변] ISR 은 빌드/요청 시점 정적 생성 + 일정 주기로 백그라운드 재생성, SWR 헤더는 CDN 단의 응답 재사용 정책. 둘은 결합 가능: ISR 결과물을 SWR 로 더 오래 재사용.
자기 점검
"오래된 콘텐츠라 나쁘다" 가 아니라 즉시 응답 + 백그라운드 갱신 으로 사용자 경험은 빠르다.
"별 문제 없다" — 사실상 모든 요청이 origin 까지 간다.