같은 URL인데 응답이 다르다면: Vary 헤더로 캐시 구분 읽기

🤖 AI Summary
같은 URL이라도 요청 언어에 따라 다른 응답이 필요할 수 있습니다. Vary는 응답을 구분할 요청 헤더를 알리는 응답 헤더입니다. 저장할 때의 요청값과 다음 요청값을 비교하는 조건이죠. 헤더가 없는 경우도 구분하고, 조건이 맞더라도 다른 캐시 재사용 요건을 확인해야 합니다. 실제 CDN의 캐시 정책과 언어별 응답을 함께 대조하세요.
블로그 목차
한국어로 열었던 안내 페이지가 다른 환경에서는 영어로 보입니다. 주소는 같은데 내용이 다르다면, 캐시가 오래됐는지 묻기 전에 어떤 요청 조건으로 응답을 골랐는지 살펴봐야 합니다.
이번 글은 언어별 안내 페이지를 예로 들어 Vary의 비교 조건을 읽습니다. 예시의 헤더와 표는 개념 설명용이며, 특정 CDN이나 운영 서버에서 측정한 결과가 아닙니다. Vary와 실제 CDN 설정이 같은 역할이라고 가정하지 않고 나눠 확인하겠습니다.
같은 URL인데 다른 응답을 캐시할 수 있나요?
같은 URL에도 언어처럼 요청 조건에 따른 여러 표현이 있을 수 있어 캐시는 응답 구분 기준을 확인합니다.
예를 들어 서버가 같은 안내 페이지의 한국어판과 영어판을 제공한다고 가정해 보죠. 주소만 보고 앞서 받은 응답을 모두에게 재사용하면, 다음 요청에 필요한 표현과 맞는지 놓칠 수 있습니다. 여기서 표현은 같은 자원에 대해 선택된 콘텐츠를 뜻하죠.
RFC 9110의 Vary 정의는 메서드와 대상 URI 외에 어떤 요청 요소가 응답 선택에 영향을 주었는지 알린다고 설명합니다. 캐시를 구분하는 데 쓰는 식별 기준인 캐시 키를 이해할 때도 이 조건을 함께 읽어야 해요.
이 구분은 보관 시간과 다른 질문입니다. 저장·재사용을 통제하는 지시어와 TTL은 Cache-Control 완전 정복: max-age와 s-maxage로 TTL 설계하기에서 다룹니다. 이번에는 얼마나 오래됐는지보다 어느 요청에 맞는 응답인지에 집중하죠.

