kakasoo

[HTTP] 17. 캐시(2) 본문

프로그래밍/HTTP

[HTTP] 17. 캐시(2)

카카수(kakasoo) 2020. 12. 6. 18:37
반응형

7.7 캐시 처리 단계

HTTP GET 메시지를 하나 보내면 캐시 처리는 일곱 가지 절차에 따라 이루어진다.

  1. 요청 받기 : 캐시는 요청 메시지를 읽는다.
  2. 파싱 : 캐시는 메시지를 파싱하여 URL과 헤더들을 추출한다.
  3. 검색 : 캐시는 로컬 복사본이 있는지 검사하고, 사본이 없다면 사본을 받아온다.
  4. 신선도 검사 : 캐시된 사본을 찾았다면 최신의 것이 맞는지 검사한다. 아니라면 서버로부터 변경사항을 확인한다.
  5. 응답 생성 : 응답을 생성한다.
  6. 발송 : 클라이언트에게 응답을 돌려준다.
  7. 로깅 : 선택적으로 로그 파일에 트랜잭션을 서술한 로그를 남긴다.

7.7.1 단계 1 : 요청 받기

캐시는 네트워크 커넥션에서의 활동을 감지, 데이터를 읽는다. 고성능 캐시는 동시에 여러 커넥션으로부터 데이터를 읽고 메시지 전체가 도착하기 전에 트랜잭션을 처리한다.

7.7.2 단계 2 : 파싱

캐시는 요청 메시지를 여러 부분으로 파싱하여 헤더 부분을 조작하기 쉬운 자료구조에 담는다. 상대 URL 참고.

7.7.3 단계 3 : 검색

캐시는 URL을 알아내고 로컬 사본이 있는지 알아낸다. 복사본은 메모리, 디스크, 심지어 다른 컴퓨터에 있을 수도 있다. 전문적인 수준의 캐시는 고도의 알고리즘을 사용한다.

만약 문서를 로컬에서 가져올 수 없으면 부모 프락시나 원 서버로부터 가져오고, 또는 실패를 반환한다.

캐시된 객체는 서버 응답 본문과 원 서버 응답 헤더를 포함하고 있으므로 캐시 적중 동안에 올바른 서버 헤더가 반환될 수 있다.

또한 캐시된 객체가 얼마나 오랫동안 캐시에 머무르고 있었는지, 얼마나 자주 사용됐는지에 관한 메타 데이터를 포함시키기도 한다.

7.7.4 단계 4 : 신선도 검사

HTTP는 캐시가 일정 기간 동안 서버 문서의 사본을 보유할 수 있도록 해준다. 이 때 일정기간을 정하는 것은 신선도 계산에서 이루어진다. 해당 내용은 후술한다.

7.7.5 단계 5 : 응답 생성

캐시가 원 서버에서 온 것처럼 보일 수 있게 캐시는 캐시된 응답 헤더를 토대로 새 응답 헤더를 생성한다. 이 때 헤더는 수정되고 늘어나기도 한다.

캐시는 클라이언트가 요구한 것에 맞게 서버 응답을 수정할 필요가 있다. 예컨대 클라이언트가 HTTP/1.1을 원한다면, 서버가 1.0을 보냈더라도 캐시 차원에서 수정해주어야 한다.

7.7.6 단계 6 : 전송

응답을 돌려준다. 프락시 캐시 역시 클라이언트와 커넥션을 유지해야 한다. 고성능 캐시는 로컬 저장장치와 네트워크 I/O 버퍼 사이에서 콘텐츠 복사를 피해 효율을 높인다.

7.7.7 단계 7 : 로깅

캐시는 로그 파일과 캐시 사용에 대한 통계를 유지하곤 한다. 따라서 통계를 지닌 캐시라면, 전송 이후 로그를 반영해 통계를 수정해야 한다.

7.8 사본을 신선하게 유지하기

오래된 데이터를 제공하는 캐시는 불필요하다. 예컨대 금융 자료는 매 초마다 변경이 되기 때문에 항상 최신의 정보를 가져와야 한다.

7.8.1 문서 만료

HTTP는 Cache-Control과 Expires라는 특별한 헤더들을 이용해서 원 서버가 각 문서에 유효 기간을 붙일 수 있게 해준다. 이는 유통기간과 비슷한 개념이다.

캐시는 이를 토대로 서버와 접촉 없이 사본을 제공할 수 있다. 만료된 데이터가 있다면 캐시는 서버에 변경 사항을 확인하고 사본과 새로운 유효기간을 가져와야 한다.

7.8.2 유효기간과 나이

