Network

HTTP The Definitive Guide - 07. Caching

깡구_ 2022. 11. 22. 22:33

title: HTTP The Definitive Guide - 07. Caching
date: 2022-11-22
tags:

  • Network
  • HTTP



Introduction

HTTP The Definitive Guide




GDSC에서 해당 서적을 통해 HTTP를 공부하는 스터디에 참가하고 있다.
HTTP 이전의 내용은 개인적으로 공부하며 채울 예정이다.
이번 Chapter는 07장 Caching 이다.


Purpose

Web Caching에 대해 학습한다.


Redundant Data Transfers

여러 Client가 Google과 같은 자주 사용되는 Server에 Access할 때, Server는 같은 Resource를 계속하여 Response한다.
이러한 불필요한 중복 데이터 전달을 해결하기 위해 Cache를 이용한다.
Cache가 존재한다면 Server까지 갈 필요 없이 바로 Resource를 받을 수 있기에 성능 향상, Network 병목 감소 등 이점이 많다.

Bandwidth Bottlenecks

Limited Bandwidth

일반적으로 Local Network의 대역폭은 Remote Server보다 훨씬 빠르다. Cache가 없다면 느린 Network를 통해 Resource를 가져온다.
Cache를 이용하면 Remote Server의 이용률이 낮아지기에 효율적으로 Network를 이용할 수 있다.
위 그림에서 5MB의 Resource를 가져올 때, Cache가 없다면 약 30초가 걸리지만 Cache를 이용하면 1초 이내에 Resource를 가져올 수 있다.

Bandwidth Table

Network에서 다른 Traffic이 존재하지 않을 때의 가장 빠른 Resource 전송 속도이다.
실제 Network에서는 많은 Traffic이 존재하며, 이에 따라 위의 표보다 더 긴 시간이 걸린다.
과거의 자료이기에 현재는 속도가 더 빠르겠지만, 국내의 속도는 매우 빨라진 반면 국외의 속도는 여전히 느리다고 느낄 수준이다.

Flash Crowds

Network는 언제나 비슷한 Traffic으로 유지되지 않는다.
속보, 이벤트 등으로 인하여 급격하게 많은 Traffic이 생길 수 있다.
과거 Starr Report가 공개되었을 때 평균 부하의 50배인 시간당 3M의 Request가 발생하였으며, CNN은 초당 50K의 Request를 받았다고 한다.

Distance Delays

대역폭만 문제가 되는 것이 아니다. 지리학적 거리 또한 큰 문제가 된다.
보스턴에서 샌프란시스코까지 약 2700Mile이며, 빛의 속도로 이동하여도 15ms가 소요된다. 물론 신호는 이보다 느리다.
20개의 작은 사진을 가져온다고 할 때, Parallel Connection을 이용하더라도 약 240ms가 소요되며, 약 6700Mile 떨어진 도쿄일 경우 600ms까지 소요된다.
기술의 발전으로 Resource의 크기는 평균적으로 더 커졌으며, 지리학적으로 근처에 Cache가 없더라면 서비스 이용이 어려울 정도로 긴 시간이 소요될 것이다.

Hits and Misses

Cache가 모든 Resource를 저장할 수 있는 것은 아니다.
모든 Resource를 저장할 수 있는 Cache는 거의 존재하지 않으며, 일부 Resource는 자주 변하기에 이러한 Resource를 저장하는 것은 낭비일 수 있다.
Request시 Cache를 먼저 확인한 후, Cache Hit라면 Cache에 존재하는 Resource를 넘겨주며, Cache Miss라면 Server에서 Resource를 가져온다.

Revalidation

Cache로 가지고 있는 Resource는 언제나 최신의 Resource는 아니다.
하나의 Server에 여러 Client가 Request를 보내며, 이에 따라 Cache에 있는 Resource가 Server에서만 갱신될 수 있다.
그렇기에 특정 기준을 충족하지 못하면 Cache의 Resource가 최신 Resource인지 확인하는 작업이 필요하다.
이때 Server에 가지고 있는 Resource가 최신의 Resource인지 확인하며, Status Code 304 Not Modified Response를 받지 못한다면 최신의 Resource가 아니기에 Cache Miss가 발생한다고 볼 수 있다.
이러한 과정을 통해 Cache Hit가 발생할 경우, 이를 Revalidate Hit 혹은 Slow Hit라 한다.
Cache Hit보다는 느리지만, Resource를 가져오는 일은 없기에 여전히 빠르다.

