Cache

Why>
변경되지 않은 파일, 데이터, 값들을 다시 통신을 통해 가져올 필요가 있는가에 대한 고민으로 나온 기술이다. 자주 사용하는 데이터, 파일, 값을 미리 복사하여 사용하는 방식이다.

 

 

갱신 일자에 따른 캐시

What>
웹서버가 Last-Modified라는 헤더를 Response에 포함하여 클라이언트로 전송한다. 날짜는 RFC 1123이라는 형식으로 기술되며 Timezone은 GMT를 설정.

 

웹서버에서 보낸 헤더

Last-Modified: Web, 03 Jun 2023 15:23:45 GMT

웹 브라우저가 캐시된 URL을 다시 읽을 때는 서버에서 반환된 일시를 그대로 If-Modified-Since 헤더에 넣어서 요청

If-Modified-Since: Web, 03 Jun 2023 15:23:45 GMT

웹서버는 클라이언트의 요청을 받고 If-Modified-Since 헤더를 통해 일시를 확인한다. 만약, 웹 서버에 데이터가 변경되었다면 200 OK Status Code와 데이터를 Body에 넣어 보낸다. 그대로라면 304 Not Modified Status Code를 반환한다.

 

갱신 일자

 

 

Expires

Why>
갱신 일시를 이용하는 캐시의 경우 캐시의 유효성을 확인하기 위한 통신이 발생한다. 확인하기 위한 통신을 하지 않고, 캐시를 사용할 수 있도록 해주는 헤더

 

HTTP/1.0에 도입되었고, Expires Header를 이용하는 방법이다. Expires header에는 날짜와 시간이 들어간다. 클라이언트는 지정한 기한 내라면 캐시가 신선하다고 판단해 강제로 캐시를 이용한다. 

Expires: Web, 03 Jun 2023 15:23:45 GMT

Expires

 

 

Pragma: no-cache

Why>
요청을 보낼 때 저장된 캐시를 사용하지 않고 싶을 수도 있다. 그러기 위해서는 헤더에 저장된 캐시를 사용하지 않겠다는 것을 명시해야 한다. 이를위해 사용하는 것이 Pragma이다.

 

no-cache는 '요청한 컨텐츠가 이미 저장돼 있어도, 원래 서버에서 가져오라'고 프록시 서버에 지시하는 것이다. 참고로, no-cache는 HTTP/1.1에서 Cache-Control로 통합되었다. 

 

 

ETag 추가

Why>
날짜와 시간을 이용한 캐시 비교만으로 해결할 수 없을 때도 있다. 클라이언트마다 같은 사이트이지만, 각각 다른 화면을 동적으로 보여줘야한다면 말이다. 하지만, 동적으로 바뀌는 요소가 늘어날수록 어떤 날짜를 근거로 캐시의 유효성을 판단해야 하는지는 정말 어렵다. 따라서 하나의 수치로 귀착시키는 방법이 ETag이다.

 

RFC 2068의 HTTP/1.1에서 추가된 ETag는 순차적인 갱신 일시가 아니라 파일의 해시 값으로 비교한다. 웹서버에서 응답에 ETag 헤더를 부여한다. 클라이언트는 If-None-Match 헤더에 다운로드된 캐시에 들어있던 ETag 값을 추가해 요청한다. 서버는 보내려는 파일의 ETag와 비교해서 같으면 304 Not Modified Status Code를 반환한다. 

ETag

 

 

 

Cache-Control

Why>
보다 자세한 Cache Control을 위해 만들어졌다.

 

ETag와 같은 시기에 HTTP/1.1에서 추가된 것이 Cache-Control이다. Expires보다 우선해서 처리된다. 서버가 response로 보내는 헤더는 아래와 같다.

  • public
    • 같은 컴퓨터를 사용하는 복수의 사용자간 캐시 재사용을 허가한다. 
  • private
    • 같은 컴퓨터를 사용하는 다른 사용자 간 캐시를 재사용하지 않는다. 같은 URL에서 사용자마다 다른 콘텐츠가 들어오는 경우
  • max-age-n
    • 캐시의 신선도를 초단위로 설정한다. 86400을 지정하면 하루동안 캐시가 유효하고 서버에 요청하지 않고 캐시를 이용한다. 그 이후는 서버에 요청하고 304 Not Modified가 반환됐을 때만 캐시를 이용한다.
  • s-maxage-n
    • max-age-n과 같으나 공유 캐시에 대한 설정값이다.
  • no-cache
    • 캐시가 유효한지 매번 요청한다. max-age-0과 거의 같다.
    • Pragma: no-cache와 똑같이 캐시하지 않는 것은 아니다. 시간을 보고 서버에 접속하지 않은 채 콘텐츠를 재이용하는 것을 그만둘 뿐이다. 갱신 일자와 ETag를 사용하며, 서버가 304를 반환했을 때 이용하는 캐시는 유효하다.
  • no-store
    • 캐시하지 않는다.

