[HTTP] Cache & Cache Control

dev_Hyun·2022년 12월 31일
0

Cache

캐시란

  • 클라이언트 자체에서 페이지 로드를 효율적으로 하기 위해 캐시데이터를 저장하는 시스템

Q.) 캐시는 장치인가 데이터인가? CacheData가 임시장소(장치)에 저장된 데이터 아닐까?

A1.) 웹 캐시는 장치, 캐시에 저장되는 것이 캐시데이터 이다. 따라서 예상한 것이 맞다.
A Web cache (or HTTP cache) is a system for optimizing the World Wide Web. (출처 : https://en.wikipedia.org/wiki/Web_cache)
A2.) 웹 캐시는 자주 쓰이는 문서의 사본을 자동으로 보관하는 HTTP 장치이다. (출처:HTTP완벽가이드 7장)

캐시 미적용 시

  • 같은 데이터 이더라도 요청시 마다 네트워크를 통해 데이터를 받아야 한다. (불필요 데이터 전송) → 로딩속도 저하 + 네트워크 비용 증가, 대역폭 병목 현상 발생 가능

캐시 적용 시

  • 캐시 가능 시간 동안 네트워크 사용 필요 없음 → 로딩속도 빠름 + 네트워크 비용 절감
  • 저장된 캐시의 유효 시간 초과 시, 두 가지 상황으로 나뉜다.
    1. 기존 데이터가 서버에서 변경된 경우 → 데이터 다운로드 후 캐시 갱신 필요
    2. 기존 데이터가 서버에서 변경되지 않은 경우 → 데이터 다운로드가 불필요함

클라이언트 & 서버간 의사과정

  1. 나(클라이언트) abc.html 에 접속할래
  2. 나 abc.html 캐시 있어?
  • 캐시(사본)있어!
    • 근데 캐시 유효기간은... 상했어 :(
      • 서버야 내가 가진 abc.html 캐시 검증해줘!
        • 검증 불통과 → 서버가 최신 abc.html 전송
        • 검증 통과 → abc.html 신선도 갱신
    • 근데 캐시 유효기간은... 신선해 :)
      • 캐시된 abc.html 써야지~
  • 캐시(사본)없어
    • 서버야 나 abc.html 줘!


출처:https://thisblogfor.me/web/http/cache/


# 기존데이터가 서버에서 변경되지 않은 경우에도 데이터를 다시 다운로드 받는 것은 낭비이다. 이 낭비를 제거하기 위해선 기존데이터의 변경 여부를 먼저 확인할 필요가 있다. 이때 확인하는 수단이 검증 헤더조건부 요청 헤더 이다.



Cache hit & miss

캐시에 사본 요청이 왔을 시,

  • 대응되는 사본이 있는 경우 → : cache hit(캐시 적중)
  • 사본이 없는 경우 → : cache miss(캐시 부적중)

Cache Revalidation

  • Revalidation이란, 캐시의 사본이 원서버가 제공하고자 하는 최신의 콘텐츠인지 원서버를 통해 확인하는 작업이다. 이를 '재검증' 라고 일컫는다.
  • 원하는 경우 사본의 재검증을 수행할 수 있지만, 충분히 오래된 경우에만 재검사를 수행한다.

Q.) '신선도검사'와 '재검사' 라는 두 용어는 다른 의미 아닌가?
서적에는 '이러한 신선도 검사를 http 재검사라고 부른다' 라고 되어 있는데 (https://thisblogfor.me/web/http/cache/) 해당 블로그의 순서도와 설명에는 Freshness check와 Revalidation을 구분하고 있다.

A.) 캐시 장치에서 요청받은 데이터가 최신의 것인지를 검사하는 것도, 원서버에 해당 데이터가 최신의 것인지 묻는 것도 모두 freshness를 check하는 것(신선도 검사) 임에는 변함 없는 것 같다. 다만 캐시장치가 아닌, 원서버와 소통하여 검증하는 것은 Revalidation 이라고 일컫는 것 같다.

출처 : https://docs.trafficserver.apache.org/en/latest/admin-guide/configuration/cache-basics.en.html?highlight=http%20proxy

