사전 Cache-Control
표준

Cache-Control

gabury1

Cache-Control 은 캐시에게 줄 지시를 적어 보내는 헤더 필드입니다. 응답을 저장해도 되는지, 얼마나 오래 그대로 써도 되는지를 여기에 적습니다. 요청에도 실리고 응답에도 실립니다.

쉽고 빠른 이해

Cache-Control 은 캐시에게 지시를 적어 보내는 헤더입니다. no-store 처럼 저장 자체를 막는 값도 있고, max-age=5 처럼 몇 초 동안 신선하다고 볼지 정하는 값도 있습니다.

이게 없으면 캐시가 응답을 얼마나 믿고 그대로 다시 써도 되는지 판단할 방법이 없습니다. 매번 오리진 서버(응답을 원래 만들어 내는 서버입니다)에 다시 물어야 하거나, 반대로 낡은 응답을 계속 내줄 위험을 안게 됩니다.

이 헤더는 세 가지를 정해서 돕습니다.

  1. 저장해도 되는지 — no-store 가 있으면 저장을 아예 막습니다
  2. 얼마나 오래 신선하다고 볼지 — max-age 로 초 단위 수명을 정합니다
  3. 다시 쓰기 전에 오리진 서버에 물어야 하는지 — no-cache·must-revalidate 로 검증(캐시가 저장해 둔 응답이 아직 쓸 만한지 오리진 서버에 물어 확인받는 것입니다)을 강제합니다

대가도 따릅니다. no-cache 를 걸면 신선한 응답도 매번 검증부터 받아야 해서 캐시가 주는 속도 이점이 줄어듭니다. must-revalidate 를 건 응답이 낡았는데 오리진에 닿지 못하면, 캐시는 낡은 응답을 내주는 대신 오류로 답해야 합니다.

상세

RFC(Request for Comments) 9111 은 이 필드를 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜) 요청과 응답이 지나는 사슬 위의 캐시들에게 줄 지시어 목록이라고 정의합니다. 지시어는 단방향입니다. 요청에 어떤 지시어가 있다고 해서 같은 지시어가 응답에 있거나 응답으로 복사된다는 뜻은 아닙니다.

특정 캐시 하나를 겨냥할 수는 없습니다. 프록시는 캐시를 구현하든 안 하든 전달하는 메시지에서 캐시 지시어를 그대로 통과시켜야 합니다. 그 프록시에게 의미가 없는 지시어여도 그렇습니다. 지시어가 사슬 위의 모든 수신자에게 적용될 수 있기 때문입니다.

값의 생김새는 단순합니다. 지시어는 토큰으로 식별하고 대소문자를 구별하지 않고 비교합니다. 인자는 선택이고 토큰과 따옴표 문자열 양쪽 문법을 쓸 수 있습니다. max-age=5 처럼 토큰 꼴로 적는 지시어가 있고, no-cache 응답 지시어처럼 인자를 따옴표로 감싸 적는 지시어도 있습니다. RFC 9111 뒤에서 인자를 정의하는 지시어들은 보내는 쪽에 특정 꼴이 요구되더라도, 받는 쪽은 두 꼴을 모두 받아들이는 것이 마땅합니다.

Cache-Control   = #cache-directive

cache-directive = token [ "=" ( token / quoted-string ) ]

# 는 값을 쉼표로 이어 붙일 수 있다는 표시입니다. 따로 밝히지 않는 한 지시어에 인자는 정의되어 있지 않고 허용되지도 않습니다.

이 필드가 정하는 것은 세 가지입니다. 첫째는 저장해도 되는가입니다. RFC 9111 §3 은 일곱 조건을 정합니다. 일곱 조건을 모두 만족해야 캐시가 응답을 저장할 수 있습니다. 다만 캐시 확장 지시어가 이 조건들 가운데 무엇이든 덮어쓸 수 있습니다.

