KKanging

[http 완벽 가이드] 7장 캐시 본문

cs/http

[http 완벽 가이드] 7장 캐시

천방지축 개발자 2023. 8. 13. 17:54

 

이 내용은 http 완변 가이드란 책을 읽고 정리한 내용입니다.

 

더 자세한 내용이 궁금하시면 책을 직접 읽어보시는 걸 추천합니다.

 

 

 

7장 캐시

  • 웹 캐시는 자주 쓰이는 문서의 사본을 자동으로 보관하는 HTTP 장치이다.

1. 불필요한 데이터 전송

  • 복수의 클라이언트가 자주 쓰이는 원 서버 페이지에 접근할 때, 서버는 같은 문서를 클라이언트에게 각각 한 번씩 전송하게 된다.
  • 이러한 반복적인 수행은 네트워크 대역폭을 잡아먹고 전송을 느리게 하며 웹 서버에 부하를 준다.
  • 캐시를 이용하면, 첫 번째 서버 응답은 캐시에 보관한다.
  • 캐시된 사본이 뒤이은 요청들에 대한 응답으로 사용 될 수 있기 때문에, 원 서버가 중복해서 트래픽을 주고 받는 낭비가 줄어들게 한다.

2. 대역폭 병목

  • 캐시는 또한 네트워크 병목을 줄여준다.
  • 만약 클라이언트가 빠른 LAN에 있는 캐시로부터 사본을 가져온다면, 캐싱은 성능을 대폭 개선할 수 있을 것이다.

3. 갑작스런 요청 쇄도

  • 캐싱은 갑작스런 요청 쇄도에 대처하기 위해 특히 중요하다.

4. 거리로 인한 지연

  • 비록 대역폭이 문제가 되지 않더라고, 거리가 문제가 될 수 있다.
  • 기계실 근처에 캐시를 설치해서 문서가 전송되는 거리를 수천 킬로미터에서 수십 미터로 줄일 수 있다.

5. 적중과 부적중

  • 이와 같은 캐시는 유용하나, 세상 모든 문서의 사본을 저장하지는 못한다.
  • 그래서 2가지 형태의 상태가 나타난다.
    • 캐시 적중
    • 캐시 부적중
  • 캐시적중 : 캐시에 요청이 도착했을 때, 만약 그에 대응하는 사본이 있다면 그를 이용해 요청이 처리되는 것
  • 캐시 부적중: 만약 대응하는 사본이 없다면 그냥 원 서버로 전달되기만 할 뿐인 상태

5.1 재검사

  • 원 서버의 컨텐츠는 변경되기 때문에, 캐시는 반드시 그들이 갖고 있는 사본이 여전히 최신인지 서버를 통해 때때로 점검해야 한다.
  • → 이를 신선도 검사를 HTTP 재검사라고 부른다.
  • 무작정 재검사를 하지는 않고 가지고 있는 사본이 오래된 경우만 재검사를 한다.
  • 재검사 요청을 서버에 보내고 만약 여전히 신선하다면 서버는 304 상태코드의 응답을 보낸다.
  • 캐시가 신선하다고 확신이 들면 클라이언트에게 제공한다.
    • 이를 재검사 적중 혹은 느린 적중이라 한다.
  • 느린 적중은 순수 캐시 적중보다는 느리지만, 서버로부터 객체 데이터를 받아 올 필요가 없기에 캐시 부적중 보다는 빠르다.
  • 캐시가 재검사를 하기 위해 GET 요청에 IF-Modeified-Since 헤더를 붙인다.
  • 이 요청이 서버에 도착하면 일어날 수 있는 경우는 3가지이다.
    1. 서버 콘텐츠가 변경하지 않을 경우: 304를 캐시한테 보낸다.
    2. 서버 콘텐츠가 변경된 경우: 200 oK를 클라이언트에게 보ㅐㄴ다.
    3. 객체가 삭제된 경우: 404에러를 보내며 캐시는 사본을 삭제한다.