정리하자면,

  • 캐시장치의 신선도 검사 기준 → 캐시 제어 헤더
  • 원서버에게 재검증 검사 요청 → 조건부 요청 헤더
  • 원서버의 재검증 검사 기준 → 캐시 검증 헤더

응답 속도 비교

  1. Cache hit (검증불필요+대응되는 사본이 존재)
  2. Cache Revalidation request + 304 not modified response (검증했더니 사본이 최신임) → '재검사 적중' 또는 '느린적중'이라 일컫는다.
  3. Cache miss (대응되는 사본이 존재하지 않음)
  4. Cahce Revalidation request + 200 ok (검증했더니 사본이 최신이 아님, 재검사 부적중)

Q.) 응답 속도 비교 3번과 4번 어떤게 더 빠를까..? 캐시의 신선도 검사가 필요없이 바로 원서버에 컨텐츠를 응답받는 3번이 더 빠를 것 같다고 예상한다.

A.)



검증 헤더와 조건부 요청 헤더

출처:본인

검증 헤더

특징

  • 검증헤더는 캐시데이터와 서버데이터가 같은지 검증하는 요청데이터이다.
    종류 : Last-Modified, ETag

Last-Modified: (데이터 최종 수정일)

특징

  • 검증 헤더
  • If-Modified-Since와 조합하여 사용

Last-Modified & If-Modified-Since 의 단점

  • 1초 미만 단위 캐시 조정 불가
  • 날짜 기반의 로직 사용해야 함
  • 데이터를 수정해 날짜가 다르지만, 데이터 수정 결과가 이전과 동일한 경우가 발생할 수 있음.
  • 따라서, 날짜가 아닌 데이터 자체의 수정여부를 판단하기 위해 ETag 방법이 탄생

ETag

특징

  • 캐시용 데이터에 임의의 고유한 버전이름을 지정 또는 Hash
  • ETag가 같으면 유지, 다르면 데이터 요청
  • 캐시 제어 로직을 서버에서 완전하게 관리. 클라이언트는 캐시 제어 로직을 알지 못함
  • Last-Modified와 ETag가 같이 있다면, ETag의 우선수위가 더 높다.

Q) Last-Modified와 ETag가 함께 사용된다면 어떤 것이 더 우선순위가 높은가?

A) HTTP 1.1에서는 하위 호환되므로 1.0의 header를 사용하여도 정상 동작하지만 중복으로 선언된다면 1.1에 정의된 것이 우선순위를 가지게 됩니다. 예를 들어 Last-Modified와 Etag가 동시에 있다면 Etag가 우선순위를 가집니다. (답변 출처: https://cyberx.tistory.com/9)

According to RFC 2616 – section 13.3.4, an HTTP 1.1 Client MUST use the ETag in any cache-conditional requests, and if both an ETag and Last Modified are present, it SHOULD use both.(답변 출처 : https://stackoverflow.com/questions/824152/what-takes-precedence-the-etag-or-last-modified-http-header)

The ETag header is considered a strong validator unless explicitly declared weak by the server, whereas the Last Modified header is considered weak unless at least a minute difference exists between it and the Date header.

RFC 2616 – 섹션 13.3.4에 따르면, HTTP 1.1 클라이언트는 캐시 조건 요청에서 반드시 ETag를 사용해야 하며, ETag와 Last Modified가 모두 존재할 경우 둘 다 사용해야 합니다.

ETag 헤더는 서버에 의해 명시적으로 약하다고 선언되지 않는 한 강력한 검증자로 간주되는 반면, Last Modified 헤더는 날짜 헤더와 최소 1분의 차이가 없는 한 약하다고 간주됩니다.

결론 : ETag의 우선순위가 더 높다. 둘다 존재할 경우 둘다 사용해야 한다.


Strong / Weak Validator (강한검사기 / 약한검사기)

  • 콘텐츠가 다소 변경되었더라도 중요한 의미가 변경되지 않은 경우 서버가 검증을 통과시키고 싶은 경우가 있을 수 있다. 이를 위해 HTTP/1.1은 'Weak Validator'(약한검사기)를 지원한다.
  • 단, 유의미한 변경이 있을 경우에는 반드시 강한검사를 수행해야 한다.
  • ETag
    • w/ 접두사를 붙여 약한 검사 대상임을 명시한다.
  • Last-Modified
    • 위의 Q&A에서 먼저 언급된 것과 마찬가지로, 1분 이내의 차이는 약하다고 간주된다.

Q.) Last-Modified 에서 약한 검사기를 이용하려면 어떻게 요청을 보내야 하는가?

Last-Modified: W/"<date>"

위와 같이 요청해야 하는가? MDN에는 관련내용이 없는 것 같다...

A.)