일곱 조건은 이렇습니다. 요청 메서드를 캐시가 이해해야 하고, 응답 상태 코드가 최종(정보성으로 잠깐 오가는 것이 아니라 요청에 대한 마지막 답으로 오는 상태 코드라는 뜻입니다)이어야 합니다. 상태 코드가 206 이나 304 이거나 must-understand(그 상태 코드를 이해하는 캐시로만 캐싱을 한정하는 지시어입니다) 지시어가 있으면, 캐시가 그 상태 코드를 이해해야 합니다. 응답에 no-store 지시어가 없어야 합니다. 공유 캐시(여러 사용자가 함께 쓰는 캐시입니다. 한 사용자만 쓰는 캐시는 사설 캐시입니다)라면 private 응답 지시어가 없거나, 있어도 공유 캐시의 저장을 막지 않는 경우여야 하고, 공유 캐시라면 요청에 Authorization 헤더 필드가 없거나 공유 캐싱을 명시적으로 허용하는 응답 지시어가 있어야 합니다. 그리고 응답이 public · Expires 헤더 필드 · max-age · 캐시를 허용하는 확장 · 휴리스틱하게(오리진 서버가 명시적 만료 시각을 안 줬을 때 캐시가 스스로 어림잡아 정하는 방식으로) 캐시 가능하다고 정의된 상태 코드 가운데 적어도 하나를 담아야 하고, 여기에 공유 캐시가 아니면 private 응답 지시어도, 공유 캐시면 s-maxage 응답 지시어도 더해집니다.

flowchart TD
    A["요청 메서드를 캐시가 이해하나"] -->|아니다| N["저장 금지"]
    A -->|그렇다| B["상태 코드가 최종인가"]
    B -->|아니다| N
    B -->|그렇다| C["상태 코드가 206·304 이거나 must-understand 가 있으면,<br/>캐시가 그 상태 코드를 이해하나"]
    C -->|아니다| N
    C -->|그렇다| D["no-store 지시어가 없나"]
    D -->|아니다| N
    D -->|그렇다| E["공유 캐시면: private 이 없거나 저장을 막지 않나"]
    E -->|아니다| N
    E -->|그렇다| F["공유 캐시면: Authorization 이 없거나 공유 캐싱을 명시 허용하나"]
    F -->|아니다| N
    F -->|그렇다| G["public·Expires·max-age·확장·휴리스틱 가능 상태 코드·private·s-maxage 중 하나 이상 있나"]
    G -->|없다| N
    G -->|있다| S["저장해도 된다"]

둘째는 얼마나 오래 신선한가입니다. 나이(응답이 오리진 서버에서 만들어지거나 오리진 서버와 검증에 성공한 뒤로 지난 시간입니다)가 신선도 수명을 아직 넘지 않은 응답이 신선한 응답입니다. 넘은 것이 낡은 응답입니다. 응답이 신선하면 오리진 서버에 연락하지 않고 이후 요청에 쓸 수 있습니다. 신선도를 정하는 1차 메커니즘은 오리진 서버가 미래의 만료 시각을 명시하는 것입니다. Expires 헤더 필드나 max-age 응답 지시어를 씁니다.

response_is_fresh = (freshness_lifetime > current_age)

여기서 freshness_lifetime 은 신선도 수명, current_age 는 나이입니다. 신선도 수명은 첫 일치 규칙으로 정합니다.

flowchart TD
    A{"공유 캐시이고 s-maxage 가 있나"} -->|그렇다| A1["s-maxage 값"]
    A -->|아니다| B{"max-age 가 있나"}
    B -->|그렇다| B1["max-age 값"]
    B -->|아니다| C{"Expires 가 있나"}
    C -->|그렇다| C1["Expires 값 빼기 Date 값"]
    C -->|아니다| D["명시적 만료 시각 없음 · 휴리스틱 신선도 수명"]

캐시는 위 규칙을 차례로 따져 처음 맞는 것을 씁니다. Expires 값에서 Date 값을 뺄 때 Date 가 없으면 메시지를 받은 시각을 대신 씁니다. 셋 다 아니면 응답에 명시적 만료 시각이 없는 것이고 휴리스틱 신선도 수명이 적용될 수 있습니다.

셋째는 다시 쓰기 전에 오리진 서버에 물어야 하는가입니다. no-cache 응답 지시어는 인자 없는 꼴에서 그 응답을 검증에 넘겨 성공 응답을 받기 전에는 다른 요청에 쓰면 안 된다고 지시합니다. 낡은 응답을 보내도록 설정된 캐시에게까지 걸립니다. must-revalidate 는 응답이 낡은 뒤에는 오리진이 검증해 주기 전까지 다른 요청에 재사용하면 안 된다고 지시합니다.

