♪ 학습 내용
캐시 / 검증헤더와 조건부요청
* 캐시 동작
웹 브라우저에 캐시가 없다면 같은 요청을 보내도 매번 계속 서버로부터 데이터를 다운로드 받아야 한다.
느린 사용자 경험.
웹 브라우저에 캐시를 적용하면 다르다.
이 경우 첫 번째 요청에서는 당연히 서버로부터 데이터를 받아와야한다.
하지만 캐시를 적용하지 않았을 때와는 달리, 서버의 HTTP 응답 메시지에 cache관련 헤더가 있고,
이 응답 결과를 웹 브라우저의 캐시 저장소에 저장하게 된다.(쿠키와 같은 원리)
그리고 두번째 요청을 보낼 때면 먼저 이 브라우저 캐시를 뒤지고, 같은 데이터가 있으면 캐시에서 조회한다.
이렇게 되면 네트워크를 사용하지 않아도 되고, 속도가 매우 빠르다.
빠른 사용자 경험.
평소에 웹 브라우저 중 한 번 들어갔던 곳은 되게 빠르게 동작했던 이유가 바로 이 캐시를 적용했기 때문이다.
캐시 관련 헤더로 기본적으로 캐시의 유효 시간을 설정해주는 cache-control 헤더가 있다.
HTTP 응답에서 cache-control 헤더로 헤더의 유효시간을 초 단위로 설정해주고,
응답을 받은 브라우저는 해당 캐시를 저장한다.
브라우저에서 캐시를 조회할 때 이 캐시의 유효 시간을 검증하고, 유효시간이 지나지 않았으면 캐시를 이용!
만약에 캐시 유효 시간을 초과했다면?
다시 서버에 요청 후 캐시를 갱신한다. 이때 네트워크 다운로드가 발생.
근데 유효시간이 지났어도 서버가 가진 데이터와 캐시에 저장된 데이터가 완전히 같다면
캐시를 갱신하기 위해 다시 전체 용량을 다운 받는건 매우 비효율적이다.
이를 해결하기 위한 방법이 바로 검증 헤더와 조건부 요청이다.
* 검증헤더와 조건부 요청1
캐시가 만료되었지만 서버에서 데이터를 변경하지 않은 경우에
저장돼있는 캐시를 재사용할 수 있다면 정말 좋다.
이를 위해서는 캐시 저장 이후에 본 데이터가 변경되었는지를 알아야 한다.
검증 헤더로 Last-Modified 를 추가.
Last-Modified는 해당 데이터의 최종 수정일을 UTC 표기로 담는다.
그리고 이 응답 결과를 캐시에 저장.(유효 시간과 최종 수정일 정보와 함께)
만약 캐시의 유효 시간이 만료 되었다면. 똑같이 서버로 재요청을 한다.
이때 조건부 요청이 사용된다.
if-modified-since 헤더를 HTTP 요청에 붙인다.
if-modified-since에는 만료된 캐시가 가지고 있는 데이터 최종 수정일이 담겨있다.
이 요청 메시지를 받은 서버의 데이터 최종 수정일과 요청의 수정일이 같다면.
즉 데이터가 아직 수정되지 않았다면!!
서버는 304 Not Modified 상태 코드와 함께 헤더 메타 정보만을 응답한다.(바디는 제외)
HTTP 바디를 제외한다는 것은, 다운로드 받는 용량이 매우 작다는 의미.
(바디에 주로 다운받는 데이터가 있으니)
그리고 이 응답을 받은 브라우저는 응답 결과를 재사용하여 헤더 데이터를 갱신하고,
데이터를 캐시에서 조회한다.
정리하자면 다음과 같다.
캐시 유효시간이 초과하더라도 데이터가 변경되지 않았다면!!
304 상태코드와 함께 바디가 없는 메세지로 응답. 이를 기반으로 클라이언트는 정보를 갱신.
이 과정에서 다운로드(헤더 메타 정보)가 발생하지만, 용량이 매우 적다.
캐시의 데이터 재활용. 매우 실용적인 해결책이 된다.
그래서 실제로 대부분의 웹 브라우저가 이 매커니즘을 사용하고 있다고 한다.
검증헤더 : Last-Modified / 조건부 요청 : if-modified-since
* 검증헤더와 조건부 요청2
Last-Modified와 if-modified-since 는 날짜 기반이다.
그렇기 때문에 데이터를 수정해서 같은 결과를 내도 수정된 날짜가 변경된다.
수정 전과 후의 결과가 같음에도.
그리고 1초 미만의 단위로 조정이 불가능하다.
이러한 단점을 보완하는 검증 헤더로 ETag가 있다.
ETag는 캐시용 데이터에 고유한 임의의 이름을 달아준다.(Hash)
만약 데이터가 변경되면 이 ETag 이름을 변경한다.(Hash 다시 생성)
이 ETag를 검증헤더로 사용하면??
ETag가 같으면 캐시 조회, 다르면 다시 받고.
결과가 같게끔 수정하는 경우에도 데이터가 같으므로 ETag는 같을 것이다.
그리고 캐시 저장소의 ETag 이름이 서버의 것과 같은지 확인하기 위해
요청 메시지의 헤더에 If-None-Match 헤더를 사용한다.(조건부 요청)
즉, 클라이언트는 ETag를 보내기만 하면 된다.
-> 캐시 제어 로직을 서버에서 완전하게 관리한다.
검증헤더 : ETag / 조건부 요청 : If-None-Match
* 캐시 제어 헤더
- Cache-Control: max-age
캐시의 유효시간, 초단위
- Cache-Control: no-cache
데이터 캐시는 가능하지만, 항상 원서버(origin)에 검증(조건부 요청)해야 한다.
- Cache-Control: no-store
캐시 저장하면 안된다.
- Pragma
HTTP 1.0 하위 호환으로, 지금은 거의 사용하지 않는다.
- Expires
캐시의 만료일을 지정한다.
하지만 초 단위로 만료를 관리하는게 더 유용하게 사용가능하기에 Cache-Control: max-age 권장.
* 프록시 캐시
예를 들어 지구 반대편에 있는 원서버(Origin Server)에 바로 접근하려면 0.5초 걸린다고 생각하자.
근데 원서버와 연결된 서버를 한국에 도입한다면, 해당 서버가 원서버와 연결하고.
우리는 해당 서버와만 연결하면 원서버로 접근한 셈이 된다.(시간은 0.1초로 단축)
이러한 서버를 프록시 캐시 서버라고 한다.
이 프록시 캐시 서버에 저장되어있는 캐시를 public 캐시, 클라이언트의 캐시를 private 캐시라고 한다.
이와 관련된 캐시 제어 헤더들ㅇ ㅣ있다.
- Cache-Control: public
응답이 public 캐시에 저장되어도 된다.
- Cache-Control: private
응답이 private 캐시에만 저장되어야한다. 즉, 사용자만을 위한 것이다.
절대로 중간의 프록시 캐시에 저장하면 안된다. 절대.
- Cache-Control: s-maxage
프록시 캐시에 적용되는 max-age
- Age:60
Origin Server에서 응답후에 프록시 캐시에 머문 시간
* 캐시 무효화
앞에서 여러 캐시 제어 지시어들을 보았다.
만약 절대 캐시를 저장하면 안된다하면 다음과 같이 사용하면 된다.(다 넣어)
Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache |
앞에서는 나오지 않았던 캐시 지시어인 Cache-Control: must-revalidate는
캐시 만료 후 최초 조회 시 원 서버에 검증해야 한다.
엥? 그러면 캐시가 만료되든 안되든 무조건 원서버에 검증해야하는 no-cache가 있으면 필요없는 거 아닌가?
다 뜻이 있다.
no-cache에서는 어떠한 이유로 원 서버에 접근이 불가한 경우에 프록시 서버로 요청이 오면,
그냥 200OK로 응답한다. 이 말은 원서버에 검정하지 않았는데 프록시에서 그냥 캐시를 조회하라고 검증하는 것.
no-cache는 오류나는 거 보다 예전 데이터를 보여주는게 낫다는 방식이기 때문.
반면에 must-revalidate는 원 서버에 접근 불가한 경우 항상 오류를 발생( 504 오류 )시킨다.
'Dev > HTTP' 카테고리의 다른 글
[HTTP] HTTP 헤더 (2) (0) | 2022.12.29 |
---|---|
[HTTP] HTTP 헤더 (1) (1) | 2022.12.29 |
[HTTP] HTTP 상태코드 (0) | 2022.12.27 |
[HTTP] HTTP 메서드 활용 (0) | 2022.12.25 |
[HTTP] HTTP 메서드 (0) | 2022.12.25 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!