304 not modified

  • HTTP Body가 없음, 헤더 메타 정보만 응답.
  • 304를 받은 클라이언트는 응답헤더 정보로 캐시의 메타를 갱신
  • 클라이언트는 캐시에 저장된 데이터를 재활용


조건부 요청 헤더

  • 검증 헤더로 조건에 따른 분기를 서버에 요청한다.
  • 조건 만족 시 200 OK, 조건 불만족 시 304 Not Modified 응답.

if-modified-since

If-Modified-Since: <캐시 사본 마지막 수정date>

  • 조건부 요청으로, Last-Modified와 함께 사용된다.
  • 특정 시점 이후에 데이터가 수정되었는지 서버에 요청
    • 데이터 미변경 시 → 수정이 없음 → 304 Not Modified
      헤더 데이터만 전송, Body 포함하지 않음
    • 데이터 변경 시 → 수정이 있음 → 200 OK
      모든 데이터 전송, Body 포함

if-none-match

If-None-Match: <tags>

  • 조건부 요청으로, ETag와 함께 사용된다.
  • 엔터티 태그 버전이 변경되었는지 서버에 요청한다.
  • 특정 객체에 대한 여러개의 사본을 가진 경우 여러 태그버전을 포함할 수 있다.
// 예시
If-None-Match: "v3.2"
If-None-Match: "v3.2", "v3.3", "v3.4"

흐름 정리

출처:본인

캐시 제어 헤더

  • 원서버가 캐시 문서에 캐시 제어 헤더를 붙여 유효기간(신선도)을 지정할 수 있다.
  • 캐시 문서가 얼마나 오랫동안 유효(신선)한지 좌우한다.

종류

  • Cache-Control
  • Pragma
  • Expires

# 참고할 링크 : 캐시제어 응답헤더 설정 : 마이구미

Cache-Control (캐시 지시어)

  • 요청과 응답 내의 캐싱 메커니즘을 위한 디렉티브를 정하기 위해 사용된다.

# 우선순위가 높은 순으로 정리

캐시 지시어요청 / 응답 헤더비고
Cache-Control: no-store모두 가능
Cache-Control: no-cache모두 가능
Cache-Control: must-revalidate응답
Cache-Control: max-age응답

Cache-Control: max-age

  • 캐시의 유효 시간 초단위 지정.
    Cache-Control: max-age=425985

Cache-Control: no-cache

  • 데이터는 캐시해도 되지만, 캐시 사용 전 항상 Origin Server에 캐시데이터를 검증후 캐시 사용 가능. 즉, Do Not Serve From Cache Without Revalidation 이다.
  • 만약, 순간 네트워크 단절로 인해 Proxy Server 에서 Origin Server 에 접근 불가할 경우 캐시 서버 설정에 따라 오류가 아닌 오래된 데이터를 응답할 수 있음

Cache-Control: no-store

  • 민감한 데이터 정보로써 저장하면 안됨을 의미.

Cache-Control: must-revalidate

  • 캐시 만료 후, 최초 조회 시 Origin Server에 검증해야 함.
  • no-cache와 달리, must-revalidate는 Origin Server 접근 실패 시 오류가 발생해야 함 (504 Gateway Timeout) (E.g 민감한 금융 데이터)
  • 캐시 유효 시간 내 이라면 캐시를 사용함.

Pragma

Pragma: no-cache

  • HTTP/1.0 하위호환 으로 거의 사용되지 않는다. cache-control을 지원하지 않는 곳에서만 사용된다.

Expires