no-cache 와 must-revalidate 가 신선도와 맞물려 검증을 강제하는 자리는 이렇습니다.

stateDiagram-v2
    state "신선한 응답" as Fresh
    state "낡은 응답" as Stale
    state "검증" as Validating

    [*] --> Fresh: 오리진 서버가 응답을 만든다
    Fresh --> Stale: 나이가 신선도 수명을 넘는다
    Fresh --> Validating: no-cache 지시어가 있다
    Stale --> Validating: must-revalidate 지시어가 있다
    Validating --> Fresh: 오리진이 검증에 성공하면 나이가 새로 시작해 신선한 응답이 된다

두 지시어가 모두 없으면 신선한 동안에는 검증 없이 그대로 재사용됩니다.

캐시는 알아보지 못한 캐시 지시어를 무시해야 합니다. 지시어 이름의 이름공간은 IANA(Internet Assigned Numbers Authority, 인터넷 할당 번호 관리기관) 의 HTTP Cache Directive Registry 가 정의합니다.

출처 문서

정본은 RFC 9111 입니다. 제목은 HTTP Caching 이고 2022년 6월에 나왔습니다. Category 는 Standards Track 이고 STD(Standard) 번호 98 을 받았습니다. RFC 7234 를 폐기했습니다. 편집자는 R. Fielding · M. Nottingham · J. Reschke 이고 IETF(Internet Engineering Task Force, 국제 인터넷 표준화 기구) 의 HTTP(HTTPBIS) 워킹 그룹이 낸 문서입니다. 옛 절 번호를 인용하면 폐기된 판을 드는 것입니다.

요구 강도 낱말의 뜻은 §1.1 이 정합니다. MUST · MUST NOT · REQUIRED · SHALL · SHALL NOT · SHOULD · SHOULD NOT · RECOMMENDED · NOT RECOMMENDED · MAY · OPTIONAL 을 BCP(Best Current Practice) 14 (RFC 2119 · RFC 8174) 에 적힌 대로 해석합니다. 다만 그 낱말이 전부 대문자로 적혔을 때, 그리고 그때만 그렇게 해석합니다.

요청 쪽과 응답 쪽은 강도부터 갈립니다. §5.2.1 은 요청 지시어가 권고라고 못 박습니다. 캐시는 그것을 구현해도 되지만(MAY) 구현이 요구되지는 않습니다. §5.2.2 는 반대입니다. 캐시는 그 절에 정의된 Cache-Control 지시어를 따라야 합니다(MUST obey).

지시어별 절 번호와 요구 강도