일반적으로 Revalidation을 위해 GET Method와 If-Modified-Since Header를 이용한다.
최신의 Resource로 Revalidation Hit라면 Status Code 304, 최신의 Resource가 아니라면 Status Code 200과 최신 Resource를 Response한다.
해당 Resource가 삭제되었을 경우 Status 404 Not Found를 통해 Resource가 삭제되었음을 알리며, Cache는 해당 Resource를 삭제한다.

Hit Rate

Cache Hit 비율을 확인하기 위해 0~1 범위의 Hit Rate (Document Hit Rate)가 존재한다.
Revalidation Hit와는 별개로 취급하기에, Hit Rate는 Revalidation 과정 없이 Cache Hit의 경우만 count한다.
100%가 Best이나, Cache의 크기와 유저가 Request하는 Resource는 일정하지 않기에 일반적으로 40%의 Hit Rate를 괜찮은 비율로 인식한다.

Byte Hit Rate

Resource의 크기가 모두 다르기에 Hit Rate만으로는 Cache의 효율을 판단하기 어렵다.
크기가 매우 큰 Resource가 Hit를 많이 한다면 Traffic을 많이 줄여주며, 크기가 매우 작은 Resource가 Hit를 많이 하여도 Traffic에는 큰 영향을 주지 않을 것이다.
이 때문에 Resource를 기준으로 하는 Hit Rate와 별개로 Byte를 기준으로 하는 Byte Hit Rate가 존재한다.
전체적인 Hit Rate가 높다면 유저가 특정 Resource를 자주 Request하는 것이며, Byte Hit Rate가 높다면 Cache 덕분에 많은 Traffic을 줄이는 것이다.
Byte Hit Rate를 높이는 것은 대역폭을 효율적으로 사용하는 측면에서의 최적화라고 볼 수 있다.

Distinguishing Hit and Miss

Cache와 관련된 동작은 Client가 알지 못한다.
Date Header와 Age Header를 이용하면 Client는 Cache Hit가 발생했는지 알 수 있다.

Cache Topologies

Cache는 특정 유저만 사용할 수 있는 Private Cache와 많은 유저가 함께 사용할 수 있는 Public Cache로 나뉜다.

Private and Public Cache

Private Cache는 Web Browser를 사용하는 거의 모든 유저가 이용하고 있다.
각 PC에서 사용하는 Browser의 Cache는 PC의 Memory나 Disk에 존재한다.

Public Cache는 이전 Chapter에서 배운 Proxy Cache이다.
Private Cache에서 Cache Hit가 발생하지 않으면 Public Cache를 확인한다.
Public Cache가 없다면 많은 유저가 같은 Resource를 이용하더라도 Server로 많은 Request를 보내 과한 Traffic이 발생할 것이다.
Public Cache덕분에 이러한 문제를 해결할 수 있다.
Chapter 06에서 배웠듯이 유저가 직접 Browser의 설정을 변경하여 Proxy를 명시할 수도 있으며, Intercepting Proxy가 알아서 처리할 수도 있다.

Cache Hierarchy

Cache Hierarchy

Request를 통해 Resource를 가져오기까지 하나의 Cache만 이용하는 것이 아니다.
작고 싼 Cache를 Private Cache로, 크고 비싼 Cache를 Proxy Cache로 이용하여 Hit Rate를 높임으로써 Network를 효율적으로 이용할 수 있다.
이는 OS에서의 Memory Hierarchy와 비슷하다고 볼 수 있다.
위 그림에서는 Level 2밖에 나와있지 않으나, 일반적으로 각 Browser는 Cache를 가지고 있기에 Level 3라고 볼 수 있다.
Proxy Cache를 이용하는 과정에서 Overhead가 발생할 수 있으며, 매우 많은 Proxy Cache를 거치게 되면 이러한 Overhead로 인하여 더 느려질 수도 있다.
과거의 Network Architecture는 이러한 문제로 인하여 2-3개의 Proxy로 제한하였으나, 기술이 발전함에 따라 더 많은 Proxy를 더 빠르게 이용할 수 있다.

