캐싱성능http
HTTP 캐시 헤더 실전 — ETag와 stale-while-revalidate
✨ AI 요약
- HTTP 캐시 헤더는 서버, CDN, 브라우저 캐시를 조율하는 중요한 요소다. - ETag를 활용하면 no-cache에서도 서버가 효율적으로 응답할 수 있다. - stale-while-revalidate는 낡은 데이터를 즉시 제공하며 갱신하는 방식이다.
조회 70
서버 캐시, CDN, 브라우저 캐시가 모두 HTTP 캐시 헤더 하나로 조율된다. 헤더 몇 줄이 Redis 도입보다 효과가 클 때가 많다.
Cache-Control 3대 패턴
# 1. 불변 자산 (해시 붙은 JS/CSS/이미지)
Cache-Control: public, max-age=31536000, immutable
# 2. 자주 바뀌는 API/페이지
Cache-Control: private, no-cache
# 3. 조금 낡아도 되는 것
Cache-Control: public, max-age=60, stale-while-revalidate=300
no-cache는 "캐시하지 마"가 아니라 "쓰기 전에 재검증해"라는 뜻이다. 진짜 저장 금지는 no-store다. 이 둘을 헷갈리면 디버깅이 산으로 간다.
ETag — 재검증을 싸게
no-cache여도 ETag가 있으면 서버가 304 Not Modified로 본문 없이 응답할 수 있다. 수백 KB짜리 JSON이 수십 바이트가 된다. 대부분의 프레임워크가 정적 파일에는 자동으로 붙여 주지만, API 응답에는 직접 챙겨야 한다.
stale-while-revalidate — 체감 지연 제거
max-age가 지나도 지정 시간 동안은 낡은 응답을 즉시 주고, 뒤에서 조용히 갱신한다. 유저는 항상 캐시 속도를 경험하고 데이터는 곧 최신이 된다. 피드, 랭킹, 통계처럼 "1분 낡아도 되는" 데이터에 최적이다. Vercel/CloudFront/Cloudflare 모두 지원한다.
실무 배치
- 해시 파일명 정적 자산: immutable 1년
- HTML/페이지: no-cache + ETag (또는 ISR)
- 목록/피드 API: s-maxage=60, stale-while-revalidate=300 (CDN만 캐시)
- 개인화 응답: private, no-cache
s-maxage는 CDN 전용 max-age다. 브라우저에는 신선하게, CDN에는 관대하게 — 이 분리가 실무의 핵심이다.