Vary는 어떤 요청 헤더를 비교하라고 알려주나요?
Vary에는 응답 선택에 영향을 준 요청 헤더의 이름을 적으며 실제 비교 대상은 각 요청의 헤더값입니다.
Vary: Accept-Language는 응답에 적는 값이죠. 한국어를 뜻하는 ko를 Vary에 직접 적는 것이 아니에요. 저장 응답을 만들었던 요청의 Accept-Language와 다음 요청의 같은 헤더를 비교하라는 뜻이죠.
RFC 9111의 캐시 비교 규칙에 따르면 지정된 요청 헤더 중 하나라도 맞지 않으면 저장 응답을 재검증 없이 사용할 수 없어요. 반대로 이 조건이 맞는다는 이유만으로 캐시 적중을 확정하지는 않죠. 저장 여부와 유효성 등 다른 요건도 남아 있죠.
비교가 언제나 원문 문자열의 단순 일치인 것은 아닙니다. 해당 헤더 문법과 의미에 맞는 공백 처리나 동등한 값의 정규화가 허용됩니다. 그렇다고 언어값이나 선호 순서를 임의로 지워 같은 요청으로 취급해도 된다는 뜻은 아니에요.
Vary: *도 별도로 읽어야 합니다. 이 값을 포함한 저장 응답은 비교에서 항상 불일치합니다. 모든 헤더를 알아서 키에 넣어 주는 옵션이나 어떤 요청에도 캐시 적중을 보장하는 표시는 아니에요.
언어가 다른 응답은 어떻게 구분해 읽나요?
언어별 응답은 요청의 Accept-Language와 응답 본문을 함께 기록하고 저장 당시 조건과 비교합니다.
여기서는 Vary가 Accept-Language 하나를 지정하고, 요청값이 ko 또는 en인 단순한 상황을 가정합니다. 아래 표의 일치는 해당 헤더의 비교 결과만 뜻하며, 응답을 반드시 저장하거나 즉시 재사용한다는 결과표는 아니에요.
저장 당시 요청값 | 다음 요청값 | Vary 조건 판단 |
|---|---|---|
ko | ko | 이 헤더 조건은 일치 |
ko | en | 불일치: 재검증 없는 재사용 금지 |
헤더 없음 | ko | 헤더 유무가 달라 불일치 |
헤더 없음 | 헤더 없음 | 이 헤더 조건은 일치 |
Accept-Language는 클라이언트의 언어 선호를 전달합니다. 실제로 어떤 언어를 선택해 제공할지는 서버의 콘텐츠와 선택 로직을 확인해야 하죠. Vary를 추가하는 것만으로 번역 기능이나 언어별 페이지가 생기지는 않아요.
헤더가 없는 요청에 돌아오는 기본 응답도 비교에 넣으세요. MDN의 Vary 안내는 같은 URL의 기본 응답과 304 응답에도 일관된 Vary 값을 사용하도록 설명하죠. 언어별 응답만 살피고 기본 응답의 표시를 빠뜨리지 않는 것이 중요해요.
확인할 때는 같은 URL과 메서드로 요청하고, 언어 헤더 외에 쿠키·인증·쿼리 등 다른 조건이 바뀌었는지도 기록합니다. 먼저 기대한 언어의 본문이 오는지 확인한 뒤 캐시 관측값을 읽는 순서가 좋습니다. 이는 비교를 위한 운영 제안입니다.
Vary를 늘리면 캐시 재사용에는 어떤 부담이 생기나요?
응답 구분에 쓰는 요청값의 종류가 늘어나면 캐시가 나뉠 수 있어 꼭 필요한 구분인지 먼저 검토합니다.
CloudFront의 요청 헤더 기반 캐싱 안내는 여러 값으로 응답을 나눌 때 오리진 요청이 늘 수 있다고 설명합니다. 값의 종류가 많은 Date나 User-Agent를 구분 기준으로 삼는 데에도 주의를 제시하죠. 실제 응답이 같다면 그 헤더로 나눌 필요가 있는지 살펴봐야 합니다.
다만 헤더 이름을 하나 늘렸다는 사실만으로 저장 객체가 정해진 배수로 늘거나 적중률이 일정하게 떨어진다고 계산할 수는 없습니다. 실제 요청값의 분포, 캐시 정책과 저장 상태를 관측해야 해요. 이 글은 특정 환경의 성능 개선 수치나 최적 헤더 개수를 제안하지 않죠.
재사용을 늘리려고 실제 응답 차이를 숨기는 것도 적절하지 않습니다. 언어 선택을 단순화하거나 입력값을 정리하려면, 다른 콘텐츠를 하나로 합치지 않는지 먼저 확인해야 하죠. 효율과 올바른 응답 구분을 함께 검토하죠.
압축 코딩 선택과 호환성은 정적은 Brotli, 동적은 zstd: 2026년 웹 압축을 나누는 기준으로 위임합니다. 여기서는 압축 알고리즘 비교 대신 구분 조건이 늘어날 때의 판단에 초점을 둡니다.
Vary와 CDN의 실제 캐시 설정은 어떻게 대조하나요?
응답의 Vary와 CDN의 캐시 키 정책을 따로 확인한 뒤 같은 요청 조건의 본문과 관측값을 대조합니다.
CloudFront의 캐시 정책 문서는 캐시 키에 포함할 헤더·쿠키·쿼리 문자열을 정책으로 지정한다고 설명합니다. 따라서 응답에 Vary가 보인다는 사실만으로 원하는 구분 정책이 배포됐다고 판단하지 마세요. 제품별 지원 방식과 현재 적용된 정책을 함께 읽어야 하죠.
확인 지점 | 남길 기록 |
|---|---|
응답 선택 | 언어 헤더 유무·값과 실제 본문 언어 |
응답 헤더 | 언어별 응답·기본 응답의 Vary와 저장·재사용 조건 |
CDN 정책 | 대상 경로에 적용된 캐시 키·요청 헤더 처리 설정 |
동작 비교 | 같은 조건과 다른 조건의 요청 결과·시각·관측 지점 |
이 표는 점검 기록의 제안이며 특정 설정의 성공 판정표가 아니죠. 한 번의 HIT·MISS 표시만으로 언어별 구분이 올바르다고 결론 내리면 안 돼요. 확인한 조건과 아직 확인하지 않은 조건을 나눠 남기는 편이 좋습니다.
사용자마다 다른 정보가 담긴 응답은 공유 캐시에 저장해도 되는지부터 별도로 검토해야 합니다. Vary는 접근 권한 검사나 개인정보 보호 정책의 대체 수단이 아니죠. 이번 예시는 공통 안내 페이지의 언어 선택에 한정해요.
Origin별 허용 응답과 브라우저의 읽기 제한은 API는 200인데 브라우저에서 막힌다: CORS·프리플라이트·CDN 캐시 진단에서 다룹니다. 언어별 캐시 선택과 CORS 권한 판단을 같은 문제로 처리하지 마세요.
이것만 기억하세요
같은 주소와 같은 응답 조건은 다릅니다. Vary가 지정한 요청값을 맞춰 보고, 조건 일치와 실제 캐시 재사용 결과를 구분하세요. 마지막 판단은 적용된 CDN 정책과 올바른 본문이 함께 확인됐는지에 둡니다.
자주 묻는 질문 (FAQ)
Q. Vary는 요청에 넣는 헤더인가요?
여기서 다루는 Vary는 응답 헤더죠. 응답을 선택할 때 영향을 준 요청 헤더의 이름을 알려주며, 그 이름에 해당하는 요청값을 비교하도록 합니다.
Q. Vary: Accept-Language만 넣으면 번역이 되나요?
아닙니다. 언어별 콘텐츠를 선택하고 제공하는 기능은 서버나 애플리케이션에서 구현해야 합니다. Vary는 그 선택 기준을 캐시 등에 알리는 역할이죠.
Q. 요청 헤더가 없는 경우도 비교해야 하나요?
네. Vary가 지정한 헤더가 한 요청에 없다면, 비교하는 다른 요청에도 그 헤더가 없어야 해당 조건이 맞습니다. 기본 응답을 조사할 때도 헤더 유무와 Vary를 기록합니다.
Q. Vary: *는 모든 요청을 같은 캐시로 처리하라는 뜻인가요?
아닙니다. 이 값을 포함한 저장 응답은 Vary 조건 비교에서 항상 불일치합니다. 이를 모든 요청 헤더를 자동으로 키에 넣는 설정이나 모든 요청에 대한 캐시 적중으로 해석하지 않습니다.
Q. Vary가 같으면 캐시 적중을 보장하나요?
보장하지 않습니다. 저장 허용 여부와 유효성 등 다른 조건도 필요하고, 실제 CDN의 정책과 관측 결과를 대조해야 합니다. Vary의 조건 일치만으로 적중이나 응답의 안전성을 확정하지 않죠.