Cache Mesh & Content Routing & Peering

Sibling Cache


일부 Network Architecture는 간단한 Cache Hierarchy가 아닌, 복잡한 Cache Mesh를 구성한다.
단순히 상위 Cache를 조회하는 방식에서 벗어나 정교하고 동적인 동작을 통해 Network를 효율적으로 이용한다.
이러한 Proxy Cache를 Content Router라고 부른다.
Content Router는 아래와 같은 동작을 할 수 있다.

  • URL을 통해 Parent Cache와 Server중 어떠한 것으로 Access할지 결정한다.
  • URL을 통해 특정 Parent Cache를 선택한다.
  • Parent Cache로 Access하기 전 Local Cache를 조회한다.
  • 다른 Cache가 현재 Cache의 일부를 조회할 수 있도록 하지만, Internet Transit은 허용하지 않는다.
    • Internet Transit - 다른 ISP로 Traffic이 이동하는 것

Cache를 더욱 효율적으로 사용하기 위해 다른 조직에 있는 Cache끼리 연결하여 사용할 수 있다. 이를 Peering이라고 하며, 이러한 Cache를 Sibling Cache라고 부른다.
HTTP에서 정식으로 지원하는 기능이 아니기에 ICP (Internet Cache Protocol)이나 HTCP (HyperText Caching Protocol) 등을 추가적으로 이용한다.
더 자세한 것은 Chapter 20에서 다룬다.

Cache Processing Steps

Process of Cache

현대의 상업용 Proxy Cache는 매우 복잡하다. 고성능이며 HTTP에서 사용 가능한 고급 기능이나 기술을 지원하도록 설계되었다.
하지만 Web Cache의 동작 방식은 대부분 간단한 편이다.
Cache 처리 과정은 크게 7가지로 분류할 수 있다.

  • Receiving - Cache가 Request를 받는다.
  • Parsing - Request를 Parsing한다.
  • Lookup - Local Cache에 존재하는지 확인한다.
  • Freshness Check - Cache의 Resource가 최신 Resource인지 확인하며, 아니라면 Server에 Request하여 Cache를 갱신한다.
  • Response Creation - Client의 Request에 대한 Response를 작성한다.
  • Sending - Response를 보낸다.
  • Logging - 선택적인 동작이며, Transaction에 대한 Log를 남긴다.

 

Step 1 : Receiving

Cache가 Network Connection을 통해 데이터가 들어오는 것을 감지한다.
고성능의 Cache는 여러 Request가 동시에 들어오는 것을 읽고 Request가 전부 도착하기 전에 Transaction을 실시하기도 한다.

Step 2 : Parsing

Cache가 Request를 Parsing하여 Header를 관리하기 쉽게 자료구조를 이용한다.
이러한 작업 덕분에 Caching S/W가 Header를 처리하기 쉽다.
또한 해당 과정에서 대소문자, 여러 형식의 날짜 표현 등을 하나의 방식으로 통일해주는 작업도 처리한다.
일부 Request는 전체 URL을, 일부 Request는 상대적 URL 등을 이용할 수 있기에 일반적으로 이러한 세부 사항은 가린다.

Step 3 : Lookup

Cache는 URL을 이용하여 Local Cache에 해당 Resource가 존재하는지 확인한다.
Local Cache는 Memory, Disk, 다른 컴퓨터 등 다양한 위치에 존재할 수 있다.
Local Cache가 존재하지 않다면 Parent Proxy나 Server에 Request를 보내 Resource를 받아온다.
Resource뿐만 아니라 Server의 Response, Resource가 Cache에 얼마나 오래 있었으며 얼마나 많이 사용되었는지 등을 알려주는 Metadata 등을 가지고 있다.
Server의 Response를 통해 HTTP 1.1에서는 Content Negotiation을 진행한다. 이는 Chapter 17에서 자세히 다룬다.

