[TIL] HTTP : The Definitive Guide "p182 ~ p183"

시윤·2025년 1월 11일
1

[TIL] Two Pages Per Day

목록 보기
76/107
post-thumbnail

Chapter 7. Caching

(해석 또는 이해가 잘못된 부분이 있다면 댓글로 편하게 알려주세요.)


✏️ 원문 번역


Controlling Cachability

HTTP defines several ways for a server to specify how long a document can be cached before it expires. In decreasing order of priority, the server can:

• Attach a Cache-Control: no-store header to the response.

• Attach a Cache-Control: no-cache header to the response.

• Attach a Cache-Control: must-revalidate header to the response.

• Attach a Cache-Control: max-age header to the response.

• Attach an Expires date header to the response.

• Attach no expiration information, letting the cache determine its own heuristic expiration date.

  • HTTP는 문서가 만료되기 전까지 얼마나 오랜 시간 캐싱될 수 있는지 원본 서버가 정의하기 위한 여러 가지 수단을 제공하고 있습니다.
      1. 응답에 Cache-Control: no-store 헤더를 붙입니다.
      1. 응답에 Cache-Control: no-cache 헤더를 붙입니다.
      1. 응답에 Cache-Control: must-revalidate 헤더를 붙입니다.
      1. 응답에 Cache-Control: max-age 헤더를 붙입니다.
      1. 응답에 Expires date 헤더를 붙입니다.
      1. 어떠한 Expiration 정보도 붙이지 않고 캐시가 나름의 합리적인 만료일시를 설정하도록 합니다.

This section describes the cache controlling headers. The next section, “Setting Cache Controls,” describes how to assign different cache information to different content.

  • 이번 섹션에서는 캐시 제어 헤더에 대해 설명합니다.

  • 다음 섹션인 "Setting Cache Controls"에서는 서로 다른 콘텐츠에 대해 캐시 정보를 다르게 설정하는 방식에 대해 설명합니다.


No-Cache and No-Store Response Headers

HTTP/1.1 offers several ways to limit the caching of objects, or the serving of cached objects, to maintain freshness. The no-store and no-cache headers prevent caches from serving unverified cached objects:

Cache-Control: no-store
Cache-Control: no-cache
Pragma: no-cache

  • HTTP/1.1은 Freshness를 유지하기 위해 오브젝트를 캐싱하거나 캐싱된 오브젝트를 제공하는 것을 제한하는 방법들을 제공하고 있습니다.

  • no-store 및 no-cache 헤더는 검증되지 않은 캐싱 오브젝트를 제공하는 것을 방지합니다.

    	Cache-Control: no-store
    	Cache-Control: no-cache
    	Pragma: no-cache

A response that is marked "no-store" forbids a cache from making a copy of the response. A cache would typically forward a no-store response to the client, and then delete the object, as would a non-caching proxy server.

  • "no-store"로 표시된 응답은 캐시가 응답으로부터 사본을 생성하는 것을 막습니다.

  • 일반적으로 캐시는 비캐싱 프록시 서버와 마찬가지로 클라이언트에게 no-store 응답을 그대로 전달한 후 오브젝트를 삭제합니다.

A response that is marked "no-cache" can actually be stored in the local cache storage. It just cannot be served from the cache to the client without first revalidating the freshness with the origin server. A better name for this header might be "do-not-serve-from-cache-without-revalidation."

  • "no-cache"로 표시된 응답은 실제로 로컬 캐시 스토리지에 리소스를 저장할 수 있습니다.

  • 그러나 원본 서버에서 Freshness를 재검증하지 않으면 캐시에서 클라이언트로 해당 리소스를 제공할 수 없습니다.

  • 이 헤더에 더 적합한 이름은 "do-not-serve-from-cache-without-revalidation(재검증 없이 제공 불가)"일지도 모릅니다.

The Pragma: no-cache header is included in HTTP/1.1 for backward compatibility with HTTP/1.0+. HTTP/1.1 applications should use Cache-Control:no-cache, except when dealing with HTTP/1.0 applications, which understand only Pragma: no-cache.*

  • Pargma: no-cache 헤더는 HTTP/1.1에 포함되어 있습니다. 이전 버전인 HTTP/1.0+과의 호환성을 유지하기 위함입니다.

  • Pragma:no-cache만 이해할 수 있는 HTTP/1.0 응용 프로그램을 처리하는 것이 아니라면 HTTP/1.1 응용 프로그램은 Cache-Control:no-cache 헤더를 사용해야 합니다.


Max-Age Response Headers

The Cache-Control: max-age header indicates the number of seconds since it came from the server for which a document can be considered fresh. There is also an s-maxage header (note the absence of a hyphen in “maxage”) that acts like max-age but applies only to shared (public) caches:

Cache-Control: max-age=3600
Cache-Control: s-maxage=3600

  • Cache-Control: max-age 헤더는 원본 서버에서 응답이 온 후로 몇 초 동안을 Fresh 하다고 여길 것인지를 나타냅니다.

  • max-age처럼 동작하지만 Shared Cache에서만 동작하는 s-maxage 헤더라는 것도 있습니다. 이 헤더는 maxage 사이에 하이픈(-) 기호가 없음에 유의합니다.

    	Cache-Control: max-age=3600
    	Cache-Control: s-maxage=3600

Servers can request that caches either not cache a document or refresh on every access by setting the maximum aging to zero:

Cache-Control: max-age=0
Cache-Control: s-maxage=0

  • 서버는 maximum age를 0으로 설정하여 문서를 아예 캐싱하지 않거나 접근할 때마다 재검증을 수행하도록 요청할 수 있습니다.
    	Cache-Control: max-age=0
    	Cache-Control: s-maxage=0

Expires Response Headers

The deprecated Expires header specifies an actual expiration date instead of a time in seconds. The HTTP designers later decided that, because many servers have unsynchronized or incorrect clocks, it would be better to represent expiration in elapsed seconds, rather than absolute time. An analogous freshness lifetime can be calculated by computing the number of seconds difference between the expires value and the date value:

Expires: Fri, 05 Jul 2002, 05:00:00 GMT

  • 현재는 잘 사용되지 않는 Expires 헤더는 초 단위의 시간 대신 실제 만료 일시를 나타냅니다.

  • HTTP 설계자들은 시간이 흐르고 나서야 만료 일시를 절대 시간보다는 경과된 초 단위로 나타내는 것이 더 낫다는 것을 알게 됩니다. 많은 서버들이 동기화되지 않은 부정확한 시계를 사용하고 있었기 때문입니다.

  • Freshness의 생명주기는 Expires의 값과 Date의 값을 비교하여 연산될 수 있습니다.

Some servers also send back an Expires: 0 response header to try to make documents always expire, but this syntax is illegal and can cause problems with some software. You should try to support this construct as input, but shouldn’t generate it.

  • 어떤 서버는 문서를 항상 만료 상태로 두기 위해 Expires: 0 응답 헤더를 반환하기도 합니다.

  • 하지만 이것은 잘못된 문법으로, 일부 소프트웨어에서는 문제를 발생시킬 수 있습니다.

  • 개발자들은 이러한 잘못된 형태도 지원할 수 있어야 하지만 직접 생산해서는 안 됩니다.


Must-Revalidate Response Headers

Caches may be configured to serve stale (expired) objects, in order to improve performance. If an origin server wishes caches to strictly adhere to expiration information, it can attach a Cache-Control:

Cache-Control: must-revalidate

  • 캐시는 성능을 향상시키기 위해 Stale 오브젝트를 제공하도록 구성될 것입니다.

  • 만약 캐시가 만료에 대한 정보를 엄격하게 준수하길 원한다면 Cache-Control에 must-revalidate를 붙일 수 있습니다.

    	Cache-Control: must-revalidate

The Cache-Control: must-revalidate response header tells caches they cannot serve a stale copy of this object without first revalidating with the origin server. Caches are still free to serve fresh copies. If the origin server is unavailable when a cache attempts a must-revalidate freshness check, the cache must return a 504 Gateway Timeout error.

  • Cache-Control: must-revalidate 응답 헤더는 캐시가 오브젝트의 만료된 사본을 원본 서버로부터의 재검증 없이 제공하지 못하도록 합니다.

  • 물론 여전히 캐시는 Fresh한 사본들을 제공하는 것에 자유롭습니다.

  • 캐시가 must-revalidate에 따라 Freshenss Check를 요청하였지만 원본 서버를 이용할 수 없는 상황이라면, 캐시는 504 Gateway Timeout 에러를 반환해야 합니다.


✏️ 요약


Controlling Cachability

캐싱된 문서의 "Fresh" 기간을 원본 서버가 정의하기 위한 몇 가지 방식

[1] Cache-Control: no-store

Cache-Control: no-store
  • 캐시가 응답으로부터 사본을 저장하지 않는다
  • 클라이언트에게 응답을 전달한 후 오브젝트는 곧바로 삭제된다

[2] Cache-Control: no-cache

Cache-Control: no-cache
  • 캐시가 Freshness를 재검증하지 않으면 클라이언트로 리소스를 제공할 수 없다
  • 캐시가 응답으로부터 사본을 저장할 수 있다 (단, 제공 시 재검증 필요)

[3] Pragma: no-cache

Pragma: no-cache
  • HTTP/1.0+과의 호환성을 위해 사용하는 no-cache 헤더
  • HTTP/1.1 응용 프로그램에서는 Cache-Control: no-cache 헤더를 사용한다