5.2 적중률

  • 캐시가 요청을 처리하는 비율을 캐시 적중률, 혹은 문서 적중률이라고 부르기도 한다.
  • 흔히 퍼센트로 표현한다.
  • 캐시는 유용한 콘텐츠가 캐시 안에 머무르도록 보장하기 위해 노력해야한다.

5.3 바이트 적중률

  • 바이트 단위 적중률은 캐시를 통해 제공된 모든 바이트의 비율을 표현한다.
    • 이 측정값은 트래픽이 절감된 정도를 포학해낸다.
  • 문서 적중률과 바이트 단위 적중률은 둘 다 캐시 성능에 대한 유용한 지표다.
    • 문서 적중률은 얼마나 많은 웹 트랜잭션을 외부로 내보내지 않았는지를 보여줌

5.4 적중과 부적중의 구별

  • 클라이언트는 캐시가 적중했는지 부적중했는지 알 수 없다.
    • 이유는 둘다 200 OK가 보이기 때문
  • 구별을 가능하게 할려면 Date ,Age헤더를 통해 응답이 만들어진 날짜를 본다.
    • 이유는 캐시는 응답 메시지까지 만들어진걸 보관하기 때문에 옛날에 만들어진거면 적중했을 가능성이 높다.
  • Via 헤더를 쓴다.

6. 캐시 토폴로지

  • 한 명에게만 할당된 캐시를 개인 전용 캐시라고 부른다.
    • 개인을 위한 캐시로 개인이 많이 찾는 페이지 같은 것을 담는다.
  • 공유된 캐시는 공유 캐시라고 불린다.
    • 공용 캐시는 사용자 집단에게 자주 쓰이는 페이지를 담는다.

6.1 개인 전용 캐시

  • 개인 전용 캐시는 많은 에너지나 저장 공간을 필요로 하지 않으므로 작고 저렴할 수 있다.
  • 웹 브라우저는 개인 전용 캐시를 내장하고 있다.
    • 대부분 자주 쓰이는 문서를 개인용 컴퓨터의 디스크와 메모리에 캐시해 놓는다.
  • 수동으로 설정할 수도 브라우저를 통해 어떤 캐시가 있는지 볼 수 있다.

6.2 공용 프락시 캐시

  • 공용 캐시는 캐시 프락시 서버 혹은 더 흔히 프락시 캐시라고 불리는 프락시 서버이다.
  • 프락시 캐시는 로컬 캐시에서 문서를 제공하거나, 혹은 사용자의 입장에서 서버에 접근한다.
    • 이는 불필요한 트래픽을 감소한다.
  • 공용 캐시는 자주 찾는 객체를 단 한번만 가져와 모든 요청에 대해 공유된 사본을 제공함으로써 네트워크 트래픽을 줄인다.

6.3 프락시 캐시 계층들

  • 보통 작은 캐시에서 부적중이 발생했을 때 더 큰 부모 캐시가 그 걸러 남겨진 트래픽을 처리하도록 하는 계층을 만드는 방식이 합리적인 경우가 많다.
  • 만약 작은 1단계 캐시가 트래픽을 처리하지 못했다면 더 큰 다음 단계 캐시가 처리할 수 있을 것이다.
  • 캐시 계층이 깊다면 요청은 캐시의 긴연쇄를 따라가게 될 것이며, 길어질수록 각 중간 프락시는 현저한 성능 저하가 발생할 것이다.

6.4 캐시망, 컨탠츠 라우팅, 피어링

  • 몇몇 네트워크 아키텍처는 단순한 캐시 계층 대신 복잡한 캐시망을 만든다.
  • 이는 동적으로 부모 캐시에 라우팅할 것인지 또는 원서버로 가도록 할 것인지에 대한 결정을 내린다.

캐시망 안에서의 콘텐츠 라우팅을 위해 설계된 캐시들은 다음에 나열된 일들을 모두 할 수 있을 것이다.

  • URL에 근거하여, 부모 캐시와 원 서버 중 하나를 동적으로 선택한다.
  • URL에 근거하여 특정 부모 캐시를 동적으로 선택한다.
  • 부모 캐시에게 가기 전에, 캐시된 사본을 로컬에서 찾아본다.
  • 다른 캐시들이 그들의 캐시된 콘텐츠에 부분적으로 접근할 수 있도록 허용하되,그들의 캐시를 통한 인터넷 트랜짓(Internet transit)9은 허용하지 않는다.