expires: Mon, 28 Aug 2022 00:00:00 GMT

  • 캐시 만료일 지정 가능.
  • 초단위가 훨씬 유연하기 때문에, 하위호환으로 취급됨. 따라서 Cache-Control: max-age를 권장함.
  • expires는 비권장(deprecated)헤더 이다.
    이유 → 부정확한 시간을 갖고있을 수 있기에 만료될 시각 대신 경과된 시간을 표현하는 것이 낫기 때문이다.
  • 두개가 함께 사용될 경우 Expires는 무시됨.


Proxy 프록시

  • 웹 애플리케이션의 한 종류로, 클라이언트의 모든 HTTP 요청을 받아 대게 수정하여 서버에 전달한다.
  • 보안을 위해 사용
  • 사용자 대신 프락시가 서버에 접근한다
  • 클라이언트와 서버의 중재자 역할

프록시 캐시

  • 클라이언트와 Origin Server 의 거리가 멀어, 중간에 Proxy 서버를 도입.


출처:https://velog.io/@youngs508/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%8B%AC%ED%99%94-%ED%94%84%EB%A1%9D%EC%8B%9C-%EC%BA%90%EC%8B%9CProxy-Cache

cache-control: private

  • 응답이 해당 클라이언트만을 위한 것. private 캐시에 저장
    기본값

cache-control: public

  • 응답이 public 캐시에 저장

Cache-Control: s-maxage

  • 프록시 캐시에만 적용되는 max-age

Age: 60 (HTTP 헤더)

  • 오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)


Preventing storing 캐시 무효화

  • 캐시가 되면 안되는 데이터가 분명 존재할 수 있다. (잦은 데이터 변경 E.g 통장잔고 등)
  • 이때, 확실한 캐시 무효화를 위해 아래 헤더를 모두 조합하여 사용한다.
    • Cache-Control: no-cache, no-store, must-revalidate
    • Pragma: no-cache (하위호환 까지 고려)

Q) 의미가 없는 짓이라는 MDN 문서를 확인했다. 해석하자면 이론적으로 지시어들이 중복될 경우 가장 제한적인 지시어가 적용된다. 따라서 [Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate] 를 해봤자 [Cache-Control: no-store] 와 동일하다는 내용이다. (관련링크: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#preventing_storing)
# 소름..누군가 해당 내용을 이미 질문했었다. 다음은 김영한 님이 답변하신 내용이다. (관련링크:https://www.inflearn.com/questions/112647)

A) no-store만으로 캐시가 무효화 되어야 하는 것이 맞습니다. 그런데 HTTP 스펙이라는 것이 모든 상황을 완벽하게 정의했으면 좋겠지만, 디테일하게 들어가면 모호한 부분들이 존재합니다.

예를 들어서 웹 브라우저에서 앞으로가기, 뒤로가기를 했을 때도 이것을 캐시로 볼 것인가? 이때는 no-store만 보고 판단할 것인가? no-cache를 보고 판단할 것인가? HTTP 1.1을 지원하지만 조금 오래된 브라우저와의 호환, 그리고 버그 수 많은 프록시 캐시 업체들과 그 구현 서버 등등..

이런 문제들 때문에 no-store만으로 해결하지는 못하고, 나머지 옵션들도 함께 사용하게 됩니다. 그래서 구글이나 네이버 등 주요 메이저 사이트의 응답을 보면 cache-control: no-cache, no-store, must-revalidate를 함께 가져갑니다.

결론 : no-store 만으로 캐시가 되면 안되는 데이터를 캐시무효화 되어야 하는 것이 맞다. 그러나, 앞으로가기/뒤로가기/서버문제/운영체제의 시간 수동변경 등 다양한 문제들 때문에 no-store 만으로는 해결이 안 될 수 있다.

추가 참고 링크 : https://stackoverflow.com/questions/49547/how-do-we-control-web-page-caching-across-all-browsers

How do we control web page caching, across all browsers?
Our investigations have shown us that not all browsers respect the HTTP cache directives in a uniform manner. For security reasons we do not want certain pages in our application to be cached, eve...
stackoverflow.com

profile
공룡, 다람쥐 그리고 돌고래!

0개의 댓글