지시어 뜻 절 문서가 쓴 요구 강도
max-age (요청) 나이가 지정한 초 이하인 응답을 선호 5.2.1.1 보내는 쪽은 따옴표 문자열 꼴을 생성하면 안 됩니다(MUST NOT)
max-stale 신선도 수명을 넘긴 응답도 받아들임 5.2.1.2 강도 낱말 없음. 클라이언트가 무엇을 받아들이는지만 적습니다
min-fresh 지정한 시간만큼 더 신선할 응답을 선호 5.2.1.3 강도 낱말 없음. 클라이언트가 무엇을 선호하는지만 적습니다
no-cache (요청) 검증 없이 저장된 응답을 쓰지 않기를 선호 5.2.1.4 강도 낱말 없음. 클라이언트가 무엇을 선호하는지만 적습니다
no-store (요청) 요청·응답 어느 부분도 저장 금지 5.2.1.5 캐시가 이 요청이나 그 응답의 어느 부분도 저장하면 안 됩니다(MUST NOT)
no-transform (요청) 중간자(앞서 나온 프록시도 여기 포함됩니다)에게 콘텐츠 변환을 하지 말라고 요청 5.2.1.6 강도 낱말 없음. 클라이언트가 요청하는 것이라고만 적습니다
only-if-cached 저장된 응답만 요구 5.2.1.7 이를 존중하는 캐시는 저장된 응답이나 504(Gateway Timeout) 로 답하는 것이 좋습니다(SHOULD)
max-age (응답) 지정한 초를 넘기면 응답을 낡은 것으로 봄 5.2.2.1 보내는 쪽은 따옴표 문자열 꼴을 생성하면 안 됩니다(MUST NOT)
must-revalidate 낡은 뒤 검증 전 재사용 금지 5.2.2.2 낡은 뒤 검증 전 재사용 금지(MUST NOT) · 어떤 상황에서도 무시 금지(MUST NOT) · 끊긴 캐시(오리진 서버와 연결할 수 없는 캐시)는 오류 응답을 생성해야 합니다(MUST) · 상태 코드는 504 가 좋습니다(SHOULD)
must-understand 그 상태 코드를 이해하는 캐시로 캐싱을 한정 5.2.2.3 no-store 도 함께 담는 것이 좋습니다(SHOULD) · 상태 코드의 캐싱 요구를 이해하고 구현하면 no-store 를 무시하는 것이 좋습니다(SHOULD)
no-cache (응답) 검증에 성공하기 전에는 다른 요청에 쓰면 안 됨 5.2.2.4 검증에 넘겨 성공하기 전에는 다른 요청에 쓰면 안 됩니다(MUST NOT) · 인자는 따옴표 문자열 꼴이고 토큰 꼴을 생성하지 않는 것이 좋습니다(SHOULD NOT)
no-store (응답) 저장·재사용 모두 금지 5.2.2.5 어느 부분도 저장 금지 · 다른 요청에 사용 금지(MUST NOT) · 비휘발성 저장소에 일부러 저장 금지(MUST NOT) · 휘발성 저장소에서 지우려 최선을 다해야 합니다(MUST)
no-transform (응답) 중간자의 콘텐츠 변환 금지 5.2.2.6 중간자(캐시를 구현하든 안 하든)는 콘텐츠를 변환하면 안 됩니다(MUST NOT)
private 공유 캐시엔 저장 금지, 사설 캐시는 허용 5.2.2.7 공유 캐시는 저장하면 안 됩니다(MUST NOT) · 사설 캐시는 저장해도 됩니다(MAY)
proxy-revalidate 공유 캐시에만 낡은 뒤 재검증을 요구 5.2.2.8 공유 캐시는 낡은 뒤 검증 전 재사용 금지(MUST NOT)
public 원래 금지됐을 응답도 저장을 허용 5.2.2.9 캐시가 저장해도 됩니다(MAY)
s-maxage 공유 캐시의 최대 나이를 덮어씀 5.2.2.10 공유 캐시는 낡은 뒤 검증 전 재사용 금지(MUST NOT) · 따옴표 문자열 꼴 생성 금지(MUST NOT)

must-revalidate 에는 강도 밖의 문장도 붙습니다. RFC 9111 은 이 지시어를 서버가 쓰는 것이 마땅한 경우를 검증 실패가 잘못된 동작을 낳을 수 있을 때로 한정합니다. 조용히 실행되지 않은 금융 거래를 예로 듭니다.

명세가 안 정하고 남긴 자리

요청 지시어를 캐시가 존중할 의무는 없습니다. §4.2 도 클라이언트가 max-age 나 min-fresh 요청 지시어로 신선도 계산의 한계를 제안할 수 있지만 캐시가 그것을 존중할 것이 요구되지는 않는다고 적습니다.

중복과 충돌의 처리는 소문자 should 로 적혀 있습니다. §4.2.1 은 한 지시어에 값이 여럿 있으면 첫 등장을 쓰거나 응답을 낡은 것으로 보아야 마땅하다고 적습니다. max-age 와 no-cache 처럼 지시어가 충돌하면 가장 제한적인 지시어를 존중해야 마땅하다고 적습니다. 전부 대문자가 아니므로 §1.1 이 정한 BCP 14 요구는 아닙니다. 정수가 아닌 max-age 값처럼 신선도 정보가 유효하지 않은 응답은 낡은 것으로 보도록 캐시들에게 권장합니다.

지시어 이름 전체 목록의 정본은 등록부입니다. IANA 의 HTTP Cache Directive Registry 는 2014-02-17 에 만들어졌고 2022-06-08 에 마지막으로 갱신됐습니다. 등록 절차는 IETF Review 이고, 등록에는 지시어 이름과 명세 텍스트를 가리키는 포인터가 반드시 들어가야 합니다(MUST). 등록부에 있지만 RFC 9111 이 정의하지 않은 이름도 있습니다. immutable 은 RFC 8246 이, stale-if-error 와 stale-while-revalidate 는 RFC 5861 이 정의합니다.