7. 캐시 처리 단계

  • 캐시 처리 단계는 다음과 같이 이루어진다.
  1. 단계 1: 요청 받기
    • 들어오는 데이터를 읽어들이는 단계
  2. 단계 2: 파싱
    • 요청 메시지의 여러 부분으로 파싱하여 헤더 부분을 조작하기 쉬운 자료구조에 담는다.
    • 이는 캐싱 소프트웨어가 헤더 필드를 처리하고 조작하기 쉽게 해준다.
  3. 단계 3: 검색
    • 캐시는 요청 메시지에 있는 URL에 해당하는 로컬 사본이 있는지 검사한다.
    • 만약 가져 올 수 없다면, 원서버나 부모 캐시 라우팅 또는 실패를 반환할 것이다.
  4. 단계 4: 신선도 검사
    • 만약 가지고 있는 사본이 오래되었다면 신선도 검사를 해야한다.
  5. 단계 5: 응답 생성
    • 캐시는 응답을 생성하는데 클라이언트에 맞게 헤더를 조정해야하는 책임이 있다.
    • 프로토컬 버전을 맞춘다는지
    • 신선도 정보를 헤더에 삽입하거나
    • 캐시를 거쳐 갔음을 알리는 Via 헤더를 포함한다.
    • 하지만 Date헤더는 건드리면 안된다. 이는 캐시의 사본이라는 증거이기 때문
  6. 단계 6: 전송
  7. 단계7: 로깅

캐시처리 플로 차트

8. 사본을 신선하게 유지하기

  • 캐시된 사본은 항상 원서버의 사본과 일치하는 것이 아니다.
  • 주식시장, 온라인 신문등만 봐도 짧은 시간에 빠르게 사본이 바뀌는 사례가 많다.
  • 어떤 캐시가 사본은 갖고 있는지 서버가 기억하지 않더라도, 캐시된 사본이 서버와 충분히 일치하도록 유지할 수 있게 해주는 단순한 메커니즘을 갖고있다.
    • 문서 만료
    • 서버 재검사

8.1 문서 만료

  • 특별한 헤더를 이용해서 원 서버가 각 문서에 유효기간을 붙일 수 있다.
  • 이 유효기간이 만료되면 캐시는 반드시 재검사를 해야 한다.

8.2 유효기간과 나이

  • 서버는 응답 본문과 함께 하는, HTTP/1.0+ Expires나 HTTP/1.1 Cache-Control: max-age 응답 헤더를 이용해서 유효기간을 명시한다.
  • Expires와 Cache-Control: max-age 헤더는 기본적으로 같은 일을 하지만, 절대 시간은 컴퓨터의 시계가 올바 르게 맞추어져 있을 것을 요구한다.

8.3 서버 재검사

  • 캐시된 문서가 만료되었다는 것은, 그 문서가 원서버의 문서와 다르다는 것을 시사하지는 않는다.
  • 하지만 이제 검사할 시간이 되었음을 뜻한다.
  • 변경되었는지 물어보는것을 서버 재검사라 부른다.
    • 변경되었다면 새로운 사본을 가져와 오래된 데이터 대신 저장한 뒤 클라이언트에게도 보내준다.
    • 재검사 결과 콘텐츠가 변경되지 않았다면, 캐시는 새 만료일을 포함한 새 헤더들만 가져와서 캐시 안의 헤더들을 갱신한다.

8.4 조건부 메서드와의 재검사

  • 캐시는 재검사 요청을 서버에게 보낼때 GET 요청과 함께 If-Modified-Since와 If_None-Match같은 헤더를 포함해서 보낸다.
  • 이는 문서가 갖고있는 것 과 다를 때만 객체를 보내라는 의미이다.

