<개요>
- 최근 S3를 File,정적데이터 제공등의 목적으로 사용중인데 max-age 헤더에 대한 내용이 궁금하여 상세한 내용을 파악해 보았다. (HTTP 완벽 가이드 중 일부 내용 정리)
- HTTP 프로토콜은 통신의 많은 부분을 차지하고 있으며 OSI 7 Layer상 최상단에 위치한다.
- 즉, 해당 계층을 잘 활용하면 실제 사용자에게 전달되는 데이터를 컨트롤 할 수 있으며
특히 캐시를 잘 활용하면 응답시간을 상당히 개선할 수 있다.
(다만 브라우저나 클라이언트등에서 일으키는 강제 Refresh에 대해서도 고려할 필요가 있다.)
<내용>
1. Cache-Control 헤어
- 클라이언트는 Cache-Control 요청헤더를 사용하여 만료제약을 조정할 수 있다.
Cache-Control: max-stale Cache-Control: max-stale=<s> |
캐시는 신선하지 않은 문서라도 자유롭게 제공할 수 있다. <s>가 지정되면, 클라이언트는 만료시간이 <s>만큼 지난 문서도 받아들인다. |
완화 |
Cache-Control: min-fresh=<s> | 클라이언트는 지금으로부터 적어도 <s>초 후까지 신선한 문서만을 받아들인다. | 엄격 |
Cache-Control: max-age=<s> | 캐시는 <s>초보다 오랫동안 캐시된 문서를 반환할 수 없다. 나이가 유효기간을 넘어서게 되는 max-stale지시어가 함께 설정되지 않는 이상 더엄격하게 만든다. |
엄격 |
Cache-Control: no-cache-Pragma:no-cache | 이 클라이언트는 캐시된 리소스는 재검사하기 전에는 받아들이지 않을 것이다. | 엄격 |
Cache-Control: no-store | 이 캐시는 저장소에서 문서의 흔적을 최대한 빨리 삭제해야 한다. 그 문서에는 민감한 정보가 포함되어 있기 때문이다. |
엄격 |
Cache-Control: only-if-cached | 클라이언트는 캐시에 들어있는 사본만을 원한다. |
* 이는 완벽한 시스템이 아니다.
* 유효기간을 먼 미래로 설정한다면, 어떤 변경도 캐시에 반영되지 않을 것이다.
* 유효기간을 사용조차 하지 않아서 문서가 얼마나 오래 신선할 것인지 캐시가 알기 어려운 경우도 많다.
* 이는 DNS와 같은 많은 인터넷 프로토콜에서 사용되는 "ttl"의 기법의 한 형식이다.
다행히 HTTP에는 DNS와 달리 클라이언트가 만료일을 덮어쓰고 강제로 재로딩할 수 있는 메커니즘이 있다.
2. 나이와 신선도 계산
- 캐시된 문서가 제공되기에 충분히 신선한지 알려면 두 가지값을 계산할 필요가 있다.
- 바로 캐시된 사본의 나이와 신선도의 수명이다.
- 충분히 신선한가?
$나이 < $신선도 수명
다음 사항이 주 고려사항이다.
- 캐시는 문서응답이 어디에서 왔는지 알 수 없기 때문에 헤더를 통해서 계산해야 한다.
- 신선도 수명은 해당 문서의 나이가 신선도 수명을 넘었다면 제공하기에 충분하지 않다고 판단하는 것으로 문서의 유효기간 뿐만 아니라 영향을 주는 클라이언트의 모든 요청을 고려해야 한다. (e.g 네트워크 지연)
A. 겉보기 나이는 Date헤더에 기반한다.
$겉보기_나이 = max(0, $응답을 받은 시각 - $Date_헤더값)
$문서가_캐시에_도착했을때의_나이 = $겉보기 나이
- 모든 컴퓨터가 똑같이 정확한 시간을 갖고 있다면 단순히 현재시간 - 문서를 보낸 시간으로 계산할 수 있다.
- 하지만 모든 시계는 동기화되지 않으며 심지어 오차가 심할 경우에는 음수가 되기도 한다. max(0, )처리가 필요한 이유
- 이러한 문제를 클럭 스큐라고 한다.
B. 점층적 나이
- 그래서 우리는 이에 대한 대응방법으로 프락시나 캐시를 통과할때마다 Age헤더에 상대적인 나이를 누적해서 더하도록 한다.
- 이 방법은 서버간의 시간비교나 종단 시간비교가 필요없기 때문에 유용하다. (내부시계를 사용하여 체류시간 계산)
- 문서가 각 어플리케이션에 머무른시간과 네트워크 사이를 이동한 시간만큼 Age헤더의값을 늘려야 한다.
- 비 HTTP/1.1 장치의 경우 헤더를 고치거나 삭제하기 때문에 유의해야 하며, 따라서 Age 헤더는 상대나이에 대한 모자란 추정값의 상태로 본다.
$보정된_겉보기_나이 = max($겉보기_나이, $Age헤더값)
$문서가_캐시에_도착했을때의_나이 = $보정된_겉보기_나이
*신선한 컨텐츠를 얻는 것이 목적이기 때문에 max를 이용해서 보수적으로 계산한다.
C. 네트워크 지연에 대한 보상
- 트랜잭션은 느려질 수 있다. (캐시의 주된 동기)
- 매우 느린 네트워크, 과부하 서버, 트리팩등의 발생은 문서의 나이 추정에 대한 추가 계산이 필요하다.
- Date헤더는 언제 문서가 원 서버를 떠났는지 나타내주고 ( *프락시/캐시는 절대 이 헤더를 수정해서는 안된다), 캐시로 옮겨가는 중 얼만큼 시간이 걸렸는지 말해주지 않는다.
- 서버 <> 캐시 왕복지연 시간을 계산하는 것은 상대적으로 쉽다. (왜나하면 요청시각과 도착시간을 알고 있으니까)
$겉보기_나이 = max(0, $응답을 받은 시각 - $Date_헤더값)
$보정된_겉보기_나이 = max($겉보기_나이, $Age헤더값)
$응답_지연_추정값 = ($응답을_받은_시각 - $요청을_보낸_시각)
$문서가_캐시에_도착했을때의_나이 = $보정된_겉보기_나이 + $응답_지연_추정값
D. 최종 나이계산
- 이 응답이 캐시에 한번 저장되면, 나이를 더 먹게 된다.
- 그 문서의 현재 나이를 계산하기 위해서 그 문서가 캐시에 얼마나 오랫동안 머물렀는지 알아야 한다.
$나이 = $문서가_캐시에_도착했을때의_나이 + $사본이_얼마나_오래_우리의_캐시에_있었는지
캐시된 문서의 나이 | |||||||
서버 | 요청네트워크지연 | 서버가 처리하는 시간 | 응답네트워크지연 | ||||
캐시 | 요청한_시각 | 응답을_받은_시각 | 캐시에 체류한 시간 | 현재_시각 | |||
클라이언트 | 클라이언트가_요청한_시각 |
<정리>
- HTTP에서는 문서의 나이와 신선도를 계산하여 캐시를 제공한다.
- 신선도 수명은 서버와 클라이언트의 제약조건에 의존한다.
- 인터넷의 특성상 클럭스큐와 네트워크 지연이 발생하며 문서의 나이를 계산할때 이를 고려한 방법들이 존재한다.
- 다음 글에서는 신선도를 계산하는 알고리즘에 대해서 정리한다.