RFC 7234 에서 바뀐 것

Appendix B 가 무엇이 바뀌었는지를 적습니다. 중복되고 충돌하는 캐시 지시어의 처리가 명확해졌습니다. 일부 지시어는 값의 따옴표 꼴을 생성하는 것에 대한 금지가 더 강해졌습니다. 그것이 상호운용 문제를 만든다는 것이 확인됐기 때문입니다. 확장 캐시 지시어를 소비하는 쪽은 토큰과 따옴표 문자열 두 꼴을 모두 받아들일 의무에서 풀렸습니다. 다만 모르는 확장을 제대로 파싱할 필요는 여전히 있습니다. public 과 private 지시어는 어떤 조건에서도 응답을 재사용 가능하게 만들지는 않는다는 쪽으로 명확해졌습니다. must-understand 가 새로 들어왔고, 그에 따라 캐시가 새 응답 상태 코드의 의미론을 이해할 의무는 must-understand 가 있을 때로 좁혀졌습니다. Warning 응답 헤더는 폐기됐습니다.

예시

RFC 9111 본문에 실제로 적혀 있는 값들입니다.

확장 지시어를 붙인 값

Cache-Control: private, community="UCI"

§5.2.3 이 든 값입니다. community 는 private 지시어를 수식하는 새 응답 지시어로 가정한 것입니다. 사설 캐시에 더해, 이름 붙은 커뮤니티의 구성원들이 공유하는 캐시만 그 응답을 캐시할 수 있게 합니다. 이런 확장을 알아보는 캐시는 그 확장에 맞춰 동작을 넓힐 수 있습니다. 알아보지 못하는 캐시는 community 를 무시하고 private 지시어를 따릅니다. 쉼표로 지시어를 이어 붙이는 근거는 §5.2 의 Cache-Control = #cache-directive 입니다.

어느 응답을 쓸지 모호함을 없애는 값

Cache-Control: max-age=0
Cache-Control: no-cache

§4 의 값들입니다. 알맞은 응답이 여럿 저장되어 있으면 캐시는 Date 헤더 필드로 판정한 가장 최근 것을 써야 합니다. max-age=0 이나 no-cache 를 실어 요청을 전달하면 캐시가 저장해 둔 응답 대신 오리진 서버의 검증을 거치게 되므로, 어느 응답을 쓸지 모호함을 없앨 수 있습니다.

저장 자체를 막는 값

Cache-Control: no-store

§6 이 애플리케이션과 캐시의 관계를 이야기하며 든 값입니다. no-store 를 실으면 캐시가 이 요청이나 응답의 어느 부분도 저장하지 못합니다. RFC 9111 은 애플리케이션이 HTTP 캐싱을 고려하는 것을 금지하지 않습니다. 히스토리 메커니즘(브라우저의 뒤로 가기처럼 이전에 본 것을 다시 보여 주는 기능)이 사용자에게 지금 보는 것이 낡았다고 알려 줄 수도 있고, 이런 캐시 지시어를 존중할 수도 있습니다.

인자를 적는 꼴

max-age=5
s-maxage=10

delta-seconds 인자를 쓰는 지시어는 토큰 꼴로 적습니다. max-age=5 이지 max-age="5" 가 아닙니다. s-maxage=10 이지 s-maxage="10" 이 아닙니다. 보내는 쪽은 따옴표 문자열 꼴을 생성하면 안 됩니다(MUST NOT). no-cache 응답 지시어는 반대입니다. 인자를 따옴표 문자열 꼴로 적고, 보내는 쪽은 토큰 꼴을 생성하지 않는 것이 좋습니다(SHOULD NOT). 항목이 하나뿐이라 따옴표가 필요 없어 보일 때도 그렇습니다.

신선도 판정식

response_is_fresh = (freshness_lifetime > current_age)

§4.2 의 식입니다. max-age 응답 지시어가 적은 초가 여기서 freshness_lifetime 자리에 들어갑니다. 공유 캐시에서 s-maxage 가 있으면 그 값이 먼저 들어갑니다.

만료 시각을 적는 값

Expires: Thu, 01 Dec 1994 16:00:00 GMT

§5.3 의 값입니다. Expires 필드 값은 HTTP-date 타임스탬프이고, 이 시각이 지나면 응답을 낡은 것으로 본다는 절대 시각입니다.