8.5 If-Modified-Since : 날짜 재검사

  • 흔히 쓰이는 재검사 헤더로써
  • 재검사 요청은 흔히 ‘IMS’ 요청으로 불린다.
  • IMS 요청은 서버에게 리소스가 특정 날짜 이후로 변경된 경우에만 요청한 본문을 보내달라고 한다.
  • 만약 문서가 주어진 날짜 이후에 변경되었다면, If-Modified-Since 조건은 참이고, 따라서 GET 요청은 평범하게 성공한다.새 문서가, 새로운 만료 날짜와 그 외 다른 정보들이 담긴 헤더들과 함께 캐시에게 반환된다.
  • 만약 문서가 주어진 날짜 이후에 변경되지 않았다면 조건은 거짓이고, 서버는 작은 304 Not Modified 응답 메시지를 클라이언트에게 돌려준다. 효율을 위해 본문은 보내지 않는다.응답은 헤더들을 포함하지만, 원래 돌려줘야 할 것에서 갱신이 필요한 것만을 보내준다.예를 들어, Content-Type 헤더는 잘 변하지 않기 때 문에 대개 보내줄 필요가 없고, 새 만료 날짜는 보통 보내주게 된다.If-Modified-Since 헤더는 서버 응답 헤더의 Last-Modified 헤더와 함께 동작한다.

원 서버는 제공하는 문서에 최근 변경 일시를 붙인다. 캐시가 캐시된 문서를 재검사 하려고 할 때, 캐시된 사본이 마지막으로 수정된 날짜가 담긴 If-Modified-Since 헤더를 포함한다.

8.6 If-None-Match: 엔터티 태그 재검사

  • 다음과같이 최근 변경 일시 재검사가 적절히 행해지기 어려운 상황이 몇 가지 있다.
  • 어떤 문서는 일정 시간 간격으로 다시 쓰여지지만(예를 들면 백그라운드 프로세 스에 의해) 실제로는 같은 데이터를 포함하고 있다. 내용에는 아무런 변화가 없 더라도 변경시각은 바뀔 수 있다.
  • 어떤 문서들의 변경은 전 세계의 캐시들이 그 데이터를 다시 읽어들이기엔 사소 한 것일 수도 있다. (예: 철자나 주석의 변경)
  • 어떤 서버들은 그들이 갖고 있는 페이지에 대한 최근 변경 일시를 정확하게 판별 할수 없다.
  • 1초보다 작은 간격으로 갱신되는 문서를 제공하는 서버들에게는, 변경일에 대한 1초의 정밀도는 충분하지 않을 수 있다.

8.7 약한 검사기와 강한 검사기

  • 약한 검사기는 : 약간의 변경을 허용
  • 강한 검사기는 : 약간의 변경도 허용하지 않음

8.8언제 엔터티 태그를 사용하고 언제 Last-Modified 일시를 사용하는가

  • HTTP/1.1 클라이언트는 만약 서버가 엔터티 태그를 반환했다면, 반드시 엔터티 태그 검사기를 사용해야 한다. 만약 서버가 Last-Modified 값만을 반환했다면, 클라이언트는 If-Modified-Since 검사를 사용할 수 있다.
  • 만약 엔터티 태그와 최근 변경 일시가 모두 사용 가능하다면, HTTP/1.0과 HTTP/1.1 캐시 모두 적절히 응답할 수 있도록 클라이언트는 각각을 위해 두 가지의 재검사 정책을 모두 사용해야 한다.
  • HTTP/1.1 원 서버는 실현 불가능하지만 않다면 엔터티 태그 검사기를 보내야 하며, 이점이 있다면 강한 엔터티 태그 대신 약한 엔터티 태그를 보낼 수도 있다.
  • 또한 Last-Modified 값을 같이 보내는 것도 선호된다.
  • 만약 HTTP/1.1 캐시나 서버가 If-Modified-Since 엔터티 태그 조건부 헤더를 모두 받았다면, 요청의 모든 조건부 헤더 필드의 조건에 부합되지 않는 한 304 Not Modified 응답을 반환해서는 안 된다.

캐시 제어