Expires는 절대 시간이다. 그래서 컴퓨터의 절대 시간이 바르게 맞춰져 있을 것을 요구한다. 그렇기에 새로 생겨난 것이 Cache-Control이다. 이는 상대시간을 초(seconds)로 받는다.

7.8.3 서버 재검사

캐시된 문서가 만료되었다면 서버에 확인 요청을 보낸다. 이를 서버 재검사라고 한다. 검사 이후 캐시는 아래의 결과를 돌려줘야 한다.

  • 충분히 신선한, 캐시된 사본 (서버로부터 새로 받아온 경우)
  • 원 서버와 재검사 되었기 때문에 충분히 신선하다고 확신할 수 있는 캐시된 사본 (변경사항이 없음을 확인한 경우)
  • 에러 메시지 (서버가 다운된 경우)
    • 서버가 죽은 경우, 캐시에는 데이터가 남아 있더라도 에러를 보내는 것이 옳다.
  • 경고 메시지가 부착된 캐시된 사본 (부정확한 경우)

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

HTTP 조건부 메서드는 재검사를 효율적으로 만들어준다. HTTP는 캐시가 서버에게 '조건부 GET' 이라는 요청을 보낼 수 있도록 한다.

이는 캐시가 가지고 있는 사본이 서버의 것과 다른 경우에만 데이터를 보내달라는 요청이다.

HTTP에서는 5가지의 조건부 요청 헤더를 정의하고 있는데, 그 중 둘은 캐시 재검사를 위한 If-Modified-Since와 If-None-Match다.

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

IMS 요청이라고도 한다. IMS 요청은 특정 날짜 이후로 변경된 경우에만 요청한 본문을 보내달라고 한다. 변경이 없는 경우, 변경이 필요한 헤더들만 수정하여 보내준다.

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

IMS에는 몇 가지 문제가 있다.

  • 변경점이 없어도, 백 그라운드 프로세스에 의해서 변경 시각이 계속 바뀌는 데이터가 있을 경우
  • 어떤 문서의 변경이 철자나 주석 등의 사소한 변경이라, 전체 문서를 가져오는 것이 리소스 낭비로 이어질 경우
  • 최근 변경 일시를 정확하게 파악할 수 없는 경우
  • 1초보다 작은 간격으로 갱신되는 문서는, 1초마다 확인하는 것으로도 충분하지 않을 수 있다.

이런 경우에는 문서에 일종의 버전이나 넘버링을 붙여서, 해당 번호가 아닌 경우에만 돌려달라고 요청할 수 있다.

7.8.7 약한 검사기와 강한 검사기

서버는 때때로 조금의 변경 정도는 그 정도면 같은 것 이라고 말할 수 있게 약한 검사기를 지원한다. 강한 검사기는 콘텐츠가 바뀔 때마다 바뀐다.

하지만 약한 검사기는 콘텐츠의 변경을 허용하며, 콘텐츠의 중요한 정보가 바뀔 때에만 함께 변경된다.

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

둘 다 사용해야 한다. 둘 다 동시에 사용하는 것이 가장 좋다.

7.9 캐시 제어

아래는, 서버가 캐시에게 줄 수 있는 얼마나 오랫동안 유지할 것인지에 대한 기준을 우선 순위에 따라 나열한 것이다.

  • Cache-Control : no-store
  • Cache-Control : no-cache
  • Cache-Control : must-revalidate
  • Cache-Control : max-age
  • Expires 날자 헤더
  • 아무런 정보도 주지 않고 캐시 스스로가 판단하게 한다.

7.9.1 no-cache와 no-store 응답 헤더

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

no-store의 경우에는 캐시가 사본을 저장하는 것 자체를 막고, no-cache의 경우에는 무조건 서버와 재검사를 하게 하는 것이다.

7.9.2 Max-Age 응답 헤더

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

7.9.3 Expires 응답 헤더

앞서 설명한 헤더. 더는 사용을 권하지 않는다. 컴퓨터마다의 시간이 다를 수 있어 정확하지 않기 때문이다.

7.9.4 Must-Revalidate 응답 헤더

캐시가 신선하지 않은 데이터를 임의로 제공하는 것을 원천적으로 금지한다.

7.9.5 휴리스틱 만료

만약 어떤 헤더도 포함되지 않았다면 캐시는 경험적인 방법 (Heuristic) 으로 최대 나이를 계산할 것이다. 어떤 알고리즘이든지 사용될 수 있다.

다만 결과 값이 24시간보다 큰 경우에는 Heuristic Expiration 경고 헤더가 응답 헤더에 추가되어야 한다.

반응형