VaryVary는 이 응답이 어떤 요청 헤더 값에 따라 달라지는지를 캐시에 알려주는 헤더입니다. 캐시는 동일 URL이라도 Vary에 나열된 헤더 값이 다르면 별개의 캐시 항목으로 취급해, 엉뚱한 사용자에게 잘못된 표현을 주는 일을 막습니다.
콘텐츠 협상(압축·언어·미디어 타입)이나 CORS를 쓰는 응답에서 캐시 정확성을 지키는 핵심 장치입니다.
예를 들어 서버가 Accept-Encoding에 따라 gzip 버전과 비압축 버전을 다르게 낸다면 Vary: Accept-Encoding이 없을 때 캐시가 gzip 응답을 gzip을 지원하지 않는 클라이언트에게 줘 깨진 콘텐츠를 보일 수 있습니다. 다국어 사이트에서 Accept-Language로 언어를 결정한다면 Vary: Accept-Language가 필요합니다.
CORS에서 서버가 Origin을 반사(reflect)해 Access-Control-Allow-Origin을 동적으로 낸다면 반드시 Vary: Origin을 함께 내야 합니다. 그렇지 않으면 공유 캐시가 A 오리진용 응답을 B 오리진에 재사용해 CORS가 깨지거나 캐시 오염(cache poisoning)이 생깁니다.
Vary: *는 응답이 URL 외의 명시되지 않은 요청 요인에 따라 달라져 사실상 캐시할 수 없음을 뜻합니다. 또한 Vary에 나열된 헤더 조합의 카디널리티가 높을수록(예: User-Agent) 캐시 파편화가 심해져 히트율이 급락하니 꼭 필요한 헤더만 나열해야 합니다.
Vary: <header>[, <header>]* | *e.g. Vary: Accept-Encoding, Accept-Language
Accept-Encoding | 압축 협상(gzip/br)에 따라 응답이 달라짐 — 압축 응답 캐싱의 필수 값. |
Accept-Language | 언어 협상에 따라 응답이 달라짐(다국어 사이트). |
Accept | 요청한 미디어 타입에 따라 표현이 달라짐(콘텐츠 협상). |
Origin | CORS 응답을 요청 오리진별로 캐시 분리 — 교차 오리진 캐시 오염 방지. |
Cookie | 쿠키에 따라 응답이 달라짐(사용자별) — 공유 캐시 캐싱을 사실상 무력화. |
* | 모든 요청 요인에 따라 달라짐 — 사실상 캐시 재사용 불가. |