배경

HTTP/1.0 캐시에는 Pragma 가 있었습니다. 클라이언트가 no-cache 요청을 지정할 수 있게 하려고 정의한 요청 헤더 필드입니다. Cache-Control 이 HTTP/1.1 에 가서야 정의됐기 때문입니다. 지금은 Cache-Control 지원이 널리 퍼졌습니다. 그래서 RFC 9111 은 Pragma 를 폐지 예정으로 둡니다. 응답에 실린 "Pragma: no-cache" 의 뜻은 한 번도 명세된 적이 없습니다. 그래서 응답에서는 "Cache-Control: no-cache" 를 믿을 만하게 대신하지 못합니다.

만료 시각을 적는 필드로는 Expires 가 있습니다. 값은 HTTP-date 타임스탬프이고 절대 시각입니다. 절대 시각은 시계에 기댑니다. 시계가 없는 오리진 서버는 Expires 헤더 필드를 생성하면 안 됩니다 (MUST NOT). 값이 과거의 고정 시각이거나 시계를 가진 시스템이 그 값을 리소스에 연결해 준 경우만 예외입니다. 받는 쪽에도 부담이 옵니다. 캐시는 유효하지 않은 날짜 꼴, 특히 값 "0" 을 과거의 시각으로, 곧 이미 만료된 것으로 해석해야 합니다(MUST). 신선도 수명 계산에도 같은 걱정이 붙습니다. RFC 9111 은 그 계산이 가능한 한 오리진 서버가 준 시계 정보를 써서 시계 어긋남을 줄이려는 것이라고 적습니다.

max-age 는 절대 시각이 아니라 초 단위 상대 시간입니다. 그래서 둘이 함께 오면 상대 시간이 이깁니다. 응답에 max-age 지시어가 든 Cache-Control 헤더 필드가 있으면 수신자는 Expires 헤더 필드를 무시해야 합니다(MUST). s-maxage 가 있으면 공유 캐시 수신자가 Expires 를 무시해야 합니다 (MUST). 두 경우 모두 Expires 의 값은 Cache-Control 헤더 필드를 아직 구현하지 않은 수신자만을 위한 것입니다. 예전에는 Expires 값이 1년보다 멀면 안 됐습니다. 지금은 더 긴 신선도 수명이 금지되지는 않습니다. 다만 아주 큰 값이 문제를 일으킨다는 것이 실증됐습니다. 시간 값에 32비트 정수를 쓰는 탓에 시계가 넘치는 식입니다. 그리고 많은 캐시는 그보다 훨씬 일찍 응답을 축출합니다.

갈래

같은 필드지만 어느 메시지에 실리느냐에 따라 지시어 목록이 갈립니다. 그것이 축입니다. 지시어는 단방향이라 요청에 쓴 것이 응답에 그대로 나타나지 않습니다. 이름이 같아도 자리가 다르면 절 번호가 따로입니다. max-age · no-cache · no-store · no-transform 이 양쪽에 다 있습니다. 요구 강도도 갈립니다.

요청 지시어

§5.2.1 이 정의합니다. 이 지시어들은 권고입니다. 캐시가 구현해도 되지만(MAY) 구현이 요구되지는 않습니다.

지시어 인자 문서가 적은 뜻
max-age delta-seconds 클라이언트가 나이가 지정한 초 이하인 응답을 선호합니다. max-stale 이 같이 있지 않으면 클라이언트는 낡은 응답을 받고 싶어하지 않습니다
max-stale delta-seconds (없어도 됩니다) 클라이언트가 신선도 수명을 넘긴 응답도 받아들입니다. 값이 있으면 그 초만큼까지만, 값이 없으면 나이를 가리지 않습니다
min-fresh delta-seconds 클라이언트가 신선도 수명이 현재 나이에 지정한 시간을 더한 것 이상인 응답을 선호합니다. 지정한 초만큼은 계속 신선할 응답을 원하는 것입니다
no-cache 없음 클라이언트가 저장된 응답을 오리진 서버에서 검증에 성공하지 않은 채로 쓰지 않기를 선호합니다
no-store 없음 캐시가 이 요청이나 그 응답의 어느 부분도 저장하면 안 됩니다. 사설 캐시와 공유 캐시 양쪽에 걸립니다
no-transform 없음 클라이언트가 중간자들에게 콘텐츠를 변환하지 말아 달라고 요청합니다
only-if-cached 없음 클라이언트가 저장된 응답만 얻기를 바랍니다

