오답 보기는 여기서 꺼내 쓴다. 원장에 없는 오해를 즉석에서 지어내지 않는다.
각 항목은 M-<번호>로 참조한다. 새 항목을 추가할 때는 실제로 사람들이 그렇게 믿는 근거(현업 대화, 블로그 오류, 스택오버플로 오답 등)를 한 줄 적는다.
- 실제: 캐시는 하되, 재사용 전에 매번 오리진에 재검증하라는 뜻이다. 저장 자체를 막는 것은
no-store. - 왜 믿는가: 이름이 직관과 반대다. 영어 단어 그대로 읽으면 "캐시 금지"로 읽힌다.
- 오답 유형:
adjacent
- 실제:
s-maxage는 공유 캐시(CDN·프록시) 전용이며, 공유 캐시에서는max-age를 덮어쓴다. 브라우저는 무시한다. - 왜 믿는가: 브라우저 TTL과 엣지 TTL을 분리해야 한다는 필요 자체를 안 겪어봤으면 구분할 이유가 없다.
- 오답 유형:
one-step-short
- 실제:
Vary는 "이 헤더 값이 다르면 다른 응답"이라고 캐시에 알리는 힌트다. 캐시 키 자체는 CDN 설정이 정한다. 둘은 다른 층위다. - 왜 믿는가: 효과가 비슷해 보인다. 실제로 카디널리티를 늘린다는 점도 같다.
- 오답 유형:
adjacent
- 실제: weak(
W/)은 바이트 단위 동일성을 보장하지 않는다. 그래서 Range 요청 등 바이트 정합성이 필요한 곳에서는 쓸 수 없다. - 왜 믿는가:
W/접두사를 본 적은 있어도 쓰임을 구분해 본 적은 드물다. - 오답 유형:
one-step-short
- 실제: 304도 오리진(또는 상위 캐시)까지 왕복한다. 바이트는 아끼지만 RTT는 그대로다. 진짜 히트는 아예 나가지 않는 것이다.
- 왜 믿는가: "Not Modified"라는 이름이 성공적인 캐시처럼 들린다.
- 오답 유형:
one-step-short
- 실제: strong ETag 또는 HTTP 날짜만 허용한다. weak(
W/)는 바이트 동일성을 보장하지 않아 부분 응답의 일관성을 담보할 수 없고, weak를 보내면 서버는 안전한 쪽으로 돌아가 전체 응답을 준다. - 왜 믿는가: strong/weak를 '정밀도 차이' 정도로만 이해하면 쓰임새 제한까지는 읽히지 않는다(M-04와 한 쌍).
- 오답 유형:
adjacent
- 실제:
If-None-Match가 있으면If-Modified-Since는 무시된다. 둘을 함께 보내는 클라이언트에서 ETag가 진실의 원본이다. - 왜 믿는가: 두 헤더가 '보험 삼아' 같이 실리는 걸 자주 봐서 병렬 평가라고 생각한다.
- 오답 유형:
overgeneralized
- 실제: 오리진에서 태어난 이후의 전체 나이이고 계층을 지나며 누적된다. 하위 캐시는 받은
Age에 자기 계층에 머문 시간만큼만 더한다. 남은 신선도는 TTL −Age로 읽는다. 나이 판정은 절대 시계가 아니라 응답에 실린 시간 정보의 합산이라 서버 시계 어긋남에도 틀어지지 않는 구조다. - 왜 믿는가: 지금 시각에서
Date를 빼면 될 것 같은 직관이 앞서고, 홉마다 나이가 초기화된다고 상상하기 쉽다. - 오답 유형:
one-step-short
- 실제: 요청 방향 디렉티브다. 클라이언트가 자기가 지나가는 캐시에 내거는 조건이며,
min-fresh와 요청 방향max-age도 같은 부류다. - 왜 믿는가:
Cache-Control하면 응답 헤더만 떠올린다. 방향을 구분해 본 적이 없다. - 오답 유형:
inverted
- 실제:
*는 요청에 드러나지 않는 조건까지 응답이 달라진다는 선언이다. 어떤 요청과도 변형이 일치하지 않으므로 캐시는 재검증 없이는 재사용할 수 없다. 키가 늘어나는 게 아니라 재사용 자체가 막힌다. - 왜 믿는가: 와일드카드를 다른 헤더의 '전체 매칭' 관례로 읽는다.
- 오답 유형:
adjacent
- 실제: 적용 대상이 다르다.
proxy-revalidate는 공유 캐시에만 만료 후 재검증을 강제하고 브라우저의 stale 사용은 허용한다.must-revalidate는 모든 캐시에 걸린다. - 왜 믿는가: '프록시' 접두사를 s-maxage처럼 '공유 캐시 값' 정도로만 기억하고 강도 차이를 본 적이 없다.
- 오답 유형:
adjacent
- 실제: 동시 미스를 하나로 합쳐 첫 재검증이 돌아올 때까지 뒤의 요청을 기다리게 한다. 즉시 응답을 내주는 건 stale-while-revalidate의 동작이고, 만료 시각을 흩는 건 TTL 지터다. 세 처방은 바꾸는 대상이 다르다.
- 왜 믿는가: 스탬피드 완화책이 여럿이라 결과(오리진 스파이크 완화)만 보고 메커니즘을 섞는다.
- 오답 유형:
adjacent
- 실제: HTTP/1.0 잔재다. 현대 캐시는
Cache-Control을 본다. 요청 헤더로서의 의미만 남아 있다. - 왜 믿는가: 오래된 예제 코드와 블로그에 아직 살아 있다.
- 오답 유형:
outdated
- 실제: 반대다.
max-age가 있으면Expires는 무시된다. - 왜 믿는가:
Expires가 더 오래된 헤더라 "기본"처럼 느껴진다. - 오답 유형:
inverted
- 실제: 명시 헤더가 없어도 캐시는 휴리스틱 신선도를 적용해 캐시할 수 있다(
Last-Modified기반 등). 캐시를 막으려면 명시해야 한다. - 왜 믿는가: "설정하지 않았으니 동작하지 않는다"는 일반적 직관.
- 오답 유형:
overgeneralized
- 실제: "공유 캐시에 저장하지 말라"는 캐시 지시일 뿐, 암호화도 접근 제어도 아니다. 민감 데이터 보호 수단이 아니다.
- 왜 믿는가: 단어가 보안처럼 들린다.
- 오답 유형:
overgeneralized
- 실제: 어느 지점부터는 캐시 용량과 요청 분포(롱테일) 가 히트율을 제한한다. 축출되면 TTL이 남아 있어도 미스다.
- 왜 믿는가: TTL과 히트율의 관계를 단조 증가로 상상하기 쉽다.
- 오답 유형:
overgeneralized
- 실제: RFC가 아닌 확장(I-D 단계)이며 브라우저 지원에 편차가 있다. 효과도 'fresh 동안 리로드 시 재검증 생략'이라는 한정된 것이다.
- 왜 믿는가: 주요 브라우저가 일부 지원하다 보니 표준처럼 소개된 글을 많이 본다.
- 오답 유형:
overgeneralized
- 실제: 기본 저장 금지가 맞지만, 응답에
public·s-maxage·must-revalidate중 하나가 있으면 저장이 허용으로 뒤집힌다. 개인화 응답에 예외 지시를 붙였다가 다른 사용자에게 재사용되는 것이 반대 방향의 위험이다. - 왜 믿는가: '인증 됐으니 안전'과 '캐시는 알아서 격리되어 있다'는 두 안일함이 겹친다.
- 오답 유형:
overgeneralized
- 실제: 원문 문자열은 q값·순서·나열까지 브라우저마다 제각각이라 사실상 유니크하다. CDN이 지원 인코딩 집합으로 정규화해 주는지가 갈림길이고, 정규화 없이 키에 들어가면 그대로 폭발한다.
- 왜 믿는가: 'gzip/br 몇 종류겠거니' 하고 실제 헤더 원문을 열어보지 않는다.
- 오답 유형:
overgeneralized
- 실제:
Range는 키가 아니다. 전체 객체가 캐시돼 있으면 엣지가 필요한 슬라이스만 잘라 206으로 낸다. 벤더별로 갈리는 것은 미스 때 오리진을 어떻게 fetch하느냐(전체 저장 후 슬라이스 vs 범위만 프록시)다. - 왜 믿는가: 쿼리 파라미터가 캐시 키에 들어가는 경험을 Range에까지 확장한다.
- 오답 유형:
overgeneralized
- 실제: UA 원문은 브라우저·버전·디바이스·패치 수준까지 갈라져 사실상 요청별 유니크다. 소수 버킷으로 정규화하지 않으면 캐시 키가 요청 단위로 폭발한다.
- 왜 믿는가: 모바일/데스크톱 정도로 나뉜다고 상상하고 실제 헤더 원문을 열어보지 않는다.
- 오답 유형:
overgeneralized
- 실제: 만료 순간에 몰리는 문제라 TTL을 늘리면 간격만 벌어지고 스파이크는 그대로다. 해법은 요청 병합(collapsed forwarding), TTL jitter,
stale-while-revalidate다. - 왜 믿는가: 만료가 원인이니 만료를 늦추면 될 것 같다.
- 오답 유형:
one-step-short
- 실제: purge는 전파 지연·부분 실패·N개 CDN 일관성 문제를 안는다. 실무는 대개 immutable + 버전드 URL로 수렴한다.
- 왜 믿는가: "지우면 끝"이 직관적이다.
- 오답 유형:
one-step-short
- 실제: 전자는 정상 상황의 만료 직후, 후자는 오리진 장애 시다. 트리거가 다르다.
- 왜 믿는가: 둘 다 "낡은 응답을 준다"는 결과가 같다.
- 오답 유형:
adjacent
- 실제:
must-revalidate가 있으면 오류 시에도 stale 제공이 금지되어stale-if-error가 뚫고 나갈 수 없다. 장애 시 무정전 설계를 원하면 애초에must-revalidate를 넣지 않는다. - 왜 믿는가: 안전장치는 많을수록 좋다는 일반 직관.
- 오답 유형:
inverted
- 실제: mtime/inode 기반 ETag는 오리진마다 값이 어긋날 수 있고, 그러면 재검증이 계속 실패해 304 대신 200 본문 재전송이 반복된다. 재검증 왕복 비용은 내면서 본문 절약은 0이 되는 조합이다.
- 왜 믿는가: ETag를 '그냥 아무 값'으로 취급하고 생성 규칙이 서버마다 다르다는 사실을 확인해 본 적이 없다.
- 오답 유형:
one-step-short
- 실제: 성공 응답은 접수 완료일 뿐 전 PoP 전파와는 별개고, 전파는 비동기로 수 분 걸린다. 멀티 CDN이면 벤더마다 API·단위·전파 SLA가 달라 N벌 관리 문제가 된다.
- 왜 믿는가: API가 성공 응답을 주면 작업이 끝났다고 읽는 습관.
- 오답 유형:
one-step-short
- 실제: private이 막는 것은 공유 캐시 저장뿐이다. 브라우저 캐시에는 디스크로도 저장된다. 공용 기기의 잔존까지 막으려면 no-store다.
- 왜 믿는가: '개인용'이라는 이름이 '안전하게 격리·소거'로 읽힌다.
- 오답 유형:
one-step-short
- 실제: Last-Modified 이후 경과 구간의 비율(10% 관행)로 추정해, 수정 이력이 길면 수 주씩 신선하다고 본다. 이미 퍼진 옛 사본은 배포 전 기준의 긴 수명을 그대로 가지고 있어 수정 반영이 그 수명이 끝날 때까지 밀린다.
- 왜 믿는가: '명시가 없으면 보수적 짧은 값'일 거라는 직관. 이력 길이가 수명에 비례한다는 사실을 직관이 못 미친다.
- 오답 유형:
plausible-number
- 실제: 분리해야 하는 경우가 많다.
s-maxage,Surrogate-Control,CDN-Cache-Control계열이 그래서 존재한다. 엣지는 길게, 브라우저는 짧게가 흔한 패턴이다. - 왜 믿는가:
Cache-Control하나로 다 되는 것처럼 배운다. - 오답 유형:
one-step-short
- 실제: 공유 캐시 전체를 하나의 값으로 묶는다. '우리 CDN'과 '그 뒤 계층'을 나누는 것은
CDN-Cache-Control·Surrogate-Control계열의 몫이고, 이들은 표준이 아니다. - 왜 믿는가: 브라우저/엣지 2분할까지만 경험해 보고 계층 3개 이상의 요구를 겪어 본 적이 없다.
- 오답 유형:
one-step-short
- 실제: 명시적 캐싱 허용이 없으면 공유 캐시는 Set-Cookie 응답을 저장하지 않는 것이 규범이다. 쿠키를 캐시 키에 넣는 순간 사용자별로 키가 갈라지는 일도 겹친다. 캐시 대상 경로에서 쿠키를 아예 내리지 않는 것이 설계 원칙이다.
- 왜 믿는가:
max-age만 보면 될 것 같다. 쿠키와 캐시의 상호작용을 따져본 적이 없다. - 오답 유형:
one-step-short
- 실제: Vary에 오른 요청 헤더 값이 갈리는 만큼 캐시 엔트리가 쪼개진다. 같은 폰트 URL이 Origin 헤더 유무(cors 모드 preload vs no-cors CSS 로드)로 두 변형이 되어 오리진 전송이 2배가 된 실측 사고가 있다.
- 왜 믿는가: Vary를 '안전하게 하는 헤더'로만 배우고, 변형 분열이라는 비용 축을 계산해 본 적이 없다.
- 오답 유형:
one-step-short
- 실제: 사전 압축(RFC 9842)에서는 같은 dcz 인코딩이라도 어떤 사전으로 압축했는지에 따라 응답이 다르다. 캐시 가능한 사전 압축 응답은 Vary에 Available-Dictionary까지 올려야 한다.
- 왜 믿는가: gzip/br 시대의 경험이 굳어 있다. 압축 축이 늘면 변형 축도 는다는 일반화를 안 해 봤다.
- 오답 유형:
outdated
- 실제: Cache-Status(RFC 9211)에서 hit과 배타인 것은 fwd이지 stale이 아니다. ttl 파라미터가 음수면 신선 수명을 넘긴 엔트리를 서빙한 것이고(stale-while-revalidate 류), hit; ttl=-87 은 규격상 정상 표기다.
- 왜 믿는가: hit/miss 이분법으로만 캐시를 읽어 왔고, stale 서빙이라는 제3의 상태를 표기 체계에 넣어 본 적이 없다.
- 오답 유형:
adjacent