Web Cache란 Origin Server에 존재하는 object를 저장하는 저장소이다.
※ 본 포스트는 브라우저 Cache를 Cache라 칭하겠다.
Cache는 Origin Server에 존재하는 object를 브라우저 내 저장소에 저장한다.
새로고침을 할 때마다 Object를 요청할 필요 없이, 자신의 Cache 저장소에 있는 데이터를 가지고 오면 된다.
Cache가 없다면?
GET Method로 이미지 파일을 요청한다고 가정해보자.
응답 메시지에서 헤더는 0.1 M 이고, 이미지 파일(본문)은 1 M 이다.
Cache가 없다면, 새로고침을 할 때마다 Origin Server에 파일을 요청해서 1.1M 의 트래픽을 발생시켜야 한다.
Cache를 사용한다면?
똑같은 방법으로 이미지 파일을 요청한다고 해보자.
하지만, 이번 응답 헤더에는cache-control: max-age=360
이라는 필드가 존재한다.HTTP/1.1 200 OK Content-Type: image/jpg cache-control: max-age=360 Content-Length: 5720
slfl2hjefh2e3fkljfe2
해당 응답을 받은 브라우저는 이미지 파일을 360초 동안 자신의 웹 브라우저에 저장한다.
다음 요청 때는 자신의 브라우저 저장소에서 이미지를 찾아오면 된다.
Cache의 시간이 만료되면 어떻게 해야할까?
간단하다!
다시 똑같은 메시지로 요청하면 된다.
그러면 Origin Server도 똑같은 응답 메시지를 보내줄 것이다.
HTTP/1.1 200 OK
Content-Type: image/jpg
cache-control: max-age=360
Content-Length: 5720
slfl2hjefh2e3fkljfe2
하지만, 이것은 매우 비효율적일 수 있다.
Origin Server에 존재하는 이미지 파일이 전혀 바뀌지 않았다면?
➜ 기존 Cache를 연장해서 그대로 사용하면 네트워크 트래픽이 발생하지 않는다.
앞선 문제를 비효율성을 개선하기 위한 방식이 바로 Conditional GET: 조건부 요청이다.
이전의 시나리오를 똑같이 생각해보자.
GET /image.jpg HTTP/1.1
Host: juju.com
HTTP/1.1 200 OK
Content-Type: image/jpg
cache-control: max-age=360
Last Modified: 2024-03-13 15:30:00
Content-Length: 5720
slfl2hjefh2e3fkljfe2
클라이언트는 360초동안 Cache를 사용한다.
360초가 지난 뒤에 클라이언트가 Origin Server에게 최종 수정 시간 변동이 있는지 묻는다.
GET /image.jpg HTTP/1.1
Host: juju.com
if-modified-since: 2024-03-13 15:30:00
HTTP/1.1 304 Not Modified
Content-Type: image/jpg
cache-control: max-age=360
Last Modified: 2024-03-13 15:30:00
Content-Length: 5720
5에서 데이터의 수정 사항이 발생하면?
➜ 200 OK 와 함께 새로운 데이터 + 최종 수정 시간을 보내준다.HTTP/1.1 200 OK Content-Type: image/jpg cache-control: max-age=360 Last Modified: 2024-03-13 20:30:00 Content-Length: 5359
dfjwbekfneo2ekfn
요청: if-modified-since
응답: Last-Modified
하지만, 위의 두 검증헤더에는 단점이 존재한다.
위의 문제점을 해결하는 검증 헤더가 ETag이다.
ETag(Entity Tag)는 검증 헤더의 일종이다.
요청: If-None-Match
응답: ETag
GET /image.jpg HTTP/1.1
Host: juju.com
HTTP/1.1 200 OK
Content-Type: image/jpg
cache-control: max-age=360
ETag: "version1"
Content-Length: 5720
slfl2hjefh2e3fkljfe2
클라이언트는 360초동안 Cache를 사용한다.
360초가 지난 뒤에 클라이언트가 Origin Server에게 ETag 변동이 있는지 묻는다.
GET /image.jpg HTTP/1.1
Host: juju.com
If-None-Match: "version1"
HTTP/1.1 304 Not Modified
Content-Type: image/jpg
cache-control: max-age=360
ETag: "version1"
Content-Length: 5720
Cache-Control
뿐만 아니라, Cache를 제어할 수 있는 여러 헤더들이 존재한다.
Cache-Control: max-age=360
➜ 초 단위로 Cache의 유효 기간을 설정한다.
Cache-Control: no-cache
➜ 데이터는 캐시해도 되지만, 항상 Origin Server에 검증하고 사용
⚠️ 캐시 해도 된다!!!
Cache-Control: no-store
➜ 캐시하면 안됨
HTTP 1.0 하위 호환을 위한 헤더이다.
HTTP 1.0 만을 지원하는 브라우저가 존재할 때 사용한다.
캐시 만료 시간을 지정한다.
HTTP 1.0 하위 호환을 위한 헤더이다.
expires: WED, 13 MAR 2024 15:30:00 GMT
Proxy Server란 Origin Server에 접속하지 않고 Client가 요청한 것을 응답하는 대리 서버이다.
한국에 거주하는 클라이언트 A가 Amazon 서버에 접속한다.
Amazon Origin Server는 미국에 존재하므로, 메시지를 송수신 하는데 시간이 오래 걸린다.
이를 해결하기 위해, Proxy Server 가 존재한다.
Proxy Server는 Origin Server의 데이터를 캐시로 저장해 놓은 서버이다.
한국에 Proxy Server를 두고 Amazon Origin Server의 데이터를 캐시로 저장하면?
➜ 한국에 거주하는 클라이언트들이 빠르게 서비스 이용 가능
Proxy Server는 클라이언트이자 서버이다.
Origin Server에 요청하는 클라이언트이자,
Client에게 응답하는 서버이다.
Cache-Control: max-age
대신, Cache-Control: s-maxage
를 사용한다.Age
라는 헤더는, Origin Server에서 응답 후 Proxy Server 내에 머문 시간을 초 단위로 제공한다.주식 데이터 같은 경우는 Cache를 사용해서는 안된다!
Cache를 확실하게 사용하지 못하도록 하려면 어떻게 해야할까?
Cache-Control: no-cache, no-store, must-revalidate
※ Pragma: no-cache
- 하위 호환
3가지 옵션을 모두 사용하면, 클라이언트가 Cache를 저장하지 못하게 확실히 막을 수 있다.
must-revalidate
은 Cache 만료 후에 최초 조회 시 Origin Server에 반드시 검증해야 하는 옵션이다.
Cache-Control: no-cache
➜ 데이터는 캐시해도 되지만, 항상 Origin Server에 검증하고 사용
Cache-Control: must-revalidate
➜ 캐시 만료 후 Origin Server에 검증을 받아야 함 + Origin Server 접근 실패시 반드시 오류 발생
- no-cache의 경우
클라이언트 A, Proxy Server P, Origin Server O 가 존재한다.
no-cache 옵션만 적용되었을 때는, 데이터를 Origin Server에 검증 받은 뒤 캐시해도 된다.
따라서, 클라이언트 A는 데이터를 P에 요청하고, P는 O의 검증을 받는다.
갑자기, O와 연결이 끊어졌다.
no-cache 이면 반드시 Origin Server의 검증을 받아야 하지만, O와 통신이 불가능한 상태이다.
이 경우, P는 오류가 나는 것보다는 오래된 데이터라도 보여주는 것을 선택한다.
- must revalidate의 경우
마찬가지로, O와 연결이 끊어진 상황을 가정해보자.
must-revalidate 는 Origin Server에 접근할 수 없는 경우, 반드시 오류가 발생해야 한다.
따라서, 이 경우에는 A에게504 Gateway Timeout
이 응답으로 전달된다.
그런데 한가지 궁금증이 생겼다.
Cache-Control: no-store
만으로도 충분하지 않나?
이 궁금증에 대한 답은 여기서 찾을 수 있었다.
요약하자면, Cache-Control: no-store
만으로는 모든 Cache를 무효화 할 수는 없다.
예를 들어, 1월까지는 Cache 저장을 허용하다가, 2월부터 Cache를 저장하지 못하도록
Cache-Control: no-store
를 적용했다.
하지만, 이전에 저장된 Cache가 삭제되는 것은 아니다.