Step 4 : Freshness Check

Cache Revalidation Flow

Cache는 특정 시간 동안은 최신이라고 취급이 되며, 이 시간이 지나면 Resource의 변화가 있는지 Revalidate 작업을 진행한다.
Client가 Request Header에 명시하는 일부 Header는 강제로 Revalidation을 실시하거나 실시하지 않도록 한다.
HTTP는 Revalidation을 하는 복잡한 규칙이 존재하며, Cache에 존재하는 여러 옵션이나 HTTP가 아닌 Protocol 등으로 인하여 더 복잡해졌다.

Step 5 : Response Creation

최신 Resource가 아닐 경우, 이전 Step에서 이미 Revalidation을 진행한 상황이다.
또한 Server Response를 가지고 있기에 이를 이용하여 Response를 작성한다.
Server Response를 기반으로 Response를 수정하며, 최신 Resource임을 알려주는 Cache-Control, Age, Expires Header와 같은 Cache Freshness 정보를 포함한다.
이때 Date Header는 바꾸어서는 안 된다. 이는 Resource가 언제 Server에서 생성 혹은 수정되었는지를 알려준다.

Step 6 : Sending

Response를 작성하였다면 Client로 보낸다.
고성능 Cache에서는 효율적으로 Response를 보내기 위해 Local Storage에서 Network I/O Buffer로 복사하는 과정을 최대한 줄이기도 한다.
아마 이 부분은 DMA와 관련된 내용으로 보인다.

Step 7 : Logging

대부분의 Cache는 Cache 사용에 대한 Log File이나 통계 정보를 가지고 있다.
각 Transaction이 완료되면 Cache Hit나 Miss와 같은 정보, Request Type, URL, 동작 결과 등을 Log File에 저장한다.
가장 유명한 Log 형식은 Squid Log와 기존 Log 형식을 확장한 Netscape Log이다.
물론 유저는 독자적인 방식으로 Log를 저장할 수 있으며, 이는 Chapter 21에서 자세히 다룬다.

Keeping Copies Fresh

Cache에 저장된 Resource에 대한 Revalidation은 앞에서 계속 언급하였다.
아예 바뀌지 않거나 월간 통계 자료도 있겠으나, 매일 혹은 몇 초 단위로 변경되는 Resource도 존재한다.
매번 Server에 물어보지 않고 Cache의 Freshness를 확인하는 여러 방법이 존재한다.

Document Expiration

Document Expiration

Server는 Resource에 Cache-Control이나 Expires Header에 파기 날짜를 지정할 수 있다.
Resource 파기 날짜가 지나기 전에는 최신 Resource임을 Server가 보증하기에 이를 신뢰하고 사용한다.
물론 Client가 Caching 혹은 검증되지 않은 Resource를 금지하는 Header를 사용하면 Revalidation 작업이 필요하다.
파기 날짜가 지나면 Cache는 Resource가 최신인지 Server에 물어보며, 새로운 Resource로 교체하거나 파기 날짜를 갱신한다.

Expiration Date and Age

HTTP 1.0+의 Expires, HTTP 1.1의 Cache-Control: max-age Header를 이용하여 Server가 파기 날짜를 지정한다.
두 Header는 기본적으로 같은 의미를 가지나, Cache-Control Header는 상대적 시간을 사용하기에 절대적 시각을 사용하는 Expires Header보다 더 선호된다.
절대적 시간의 경우 컴퓨터의 시각에 의존적이기에, 올바른 시각으로 동기화가 되지 않으면 문제가 생길 수 있다.

  • Cache-Control: max-age - 초 단위로 시간을 표기한다. 긴 시간의 경우 직관적인 파악이 어렵다.
  • Expires - GMT 기준의 절대적 시각을 표기한다. 직관적인 파악이 가능할 수 있으나, GMT 0 기준이라는 것을 기억해야 한다.

 

Server Revalidation

