Cache-ControlCache-Control은 요청·응답 양쪽에서 캐싱 동작을 지시하는 지시자(directive) 목록을 담는 헤더입니다. 응답에 붙으면 브라우저·CDN·프록시가 이 응답을 얼마나, 어떻게 저장·재사용할지 결정합니다. HTTP 캐싱 정책의 사실상 표준입니다.
핵심은 신선도(freshness)입니다. `max-age=3600`은 응답을 3600초 동안 신선한 것으로 보고 네트워크 없이 재사용하게 합니다. 시간이 지나 stale해지면 캐시는 `ETag`/`If-None-Match` 또는 `Last-Modified`/`If-Modified-Since`로 서버에 재검증하고, 서버가 304 Not Modified를 주면 본문 전송 없이 캐시를 갱신합니다.
저장 범위는 `public`(공유 캐시 허용)·`private`(개인 캐시 전용)·`no-store`(저장 금지)로 나뉩니다. `no-cache`는 이름과 달리 '저장 금지'가 아니라 '재사용 전 반드시 재검증'을 뜻하니 혼동하지 마세요. `s-maxage`는 CDN 같은 공유 캐시에만 적용되는 max-age이고, `immutable`은 버전이 파일명에 박힌 정적 자산에서 재검증을 아예 생략시켜 성능을 높입니다.
구형 `Expires`(절대 시각) 헤더보다 상대 시간을 쓰는 Cache-Control이 우선하며 더 정밀합니다. 응답이 요청 헤더(Accept-Encoding, 언어 등)에 따라 달라지면 `Vary`를 함께 지정해야 캐시가 표현을 혼동하지 않습니다.
Cache-Control: <directive>[, <directive>]*e.g. Cache-Control: public, max-age=3600, stale-while-revalidate=60
max-age=<seconds> | 응답을 신선하게 볼 최대 시간(초). 이 시간이 지나면 stale로 간주. |
no-cache | 캐시는 하되, 재사용 전 반드시 서버에 재검증(조건부 요청)해야 함. |
no-store | 어떤 캐시에도 저장 금지. 민감한 응답에 사용. |
public | 공유 캐시(CDN·프록시)에도 저장 가능. |
private | 브라우저 등 개인 캐시에만 저장, 공유 캐시는 금지. |
must-revalidate | stale해지면 재검증 없이 절대 재사용 금지. |
immutable | 유효기간 내 내용이 바뀌지 않으니 재검증 불필요(버전드 자산). |
s-maxage=<seconds> | 공유 캐시 전용 max-age. max-age를 덮어씀. |
stale-while-revalidate=<s> | 재검증하는 동안 잠시 stale 응답을 제공 허용. |