FEInterview Prep

Velog

Next.js의 전체 페이지 캐싱: 신선도를 잃지 않고 SSR 페이지를 캐시하는 방법

Next.js 15 App Router 에서 SSR 페이지를 캐시하는 4가지 전략(Cache-Control, Redis, Edge Middleware, ISR+Edge)과 디버깅·모범 사례 정리.

2025-09-08·12분 읽기
Next.js성능
원문 보기 ↗

핵심 요약

전략 4가지:

#도구적합한 케이스핵심 노브
1Cache-Control 헤더 (CDN)트래픽 많고 변동 적은 페이지s-maxage, stale-while-revalidate
2Redis 수동 캐시self-hosted, 정밀 무효화 필요TTL, 캐시 키
3Edge Middleware지역/AB 등 변형 캐시URL rewrite + 헤더
4ISR + Edge블로그/제품 상세export const revalidate

디버깅: x-vercel-cacheHIT/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 응답을 즉시 반환하면서 백그라운드에서 갱신

즉 사용자는 절대 재생성을 기다리지 않는다.

s-maxagestale-while-revalidateCDNCache-Control
자주 하는 오해

max-age 만 쓰고 s-maxage 누락. CDN 이 캐시 안 한다.

쿠키 한 줄이 전체 페이지 캐시를 죽인다

Vercel 기준 next-auth.session-token 같은 인증 쿠키가 요청에 포함되면 CDN 이 전체 캐시 우회. 공개 마케팅 페이지에 불필요한 쿠키가 묻어 있으면 HIT 률이 0% 가 된다.

curl -I https://example.com/
x-vercel-cache: MISS  # 의심: 쿠키?
cookiex-vercel-cacheMISSpersonalisation
자주 하는 오해

분석 스크립트가 심은 쿠키가 전 페이지에 퍼지는 것. 공개 페이지에서는 도메인/경로 단위로 쿠키 잘라내기.

변형(variant) 캐시는 "분리" 하되 폭발시키지 마라

Edge Middleware 로 geo 별 URL rewrite (/landing/us/landing) 하면 country 별로 cache key 가 갈리지만, country × language × device × A/B 처럼 곱하면 카디널리티가 폭발한다. 규칙: "UX 가 정말 다른 변형" 만 분리, 나머지는 client-side personalisation.

Edge Middlewarerewritecache cardinality
자주 하는 오해

모든 사용자 속성을 cache key 에 넣어 사실상 캐시 무효화. 캐시 hit 률을 항상 모니터링.

읽는 순서

  1. 1이론

    Vercel Cache-Control 문서 에서 s-maxage / stale-while-revalidate / Vary 의미를 표로 정리.

  2. 2구현

    Next.js 15 App Router 페이지에 Cache-Control 헤더를 직접 설정 후 curl -Ix-vercel-cache 변화를 관찰.

  3. 3실무

    현재 프로젝트의 트래픽 상위 5개 SSR 경로를 "캐시 가능 / 사용자 의존 / 변형 필요" 3축으로 분류하고, 본문 4전략 중 무엇을 적용할지 1쪽 분량 의사결정 문서 작성.

  4. 4설명

    "부하가 10배 됐을 때 SSR 페이지 어떻게 살릴까" 5분 발표. 4전략 + x-vercel-cache 디버깅 + 쿠키 함정 사례 1개.

면접 연결 질문

hard`force-dynamic` 페이지에 `Cache-Control: s-maxage=60` 을 줘도 캐시되지 않는다면 어떤 가능성을 의심해야 하나요?
힌트

[좋은 답변] ① 요청에 인증 쿠키 / 사용자 식별 헤더가 묻어 캐시 우회, ② 응답이 Set-Cookie 를 반환해 CDN 이 캐시 거부, ③ Vercel 의 캐시 정책상 force-dynamic + 동적 데이터 fetch 조합 시 자동 우회. x-vercel-cache: MISS + Vary 헤더로 진단.

medium`Cache-Control` 만으로 부족해 Redis 수동 캐시가 필요한 케이스를 예시로 들어 주세요.
힌트

[좋은 답변] ① on-demand 무효화가 잦은 상품 가격 페이지 : 가격 변경 시 단일 키만 invalidate. ② self-hosted Node/Express, CDN 없음. ③ partial cache 가 필요한 대시보드 — page-level 이 아니라 query-level 캐시.

mediumISR + Edge 와 `Cache-Control: stale-while-revalidate` 의 차이를 설명해 주세요.
힌트

[좋은 답변] ISR 은 빌드/요청 시점 정적 생성 + 일정 주기로 백그라운드 재생성, SWR 헤더는 CDN 단의 응답 재사용 정책. 둘은 결합 가능: ISR 결과물을 SWR 로 더 오래 재사용.

자기 점검

`x-vercel-cache: STALE` 응답이 사용자 입장에서 의미하는 바를 한 줄로.
stale-while-revalidatebackgroundfreshness
자주 하는 오해

"오래된 콘텐츠라 나쁘다" 가 아니라 즉시 응답 + 백그라운드 갱신 으로 사용자 경험은 빠르다.

공개 마케팅 페이지에 `next-auth.session-token` 쿠키가 묻은 채 배포됐을 때 캐시가 어떻게 되는지 설명하세요.
cache bypassMISSpersonalisation
자주 하는 오해

"별 문제 없다" — 사실상 모든 요청이 origin 까지 간다.