파기 날짜가 지나더라도 해당 Resource가 갱신되었다는 의미는 아니다.
갱신의 가능성이 있기에 Server의 Resource와 비교하여 확인이 필요하다는 의미이다.
Server의 Resource가 바뀌었다면 해당 Resource를 가져오며, 바뀌지 않았다면 Server Response Header를 이용하여 파기 날짜를 갱신한다.
이 덕분에 Resource를 이용할 때마다 Server에 물어보지 않아도 된다.
Revalidation이 필요할 때 Server에 연결할 수 없다면 에러를 return한다.

Conditional Method

HTTP Header에 조건을 지정할 수 있으며, 이 덕분에 Conditional GET 한 번으로 Resource의 Revalidation이 가능하다.
If-Modified-Since, If-Unmodified-Since, If-None-Match, If-Match 등 여러 Conditional Header가 존재하며, 이 중 두 가지를 많이 사용한다.

If-Modified-Since : Date Revalidation

If-Modified-Since

줄여서 IMS라고도 불린다.
명시한 날짜 이후에 수정이 되었거나 Server가 IMS Header를 모른다면 GET Method를 수행하여 Resource를 가져온다.
수정되지 않았다면 Status Code 304 Not Modified와 새로운 파기 날짜를 Response로 받는다.

일부 Server는 IMS를 구현하지 않아 사용할 수 없다. 대신 특정 날짜에 수정이 되었는지를 확인한다.

If-None-Match

If-None-Match

아래와 같은 경우, If-Modified-Since Header를 이용하기 어렵다.

  • Resource가 주기적으로 갱신이 되나, 실제 내용에는 변화가 없는 경우
  • Resource가 갱신되었으나, 잘못된 스펠링 교체 혹은 Comment 추가와 같이 중요하지 않은 내용만 갱신된 경우
  • Resource의 수정 날짜를 Server가 정확하게 확인하지 못하는 경우
  • ms 단위로 매우 빠른 갱신이 이루어져 초 단위로 구분하는 것이 어려운 경우

이러할 때는 ETag(Entity Tag)를 이용하여 Resource가 최신인지 비교한다.
ETag는 수로 이루어진 Version이나 Version 이름으로 구성될 수 있다.
Server에서의 Resource 갱신 시 ETag를 함께 갱신할 수 있으며, 이 경우 최신 Resource가 바뀌었다고 판단할 수 있다.
If-None-Match Header에는 단일 ETag뿐만 아니라 여러 ETag를 명시하여 유연하게 사용할 수 있다.

Weak and Strong Validator

지금까지 사용한 Conditional Header는 최신 Resource가 아니라면 Resource를 전부 가져와야 하는 Strong Validator이다.
HTTP 1.1부터는 ETag: W/"v2.6" 혹은 If-None-Match: W/"v2.6" 와 같이 W를 붙임으로써 Weak Validator임을 명시할 수 있다.
Weak Validator는 Resource의 중요한 부분이 갱신될 때만 Resource를 새로 가져올 수 있는 Validator이다.

Server는 서로 다른 두 Entity에 대해 특정 Strong ETag를 사용하거나 의미상으로 다른 두 Entity에 대해 특정 Weak ETag를 사용해서는 안 된다.

When to Use

Server가 ETag를 보내면 Client는 ETag를 반드시 사용해야 한다.
ETag와 Resource 수정 날짜가 모두 존재한다면 Client는 모두 사용해야 한다.
Server는 가능하다면 ETag를 보내야 하며, Weak Validator 사용에 이점이 있다면 Strong Validator 대신 Weak Validator를 사용하는 것이 좋다. 또한 Resource 수정 날짜를 함께 보내는 것이 좋다.
Cache나 Server가 ETag와 If-Modified-Since 모두 받는다면 두 조건 모두 만족할 경우에만 Status Code 304 Not Modified를 Response한다.

Controlling Cachability

Cache의 공간은 무한하지 않기에 파기 날짜가 지나지 않더라도 Cache에서 사라질 수 있다. Cache에서 Resource를 삭제할 때 아래의 우선순위를 따른다. 아래로 내려갈수록 우선순위가 내려간다.

  • Cache-Control: no-store
  • Cache-Control: no-cache
  • Cache-Control: must-revalidate
  • Cache-Control: max-age
  • Expires date Header
  • 파기에 관한 정보가 없을 경우, Cache가 heuristic 파기 날짜를 결정

