[Network] HTTP (4-3) - Proxy 캐시와 HTTP 캐시 무효화
Proxy 캐시와 HTTP 캐시 무효화에 대한 개념 정리
HTTP와 웹 브라우저의 캐시 검증과 조건부 요청에 대한 자세한 내용은 #HTTP (4-2) - HTTP 캐시 검증 & 조건부 요청 게시글을 참고
프록시(Proxy) 캐시
프록시는 클라이언트와 본 서버를 중계하는 중간에 위치한 서버 대리자로서, 클라이언트의 요청을 대신 받고 본 서버에 해당 요청을 대신 전달해주는 역할을 한다.
이 프록시를 캐시 서버로서 이용할 수 있는데, 예를 들어서 한국에 있는 클라이언트에서 이미지가 필요한 상황이고, 해당 이미지의 본 서버가 미국에 있다고 가정해보자.
한국 서버에서 미국 서버까지 직접 접근하여 이미지를 가져오는데는 약 0.5초가 걸린다고 하면, 한국에 위치한 컴퓨터들은 모두 0.5초 가량을 기다려야 해당 이미지를 받을 수 있게 된다.
위와 같은 현상을 해결하기 위해 프록시 캐시를 도입하여 사용한다고 보면 된다.
한국에 프록시 캐시 서버를 따로 두고, 최초의 요청에만 미국 서버까지 가서 이미지 리소스를 받아오고 프록시 캐시 서버에 저장한다.
그러면 한국의 클라이언트는 리소스를 가져올 때 프록시 캐시 서버로부터 가져오면 된다.
특히 여러 사람들이 찾는 자료일수록 이미 캐시에 등록되어있을 가능성이 크기에 효과적으로 빠른 속도로 자료를 가져올 수 있다.
유튜브에서 고용량의 영상을 빠르게 볼 수 있는 이유도 이에 해당한다.
즉, 같은 국내에 캐시된 데이터가 있는 덕분에 본 서버에 접근하는 것보다 훨씬 빠른 속도에 자료를 가져올 수 있다는 것이다.
참고로 클라이언트에서 사용되고 저장되는 캐시를 private 캐시라고 하며, 프록시 캐시 서버의 캐시를 public 캐시라고 한다.
웹 브라우저 캐시와 프록시 서버 캐시가 분리되어 운용되는 만큼, 위에서 설명한 Cache-Control HTTP 헤더도 프록시 전용으로 캐시를 설정해야 한다.
프록시 캐시 헤더
CDN에서는 1년 동안 캐시되지만, 브라우저에서는 매번 재검증 요청을 보내도록 설정
Cache-Control: private
- 응답이 해당 사용자만을 위한 것으로 private 캐시에 저장해야 한다. (default)
Cache-Control: public
- 응답이 public 캐시에 저장되어야 한다.
Cache-Control: s-maxage
- 프록시 캐시에만 적용되는
max-age
Age: 60
- HTTP 헤더로써, 오리진 서버에서 응답 프록시 캐시 내에 머문 시간이다.(초 단위)
HTTP 캐시 무효화
캐시 무효화(Cache Busting)는 말 그대로 웹 브라우저의 캐시를 완전히 제거해 버리는 것을 말한다.
이러한 기술이 필요한 이유는 웹 브라우저들이 GET
요청을 받을 경우에 별도의 캐시 헤더 없이도 자기 마음대로 최적화를 한다고 임의로 캐싱을 해 버리기 때문이다.
또한 리소스의 캐시 유효 기간을 길게 설정해버리는 바람에 리소스의 업데이트가 필요할 경우, 캐시 저장소의 복사본을 갱신해줘야 하는데, 기본적으로 브라우저는 캐시 유효 기간이 끝나야 캐시 유효성 검증을 서버에게 요청하기 때문에 어떠한 방법이 없다.
이런 문제를 해결하기 위해 캐시 무효화 전략을 사용한다고 보면 된다.
---
title: Cache-Control의 흐름도
---
flowchart TD
A(응답을 캐싱 할 것인가?) --<ins class="red" style="padding: 5px">NO</ins>--> B(no-store<br>캐싱 안함)
A --<ins class="blue" style="padding: 5px">YES</ins>--> C(캐시 사용 전에 <ins>캐시 유효성 검증</ins>을 할 것인가?)
C --<ins class="red" style="padding: 5px">NO</ins>--> D(프록시 캐시를 사용하는가?)
C --<ins class="blue" style="padding: 5px">YES</ins>--> E(no-cache<br><ins>매번 서버에서 캐시 유효성 검증</ins>을 하고 캐시 사용)
E --> D
D --<ins class="blue" style="padding: 5px">YES</ins>--> F(public<br><ins>프록시 캐시에 저장</ins>)
D --<ins class="red" style="padding: 5px">NO</ins>--> G(private<br><ins>클라이언트 캐시에 저장</ins>)
G --> H(캐시 유효 기간을 설정하는가?)
F --> H
H --> I(max-age= ∙∙∙)
I --> J(Add ETag Header)
캐시 무효화 헤더
만약 캐시를 사용해서는 안되는 페이지가 존재한다면, 다음과 같이 Cache-Control 헤더에 파라미터들을 설정해줘야 한다.
1
2
3
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Cache-Control: no-cache
- 데이터는 캐시해도 되지만, 항상 본 서버에 검증하고 사용해야 한다는 의미로,
max-age=0
과 동일한 뜻이다.- 즉, 서버로부터 304 응답을 받아야 캐시에서 가져온다는 의미로, 비록 네트워크 트래픽이 발생하지만 헤더 메시지만 응답받기 때문에 네트워크 다운로드량은 적다.
no-cache
라는 명칭 때문에 캐시를 사용하지 않는다고 생각할 수 있지만, 이 단어의 의미는 본래 캐시 유효 기간이 남아있으면 무조건 캐시 저장소를 조회하지만, 그러지 말고 무조건 서버에 검증을 받으라는 의미이다. - 즉, 서버로부터 304 응답을 받아야 캐시에서 가져온다는 의미로, 비록 네트워크 트래픽이 발생하지만 헤더 메시지만 응답받기 때문에 네트워크 다운로드량은 적다.
Cache-Control: no-store
- 데이터에 민감한 정보가 있기에 저장하면 안된다는 의미이다.
- 메모리에서 사용하고 최대한 빠르게 삭제한다.
Cache-Control: must-revalidate
- 캐시 만료 후 최초 조회 시, 본 서버에 검증해야 할 때 설정한다.
- 본 서버에 접근 실패 시, 반드시 504(Gateway Timeout) 오류가 발생하도록 해야 한다.
- 만일 캐시 유효 시간 내에 있다면, 캐시를 사용한다.
- 본 서버에 접근 실패 시, 반드시 504(Gateway Timeout) 오류가 발생하도록 해야 한다.
Pragma: no-cache
- HTTP/1.0 하위 호환용으로 사용한다.
간혹, 몇몇 웹 페이지에서는 캐시 무효화 우회 로직으로 Cache-Control 헤더에
max-age=0
으로 설정해 놓는다.캐시 유효 시간을
0
으로 설정해 놓으면, 매번 리소스를 요청할 때마다 서버에 재검증 요청을 보내게 된다.하지만, 몇몇 일부 모바일 브라우저의 경우 네트워크 요청을 아끼고 사용자에게 빠른 웹 경험을 제공하기 위해 웹 브라우저를 껐다 켜기 전까지 리소스가 만료되지 않도록 하는 경우도 존재한다.
따라서
max-age=0
을 사용하기 보다는 좀 더 명확한no-store
파라미터를 사용하기를 권장한다.
no-cache VS must-revalidate
캐시 무효화 헤더를 설정할 때, 보통 no-cache
와 must-revalidate
를 같이 설정하는 편이다.
must-revalidate
를 사용하는 이유는 no-cache
에 의해 본 서버(Origin Server)에 검증 요청을 보내는 도중에 본 서버와 프록시 캐시 서버(Proxy Cache Server)의 연결이 끊어져 검증이 불가능할 경우에 504 Gateway Timeout 오류를 발생시키기 위함이다.
몇몇 프록시 캐시 서버에서는 본 서버에 접근이 불가능할 경우에 검증을 거치지 않고 이전의 캐시 데이터를 반환하기 때문이다.
예를 들어, 통장 잔고와 같은 중요 데이터의 경우, Origin Server와의 연결이 불가능하다고 해서 변경 전의 데이터를 반환하면 절대로 안된다.
이와 같은 이유 때문에
must-revalidate
를 활용해서 일부러 5XX 오류를 발생시키는 전략을 세운다고 보면 된다.
no-cache의 동작 (기본)
- 클라이언트는
ETag
와no-cache
설정을 하고 서버에게 요청한다. - 중간에 프록시 캐시 서버가 받게 되고,
no-cache
설정이 되어있기 때문에, 다시 본 서버에 요청한다. - 본 서버에서
ETag
로 검증한다. - 프록시에게 304 응답을 준다.
- 프록시는 다시 클라이언트에게 그대로 응답한다.
- 클라이언트는 캐시를 재사용한다.
no-cache의 동작 (본 서버 문제 발생 시)
- 클라이언트는
ETag
와no-cache
설정을 하고 서버에게 요청한다. - 중간에 프록시 캐시 서버에서 다시 본 서버에 요청하는데, 어떠한 이유로 네트워크가 단절되어 접근이 안된다.
- 그러면
no-cache
에서는 응답으로 오류가 아닌, 오래된 데이터라도 보여준다는 개념으로 200 OK 상태 코드로 응답을 한다. - 본 서버의 처리 상태는 모른 채로 클라이언트는 오래된 데이터를 소비자에게 제공하게 되고, 결국에는 서비스에 차질이 생기게 된다.
must-revalidate의 동작
위와 같이 no-cache
의 문제점 때문에 must-revalidate
를 명시하여 Proxy Cache Server가 자체적으로 캐시 데이터를 반환하는 케이스를 사전에 차단하여야 한다.
- 클라이언트는
ETag
와must-revalidate
설정을 하고 서버에게 요청한다. - 중간에 프록시 캐시 서버에서 다시 본 서버에 요청하는데, 어떠한 이유로 인해 네트워크가 단절되어 접근이 안된다.
- 문제가 생겼으므로 일단
must-revalidate
에서는 무조건 504 Gateway Timeout 오류를 응답한다. - 클라이언트는 본 서버에 문제가 있음을 감지하고 별도의 재수정 로직을 거치게 된다.
다만,
must-revalidate
는 캐시 유효성 기간이 남아있으면 우선적으로 캐시 저장소를 조회하게 되어있다.따라서 본 서버 네트워크 문제 해결과 항상 본 서버에 캐시 검증을 함께 사용하고 싶은 경우,
no-cache
와 함께 설정해주면 된다.