[4] Cache-Control: max-age / s-maxage

Cache-Control: max-age=3600
Cache-Control: s-maxage=0
  • 서버에서 응답이 도착한 후 몇 초간 사본을 Fresh 한지 정의한다
  • s-maxage : Shared Cache에서만 동작하는 max-age 헤더
  • maximum age의 값이 0이면 no-store 혹은 no-cache처럼 동작

[5] Expires

Expires: Fri, 05 Jul 2002, 05:00:00 GMT
Expires: 0 (잘못된 형태)
  • Date와 Expires의 값을 비교함으로써 사본이 Fresh 한지 정의한다
  • 문서를 항상 Stale 상태로 두기 위해 Expires: 0을 사용하기도 하지만 이는 잘못된 문법이다

[6] Cache-Control: must-revalidate

Cache-Control: must-revalidate
  • 원본 서버로부터의 재검증 없이 만료된 사본을 제공하지 못하도록 한다
  • 원본 서버를 이용할 수 없는 상황이면 504 Gateway Timeout을 반환한다

✏️ 감상


신경쓰지 않아 몰랐던 것들

오늘 배운 헤더들 사실 개발하면서 많이 봤던 것들이다. 딱히 이 헤더들을 다룰 일도, 이 헤더 때문에 문제가 발생했던 적도 없어서 그저 항상 존재하는 공기처럼 취급했던 것뿐이다. 당연하다. Cache-Control이 어떻게 설정되어 있고 Expires가 어떻게 설정되어 있든 응답이 오는 데는 아무런 문제가 없다.

하지만 내가 오늘 이 글을 읽지 않고 이 헤더들을 평생 모르고 살았다면 언젠가 최적화에 문제가 발생했을 때 떠올릴 수 있는 묘수 하나가 없어지는 셈이다. 물론 그때가 되면 내가 오늘 읽은 모든 내용을 기억하지는 못하겠지만, 이미 알고 까먹은 것과 아예 모르는 것은 천지 차이라고 하지 않는가. 모든 상식들이 그렇듯 어렴풋이라도 기억해서 요긴하게 써먹을 날이 올지도 모른다.


어.. 근데 no-store, no-cache는 왜 필요할까

글을 마치려다 갑자기 그런 생각이 들었다. 캐시는 보안상 좋기도 하고 응답 지연을 해소해주는 아주 좋은 녀석이라고 알고 있다. 그런데 no-store와 no-cache라는 옵션이 있는 것을 보면 캐시를 사용하는 게 항상 좋은 것은 아닌 걸까?

앞에서 우리는 프록시에 대해 이미 배웠다. 그리고 나는 캐시도 기본적으로 프록시니까 보안 측면에서 더 좋을 것이라고 안일하게 생각했다. 하지만 얼마 지나지 않아 이 발언이 얼마나 멍청한 것인지를 깨닫게 되었다...ㅋㅋㅋㅋ 캐시는 프록시의 충분조건이지 필요조건이 아니라는 뜻이다.

프록시가 Firewall이나 Anonymizer처럼 동작한다면 트래픽을 검열한다거나 HTTP 메시지에서 식별 특성을 삭제하는 등의 조치를 취할 것이다. 그렇기 때문에 프록시가 보안상 이점이 있다는 설명이 들어가게 된 것이다. 하지만 일반적인 웹 캐시에서는 특수한 보안 조치를 기대하기는 어렵다(물론 요즘 웹 캐시들은 잘 나와서 보안 기능이 있는 것도 많다). 기껏해봐야 부하 분산에 의한 DDos 공격의 완화 정도라고 볼 수 있다. 웹 캐시는 트래픽을 암호화할 이유도 없을 뿐더러 보안보다는 빠른 리소스 제공에 더 초점을 맞추어야 하는 프록시다.

그럼 여기서 웹 캐시를 해킹하면 어떤 상황이 벌어질까?

웹 캐시가 공격을 당했을 때 노출되는 정보는 전송된 트래픽과 클라이언트의 IP 주소, 그리고 캐싱된 리소스들이다. 만약 웹 캐시로 민감한 정보가 전송되었고 심지어 저장까지 되었다면 개인정보 유출로 뉴스에 박제되는 수가 있다. 따라서 금융 정보나 로그인 세션 정보 등 민감한 정보들은 반드시 no-store 옵션을 붙여 웹 캐시에 저장되지 않도록 해야 한다. 민감 정보들이 웹 캐시에 저장되어 있지 않기만 해도 웹 캐시가 털렸을 때(?) 입는 피해는 상당히 줄어든다. 응답 시간만 쪼~금 늘어날 뿐이다.

아무튼 그런 점에서 no-cache와 no-store 옵션은 굉장히 중요하다!!

profile
맑은 눈의 다람쥐

0개의 댓글

관련 채용 정보