No-Store and No-Cache

HTTP 1.1에서 Resource Caching 여부에 대한 여러 방법이 추가되었다.

no-store를 명시할 경우 Caching을 금지한다.
no-cache를 명시할 경우 Local Cache에는 Caching할 수 있다. Proxy Cache에서 Revalidation 없이 Cache를 바로 Response하는 것을 금지한다.
HTTP 1.0에서는 No-Cache를 알 수 없기에 Pragma: no-cache를 이용해야 한다.

Must-Revalidate

Cache가 성능을 위해 오래된 Resource를 Serving할 수 있기에, 항상 Revalidation을 하도록 Server에서 must-revalidate를 명시할 수 있다.
항상 Revalidation이 이루어지며, Server가 죽어있다면 Status Code 504 Timeout을 Response한다.

Max-Age

max-age 혹은 s-maxage를 명시하여 일정 시간 동안 최신 Resource임을 보장한다. 초 단위로 명시한다.
s-maxagemax-age와 동일하지만 Public Cache에서만 이용 가능하다.

Expires Response Header

Deprecated되었으며, 정확한 파기 날짜를 명시한다.
여러 Server간의 시각을 동기화하기 어렵기에 절대 시각보다는 초 단위와 같은 상대 시간을 이용하게 되었다.
Expires: 0와 같이 사용하는 것은 해당 Resource를 항상 파기함을 의미한다.
일부 S/W에서 문제가 생길 수 있기에 이를 인식할 수는 있더라도, 이러한 Header 생성을 해서는 안 된다.

Heuristic Expiration

Response에서 Cache Control에 관한 내용이 없다면 Cache가 Heuristic Maximum Age를 계산한다.
Maximum Age가 24시간이 넘을 경우 Warning 13이 Response Header에 추가되어야 한다.

last-modified date가 존재할 경우 LM-Factor Algorithm을 이용하는데, 이에 대한 자세한 방법은 생략한다.
last-modified date조차 존재하지 않을 경우, 정보가 없기에 default freshness period로 설정한다. 보통 1시간 혹은 1일이다.
보수적인 Cache는 이를 0으로 설정하여 항상 Revalidation이 일어나도록 한다.
많은 Server는 Cache Control에 관한 내용을 사용하지 않기에 이러한 Heuristic Expiration에 대해 숙지하고 있어야 한다.

Client Freshness Constraint

Cache-Control Request Directive

Browser의 새로고침 버튼을 이용하면 오래된 Resource를 최신 Resource로 가져오도록 강제할 수 있다.
자세한 방식은 Browser, Resource, Intercepting Proxy의 설정 등에 따라 다르다.

또한 Client는 Cache-Control Header를 이용하여 Constraint의 강도를 조절할 수 있다.

Caution

Resource의 파기 날짜가 잘못하여 너무 먼 미래로 설정하면 문제가 발생할 수 있다.
이 때문에 많은 Publisher는 특정한 파기 날짜를 사용하지 않으며, Cache는 Resource가 얼마나 오랫동안 최신 Resource임을 보장받는지 알기 어렵다.

Setting Cache Controls

각 Server는 다른 방식으로 Cache Control과 Expiration Header를 제공한다.
Apache에서 Cache Control Header를 관리하는 방법은 크게 3가지로 나눈다.

  • mod_headers - Resource마다 서로 다른 Header를 지정한다.
  • mod_expires - 파기 날짜를 지정하며, Resource마다 다른 날짜로 지정할 수 있다.
  • mod_cern_meta - HTTP Header와 다른 파일을 연결한다. metafile을 만들어 Resource별로 지정할 수 있다. 정확한 용도는 모르겠다.

HTTP-EQUIV

HTML 2.0부터Tag가 추가되었다.
기존의 HTTP Header를 설정하기 위해 설정 파일을 이용하였으나, 해당 Tag를 이용하면 설정 파일이 없더라도 HTTP Header를 추가할 수 있다.
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"> 와 같이 HTML 내부의 Tag를 통해 Header를 관리하는 것이다.
HTML Parsing만 하여 쉽게 Header를 설정할 수 있으나, HTML에서만 사용 가능하기에 Server나 Proxy에서 거의 지원하지 않는다.