no-store 의 "저장하면 안 된다"는 두 가지를 뜻합니다. 캐시가 그 정보를 비휘발성 저장소에 일부러 저장하면 안 되고, 전달한 뒤에는 휘발성 저장소에서도 되도록 빨리 지우려 최선을 다해야 합니다. only-if-cached 를 존중하는 캐시는 그것을 받았을 때 요청의 다른 제약에 맞는 저장된 응답이나 504 (Gateway Timeout) 상태 코드로 답하는 것이 좋습니다(SHOULD).

응답 지시어

§5.2.2 가 정의합니다. 캐시는 이 절에 정의된 Cache-Control 지시어를 따라야 합니다.

지시어 인자 문서가 적은 뜻
max-age delta-seconds 나이가 지정한 초를 넘긴 뒤로는 응답을 낡은 것으로 봅니다
must-revalidate 없음 응답이 낡은 뒤에는 오리진이 검증해 주기 전까지 다른 요청에 재사용하면 안 됩니다
must-understand 없음 그 응답 상태 코드의 요구사항을 이해하고 따르는 캐시로 캐싱을 한정합니다
no-cache #field-name (없어도 됩니다) 인자 없는 꼴은 검증에 넘겨 성공하기 전에는 다른 요청에 쓰지 못하게 합니다. 인자가 있는 꼴은 적힌 헤더 필드들이 빠지거나 검증으로 갱신되면 그 응답을 써도 된다는 뜻입니다(MAY)
no-store 없음 그 요청과 응답의 어느 부분도 저장하면 안 되고 다른 요청에 그 응답을 쓰면 안 됩니다
no-transform 없음 중간자는 캐시를 구현하든 안 하든 콘텐츠를 변환하면 안 됩니다
private #field-name (없어도 됩니다) 인자 없는 꼴은 공유 캐시가 저장하지 못하게 합니다. 응답이 한 사용자를 위한 것이라는 뜻입니다. 사설 캐시는 §3 의 제약 아래 저장해도 됩니다(MAY)
proxy-revalidate 없음 must-revalidate 와 같되 사설 캐시에는 걸리지 않습니다
public 없음 원래 금지됐을 응답이라도 캐시가 §3 의 제약 아래 저장해도 됩니다(MAY)
s-maxage delta-seconds 공유 캐시에 대해 max-age 나 Expires 가 정한 최대 나이를 덮어씁니다

지시어끼리 겹치는 자리도 있습니다. s-maxage 는 공유 캐시에 대해 proxy-revalidate 의 의미론을 포함합니다. 공유 캐시는 s-maxage 가 붙은 낡은 응답을 오리진이 검증해 주기 전까지 다른 요청에 재사용하면 안 됩니다. must-understand 는 어떤 상황에서 no-store 를 뒤집습니다. must-understand 를 구현한 캐시가 그것이 든 응답을 받고 상태 코드의 캐싱 요구를 이해하고 구현한다면 no-store 를 무시하는 것이 좋습니다(SHOULD). public 은 반대로 필요 없어지는 자리가 있습니다. §3 에 따라 이미 캐시 가능한 응답에는 public 을 더할 필요가 없습니다. 명시적 신선도 정보가 없는 응답에 public 이 붙어 있으면 그 응답은 휴리스틱하게 캐시 가능합니다.

no-store 에는 한계가 명시되어 있습니다. RFC 9111 은 이 지시어가 프라이버시를 보장하는 데 믿을 만하거나 충분한 메커니즘이 아니라고 적습니다. 악의적이거나 침해당한 캐시는 이 지시어를 알아보지 않거나 따르지 않을 수 있습니다. 통신망은 도청에 취약할 수 있습니다.

관련 항목

이 지시어가 속한 프로토콜과 관리 기구

HTTP · IANA · IETF

같은 자리를 다투던 이웃 헤더

Expires · Pragma · Warning

이 지시어를 정의할 때 쓰는 개념

캐싱 · 신선도 · 오리진 서버 · 요청 메서드 · 상태 코드 · 메시지

다른 이름: cache-control · 캐시 컨트롤