위 헤더를 콤마로 구분해서 복수로 지정이 가능하지만, 내용면에서 아래와 같이 조합한다.

  • private, public 중 하나 혹은 설정하지 않는다. (default는 private)
  • max-age, s-maxge, no-cache, no-store 중 하나

cache-control

 

클라이언트 측에서 요청 헤더에 사용할 수 있는 설정 값은 아래와 같다.

  • no-cache
    • Pragma: no-cache와 같다.
  • no-store
    • 응답의 no-store와 같고, 프록시 서버에 캐시를 삭제하도록 요청
  • max-stale
    • 지정한 시간만큼 유지 기간이 지났어도 클라이언트는 지정한 시간 동안 저장된 캐시를 재사용하라고 프록시에 요청. 연장 시간은 생략할 수 있고, 그런 경우 영원히 유효하다는 의미 
  • min-fresh
    • 캐시의 수명이 지정된 시간 이상 남아있을 때, 캐시를 보내도 좋다고 프록시에 요청. 즉, 적어도 지정된 시간만큼은 신선해야한다.
  • no-transform
    • 프록시가 콘텐츠를 변형하지 않도록 요청 (게이트웨이와 같이 동작하라는 의미?)
  • only-if-cached
    • 캐시된 경우에만 응답을 반호나하고, 캐시된 콘텐츠가 없을 땐 504 Gateway Timeout status code를 반환하도록 프록시에 요청. 이 헤더가 설정되면 처음을 제외하고 오리진 서버에 전혀 액세스 하지 않음.

 

응답 헤더에서 서버가 프록시에 보내는 캐시 컨트롤 지시는 아래와 같다. 

  • no-transform
    • 프록시가 콘텐츠를 변경하는 것을 제어한다.
  • must-revalidate
    • no-cache와 비슷하지만 프록시 서버에 보내는 지시. 프록시 서버가 서버에 문의했을 때 서버의 응답이 없으면, 프록시 서버가 클라이언트에 504 Gateway Timeout이 반환되기를 기대.
  • proxy-revalidate
    • must-revalidate와 같지만, 공유 캐시에 요청

 

Vary

Why>
ETag는 같은 URL이라도 개인마다 달라지는 경우에 사용한다. 하지만, 같은 URL이라도 클라이언트에 따라 반환 결과가 달라야할 경우도 존재함. 이 경우에 사용하는 것이 Vary다.

 

예를들어, 사용자의 브라우저가 스마트폰용 일 때는 모바일용 페이지를 보여주는 등 언어에 내용이 바뀌는 경우를 들 수 있다. 이처럼 표시가 바뀌는 이유에 해당하는 헤더명을 Vary에 나열함으로써 잘못된 콘텐츠의 캐시로 사용되지 않게 합니다.

Vary: User-Agent, Accept-Language

 

로그인이 필요한 사이트라면 쿠키도 지시할 것이다.

 

Vary header는 검색 엔진용 힌트로도 사용된다. 브라우저 종류에 따라 콘텐츠가 바뀔 수 있다는 것은 모바일 버전은 다르게 보일수도 있다고 판단할 수 있는 재료가 된다. 그리고 영어 버전, 한국어 버전 등 언어별로 바르게 인덱스를 만드는 힌트도 된다.

 

모바일 브라우저인지 판정하는 방법은 User-Agent이다. 아래는 안드로이드 user-agent의 예시이다.

User-Agent: "Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36"

아래는 윈도우 user-agent의 예시이다.

User-Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246"

이처럼 User-Agent를 통해 판정할 수 있다. 서버에서는 이 정보를 바탕으로 콘텐츠를 나눠 내보낼 수 있다. 2017년 구글 가이드라인에서는 같은 콘텐츠를 모든 브라우저에 배포하고, 브라우저가 필요한 설정을 선택하는 반응형 웹 디자인을 권장한다. 

 

 

 

 

 

Reference

  • 리얼월드 HTTP : 역사와 코드로 배우는 인터넷과 웹 기술

 

 

 

+ Recent posts