HTTP는 문서가 만료되기 전까지 얼마나 오랫동안 캐시될 수 있게 할 것인지 서버

가 설정할 수 있는 여러 가지 방법을 정의한다. 우선순위대로 나열해보면 서버는,

  • Cache-Control: no-store 헤더를 응답에 첨부할 수 있다.
  • Cache-Control: no-cache 헤더를 응답에 첨부할 수 있다.
  • Cache-Control: must-revalidate 헤더를 응답에 첨부할 수 있다.
  • Cache-Control: max-age 헤더를 응답에 첨부할 수 있다.
  • Expires 날짜 헤더를 응답에 첨부할 수 있다.
  • 아무 만료 정보도 주지 않고, 캐시가 스스로 체험적인(휴리스틱) 방법으로 결정하게 할 수 있다.

no-cache와 no-store 응답 헤더

HTTP/1.1은 신선도를 관리하기 위해, 객체를 캐시하는 것을 제한하거나 캐시된 객체를 제공하는 여러 가지 방법을 제공한다.

no-store와 no-cache 헤더는 캐시가 검 증되지 않은 캐시된 객체로 응답하는 것을 막는다.

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

‘no-store’가 표시된 응답은 캐시가 그 응답의 사본을 만드는 것을 금지한다. 캐시 는 보통, 캐시가 아닌 프락시 서버가 그러는 것처럼, 클라이언트에게 no-store 응답 을 전달하고 나면 객체를 삭제할 것이다.

Max-Age 응답 헤더

Cache-Control: max-age 헤더는 신선하다고 간주되었던 문서가 서버로부터 온 이 후로 흐른 시간이고, 초로 나타낸다. 또한 s-maxage 헤더는(‘maxage’에 하이픈이 없음에 주의하라) max-age처 럼 행동하지만 공유된(공용) 캐시에만 적용된다.

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

서버는 최대 나이먹음(maximum aging)을 0으로 설정함으로써, 캐시가 매 접근마 다 문서를 캐시하거나 리프레시하지 않도록 요청할 수 있다.

Expires 응답 헤더

더 이상 사용하지 않기를 권하는(deprecated) Expires 헤더는 초 단위의 시간 대신 실제 만료 날짜를 명시한다.

HTTP를 설계한 사람들은, 많은 서버가 동기화되어 있 지 않거나 부정확한 시계를 갖고 있기 때문에, 만료를 절대시각 대신 경과된 시간 으로 표현하는 것이 낫다고 판단했다.

신선도 수명의 근사값은 만료일과 생성일의 초 단위 시간차를 계산하여 얻을 수 있다.

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

몇몇 서버는 문서를 항상 만료되도록 하기 위해 Expires: 0 응답 헤더를 돌려보내지 만,

이는 문법 위반이며 몇몇 소프트웨어와 문제를 일으킬 수 있다. 이런 값들을 가 급적 받아들일 수는 있어야 하나, 생성해서는 안 된다.

클라이언트 신선도 제약

웹브라우저는 브라우저나 프락시 캐시의 신선하지 않은 콘텐츠를 강제로 갱신시켜 주는 리프레시나 리로드 버튼을 갖고 있다.

이 리프레시 버튼은 Cache-control 요청 헤더가 추가된 GET 요청을 발생시켜서, 강제로 재검사하거나 서버로부터 콘텐츠를 무조건 가져온다.

정확한 리프레시 동작은 각 브라우저나 문서, 중간 캐시 설정에 달려있다.

클라이언트는 Cache-Control 요청 헤더를 사용하여 만료 제약을 엄격하게 하거나 느슨하게 할 수 있다.

클라이언트는 문서를 최신으로 유지할 필요가 있는 애플 리케이션(수동 리프레시 버튼과 같은)을 위해 Cache-Control 헤더를 사용해 만료 를 더 엄격하게 할 수 있다.

한편, 클라이언트 역시 성능, 신뢰성, 비용 개선을 위 한 절충안으로 신선도 요구사항을 느슨하게 하고자 할 수도 있다. 표 7-4는 Cache- Control 요청 지시어를 요약한 것이다.