네트워크를 통해 요청-응답을 수행하는 과정은 느리면서 비용이 많이 든다. 크기가 큰 응답은 클라이언트와 서버 사이에 많은 요청-응답 사이클이 필요하다. 때문에 브라우저가 처리할 수 있는 시기가 지연되고 방문자 또한 데이터 비용이 발생한다. 따라서 가져온 리소스를 캐싱하고 재사용하는 기능은 성능 최적화에 중요한 측면이다.
모든 브라우저에서는 HTTP 캐시 구현이 포함되어있다. 이를 사용하기 위해서는 HTTP 헤더에 캐시 관련 설정을 응답으로 제공하여 브라우저가 캐시할 시점과 기간을 설정하도록 알려주면 된다.
위 캡쳐와 같은 방식으로 응답을 반환할 때 Cache-Control헤더를 제공하여 max-age프로퍼티로 120초 동안 브라우저에서 캐시하도록 지정하며 ETag를 활용하여 응답이 만료된 후 리소스가 수정되었는 지 확인하는 데 사용할 수 있는 유효성 검사 토큰을 제공할 수 있다.
Cache-Control
참고: https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Cache-Control
Cache-Control 응답 헤더는 브라우저 및 중간 캐시가 개별 응답을 캐시할 수 있는 방법 및 기간을 제어하는 헤더이다.
no-cache vs no-store
no-cache는 반환된 응답이 변경된 경우 서버와 먼저 확인하지 않고는 동일한 URL에 대한 후속 요청을 충족하는 데 사용할 수 없음을 나타낸다. 따라서, 적절한 ETag가 있다면 서버와 한 번의 요청-응답 흐름으로 응답의 변경을 판단할 수 있다. 즉, no-cache는 매번 서버와 요청-응답을 하면서 컨텐츠의 변화를 비교하는 옵션이다.
반면, no-store는 캐시를 사용하지 않는 옵션이다. 따라서 요청마다 응답을 다운로드 받는다.
public vs private
public과 private는 캐시할 수 있는 상태에 관련한 옵션이다.
public은 HTTP로 요청-응답하고 응답 상태코드가 정상적으로 캐시할 수 없는 경우에도 캐시가 가능하다. 대부분의 경우는 public, private이 없다면 public으로 간주한다.
반면, private는 응답이 단일 사용자를 대상으로 하므로 캐시가 이 응답을 캐시하지 못하도록 막는 옵션이다. 즉, 비공개 사용 정보가 포함된 HTML은 브라우저가 캐시할 수 있지만 CDN은 캐시할 수 없다.
max-age
요청 시간부터 가져온 응답을 재활용할 수 있는 최대 시간을 지정한다. 단위는 초가 기본이다. max-age=60은 60초 동안 해당 응답이 캐싱된다는 의미이다.
Expires와의 차이
참고:https://stackoverflow.com/questions/12908766/what-is-cache-control-private
Cache-Control은 HTTP/1.1 스팩의 일부로 정의되었다. 이전에는 Expires를 사용하여 캐싱에 활용했는데 HTTP/1.1부터는 Cache-Control을 통해서 캐시 사항을 지원해주면 된다.
즉, HTTP/1.1에서는 Expires는 Deprecated 된 옵션이다.
최적의 Cache-Control 정책 정의
Cache-Control 예시
- Cache-Control: max-age=86400: 응답을 최대 1일 (60 * 60 * 24) 동안 브라우저 및 중간 캐시가 캐시할 수 있다. (public)
- Cache-Control: private, max-age=600: 응답을 10분 동안 클라이언트의 브라우저만 캐싱 가능.
ETag
첫 요청으로 리소스를 가져온 후 브라우저가 동일한 리소스에 새 요청을 실행한다고 가정한다. 이 경우 다음과 같은 사이클을 가진다.
- 브라우저는 로컬 캐시를 확인하여 이전 응답을 찾는다.
- 만료되지 않았다면 이를 그대로 사용
- 이전 응답이 만료되었다면 새 요청을 발송한다.
단, 응답이 만료되었더라도 리소스 변경이 없다면 이는 비효율적이다. 이 비효율을 해결하기 위해 나타난 것이 바로 ETag이다. 서버에서는 ETag를 일반적으로 파일 콘텐츠의 해시나 기타 임의 토큰으로 생성-반환한다. ETag값이 동일하다면 리소스가 변경되지 않고 요청-응답 흐름을 그대로 건너뛸 수 있다.
위 예시에서는 브라우저가 If-None-Match를 사용하여 받은 ETag값을 제공한다. 서버는 현재 리소스와 비교하여 이 토큰을 검사한다. 만약 일치한다면 서버는 304 Not Modified를 반한한다. 서버와 요청-응답 흐름이 있었지만 응답을 다시 다운로드할 필요는 없으므로 다운로드에 드는 시간 및 대역폭을 아낄 수 있다.
버전 업데이트
브라우저에서 응답을 캐시한 후 캐시된 버전은 max-age 또는 expires로 지정된 대로 캐시가 유효하거나 몇몇 다른 이유로 제거되지 않는다면 캐시에서 응답이 제거될 때까지 사용된다. 단, 특정 파일을 업데이트하여 제공하고 싶지만 해당 파일이 캐싱되어있다면 어떻게해야할까?
이를 위해서는 리소스의 URL을 변경하고 컨텐츠가 변경될 때마다 사용자가 새 응답을 받도록 하면 된다. 일반적으로 파일의 디지털 지문이나 버전을 파일이름에 포함하는 방식으로 수행한다.
'Web Basic > HTTP' 카테고리의 다른 글
컨텐츠 협상 (Content Negotiation) (0) | 2019.10.13 |
---|---|
HTTP 압축 (Compression) (1) | 2019.10.13 |
HTTP 세션 (0) | 2019.10.06 |
HTTP 쿠키 (0) | 2019.10.06 |
HTTP 메세지 (0) | 2019.10.06 |