Detailed Algorithms

HTTP에서 Aging이나 Cache Freshness를 계산하기 위한 Algorithm은 정확하지 않은 근사치일 가능성이 있다.
물론 시간은 상대적이지만, 적어도 지구 안에서의 시간은 절대적이라고 볼 수 있다. 왜 근사치일 수 있는지 알아본다.

Age

Age Caculation Flow

위 사진은 앞으로 설명할 내용을 그림으로 간단하게 표현한 것이다.
Cache의 Resource가 최신인 것은 Resource의 Age < Freshness Lifetime 라고 볼 수 있다.
Freshness Lifetime은 고정값이며, Age만 계산하면 된다.

Age는 간단히 말하자면 Response를 하는 시각 - Resource가 수정된 시각이다. 계산식은 매우 간단하지만 여러 문제가 발생한다.
날짜를 기준으로 할 경우 매우 간단해 보이나, 이는 Server와 Proxy 모두 같은 시각으로 동기화가 되어 있어야만 가능하다.
NTP (Network Time Protocol) 등을 이용하면 동기화가 가능하겠지만, 항상 동기화가 되어 있다고 장담할 수 없다.
이와 같이 두 컴퓨터의 시각이 다른 상황을 Clock Skew라고 한다.

날짜를 이용할 수 없다면 Resource의 수정 이후 흘러간 시간을 계산해야 한다.
각 Server 혹은 Proxy에서 저장된 시간은 Local Clock을 이용하기에 Clock Skew 문제없이 계산할 수 있다.
문제는 Server와 Proxy간의 데이터 전송 시간이다.
매우 빠른 Network라면 매우 짧은 시간이겠으나, 매우 느린 Network라면 몇 초의 시간이 소요될 수 있다.
편도의 시간은 계산할 수 없기에 왕복 시간을 계산하여 이용한다.
실제 Resource의 Age보다 조금 더 큰 값을 가지게 되지만, 오래된 Resource를 갱신 없이 유저에게 Service하는 것보다는 낫다.

서적의 내용은 훨씬 길며, 모든 내용을 적기보다는 이해하기 쉽게 적는 것이 낫다고 판단하였다.
더 자세한 학습을 원한다면 해당 Chapter를 직접 읽는 것을 추천한다.

Freshness Lifetime

Freshness Lifetime은 Server 혹은 Client의 Constraint를 이용하여 결정한다.

Caches and Advertising

광고주는 Cache 덕분에 유저들에게 더 많은 광고를 빠르게 제공할 수 있기에 좋아한다.
문제는 Cache Hit로 인하여 유저들에게 광고가 얼마나 노출되는지를 파악하기 어렵다. 이를 무시하면 Publisher는 광고비를 제대로 받지 못한다.
이 때문에 일부 Publisher는 CGI (Common Gateway Interface) Gateway를 통해 광고를 한다.
또한 no-cache Header를 추가하거나 매번 Revalidation을 하도록 한다.
이는 Cache의 목적에 부합하지 않기에 좋은 방안이 아니다.

Proxy에는 Cache에 관련된 Log가 존재할 것이며, 이를 주기적으로 보내주면 Cache를 효율적으로 이용할 수 있을 것이다.
하지만 Log는 매우 방대하며, 이를 주기적으로 보내는 것 또한 Network 측면에서 효율적인 방식은 아니다.

이러한 문제들을 해결하기 위해 RFC 2227이 도입되었다.
Meter Header를 이용하여 Cache Hit를 count하거나 Caching 시간을 제어한다.
이에 대한 자세한 것은 Chapter 21에서 다룬다.

Conclusion

Caching에 대한 전반적인 것을 학습하였다.
Cache가 없었더라면 훨씬 느린 Network를 더 비싼 비용으로 이용했을 것이다.
Cache로 인하여 발생하는 문제도 존재하지만, Cache의 이점이 훨씬 크기에 이러한 부분을 숙지하는 것이 중요할 것이다.