내가 한 노력들

[ 캐시 ] 조건부 요청 / 검증헤더 / Cache-Control / ETag 본문

IT 공부/Network

[ 캐시 ] 조건부 요청 / 검증헤더 / Cache-Control / ETag

JONGI-N CHOI 2021. 10. 20. 16:55

캐시

캐시가 없을 때 

서버에 요청해서 데이터를 한 번 받아왔을 때, 다음에 또 똑같은 데이터를 요청하면 또 한번 네트워크 서버를 사용해서 해당 요청을 거쳐서 데이터를 받와야하기 때문에 서버 사용량과 시간이 발생합니다. 

 

 

캐시가 있을 때

위와같은 문제를 해결하기 위해서, 처음 데이터를 서버에서 전송할 때, 브라우저에 존재하는 캐시 저장소에 저장을 하도록 합니다. 

그래서 똑같은 요청을 했을 때, 서버에 요청을 하는 것이아니라 캐시 저장소에서 바로 받아올 수 있도록 하는 것

 

1. 이미지 요청

GET /image.png HTTP/1.1
Host: www.google.com

2. 이미지 리소스 응답 

HTTP/1.1 200 OK
Content-Type: image/png
cache-control: max-age=60
content-length: 3402

asdlkasafkljsadflkjsal;kfjsad;lkfjad;klfj
dfkljasdlkfjsdalkfjsdlkfjsa;flkjklfj123

3. 브라우저 캐시 저장소에 저장 

 

4. 이미지 요청 

서버에 요청하지 않고, 캐시 저장소에 저장되어있는 이미지 가져다가 사용  ( 캐시 만료시간이 남아있을 경우)

 

여기서 문제점

캐시는 cache-control: 을 통해 캐시 만료 시간을 지정하게 되는데, 시간이 만료되고 난 뒤에 요청을하면, 결국은 또 다시 네트워크에서 똑같은 용량의 데이터를 받아와야 함 

 

캐시 저장소에 저장되어 있는 데이터와 서버에 있는 데이터에 차이가 있으면, 새로 받아와야 하지만, 변화없이 똑같은 데이터일 때는 굳이 또 받아와야할까? -> 조건부 요청

 

조건부 요청

if-modified-since: UTC 날짜 (조건부 요청)

 

서버 리소스에 데이터에 변화가 있다면 새로 받아와야겠지만, 변화가 없으면 굳이? 또? 이러한 문제를 해결하기 위해서 

검증헤더 추가 

Last-Modifyed

"Last-Modifyed: UTC 표기 시간"를 추가해서 보냄

HTTP/1.1 200 OK
Content-Type: image/png
cache-control: max-age=60
Last-Modifyed: UTC 표기 시간
content-length: 3402

asdlkasafkljsadflkjsal;kfjsad;lkfjad;klfj
dfkljasdlkfjsdalkfjsdlkfjsa;flkjklfj123

 

그러면, 캐시 저장소에서 캐시가 만료되었을 경우, 네트워크에 요청을 보냄

GET /image.png HTTP/1.1
if-modified-since: UTC 날짜

 

네트워크에서는 해당 리소스의 last-modified 날짜와 비교를 합니다. 

날짜가 같아 ( 변경이 없을때 )

HTTP/1.1 304 Not Modified
Content-Type: image/png
cache-control: max-age=60
Last-Modifyed: UTC 표기 시간
content-length: 3402

304 Not Modified, 즉 수정되지 않았다는 상태 코드를 전송

그리고, 처음에 응답했을때와 다르메 body가 없음. -> 네트워크 사용량을 줄일 수 있다. 

 

그러면, 브라우저에서 Not Modified 상태코드를 받으면 아~ 캐시에 있는 데이터 그대로 사용해도 되겠구나 ~ 하고 

만료 시간을 늘린다음에 사용을 합니다. 

 

Last-Modified와 if-modified-since의 단점

- 1초 미만 단위로 캐시 조정이 불가능

- 날짜 기반의 로직 사용

- 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같은 경우 ( A-> B-> A) 

 

ETag

서버에서 별도의 캐시 로직 관리르 하고 싶은 경우

- 스페이스나 주석처럼 크게 영향이 없는 변경에서는 캐시를 유지하고 싶은 경우 

 

캐시용 데이터에 임의의 고유한 버전 이름을 달 수 있음

 - ETag: "v1.0", ETag: "asdasdasd3"

 

데이터가 변경되면 이 이름을 바꾸어서 변경함 (HAS를 다시 생성) 

 

ETag만 보내서, 같으면 유지, 다르면 다시받기

 

캐시 제어 로직을 서버에서 완전히 관리 

 

클라이언트는 단순히 이 값을 서버에 제공 ( 클라이언트는 캐시 메커니즘을 모름) 

 

 

1. 이미지 요청

GET /image.png HTTP/1.1
Host: www.google.com

 

2. 이미지 리소스 응답

ETag: "abc"를 추가 

HTTP/1.1 200 OK
Content-Type: image/png
cache-control: max-age=60
ETag: "abc"
content-length: 3402

asdlkasafkljsadflkjsal;kfjsad;lkfjad;klfj
dfkljasdlkfjsdalkfjsdlkfjsa;flkjklfj123

 

브라우저 캐시 저장소에서는 ETag: "abc"를 저장해둠 

 

3. 캐시 만료가 된 후에 다시 요청을 하면

if-None-Match: "abc"를 같이 보냄 

GET /image.png HTTP/1.1
if-None-Match: "abc"

ETag의 이름이 같으면 304 상태코드 , 다르면 200 상태 코드

 

4. 응답

HTTP/1.1 304 Not Modified
Content-Type: image/png
cache-control: max-age=60
ETag: "abc"
content-length: 3402

 

5. 브라우저 캐시 저장소 만료시간 갱신 후 사용

 

 

Cache-Control

Cache-Control: max-age

- 캐시 유효 시간, 초단위

 

Cache-Control: no-cache

- 데이터는 캐시해도 되지만, 항상 Origin 서버에 검증하고 사용 ( 중간에 캐시 서버같은 것이 존재하기 때문에, 그런 중간 캐시서버에서 확인하지 말고 응답하는 본 서버에서 검증을 해라) 

 

Cache-Control: no-store 

- 데이터에 민감한 정보가 있으므로 저장하면 안됨 ( 메모리에서 사용하고 최대한 빨리 삭제) 

 

Cache-Control: must-revalidate

- 캐시 만료후 최초 조회시 원 서버에 검증해야함 

- 원 서버 접근 실패시 반드시 오류가 발생해야함 - 504 Gateway Timeout

- must-revalidate는 캐시 유효 시간이라면 캐시를 사용함 

 

no-cache와 must-revalidate의 차이점

중간에 프록시 캐시 서버가 존재할 경우에, no-cache는 데이터를 요청하면 원 서버에서 검증을 받아야하는데, 프록시 서버와 원서버 사이에서 연결이 끊킨 경우에 프록시 서버에서 그냥 원래 있던 데이터를 보내어 200 상태 코드를 보내는 경우가 있다. 

 

하지만, must-revalidate인 경우에는 프록시 서버와 원 서버사이에 연결이 끊켜서 검증이 안되는 경우에는 504(Gateway Timeout) 상태 코드를 전달하게 됩니다. 

 

프록시 캐시

보통 해외에 있는 서버들은 데이터를 받아오는데 시간이 오래걸리기 때문에, 중간에 프록시 캐시 서버가 존재한다. 

한국에서 미국에 있는 서버에 데이터를 가져올 때, 바로 가져오기 보다는 한국 어딘가에 있는 프록시 캐시 서버가 미국 서버의 데이터를 받아서 저장해두고, 한국에 사람이 요청을 할 경우 한국 프록시 캐시 서버에서 데이터를 받아옴

 

Cache-Control: public 

응답이 public 캐시에 저장되어도 됨

 

Cache-Control: private

응답이 해당 사용자만을 위한 것임, private 캐시에 저장되어야 함 

 

 

확실한 캐시 무효화 응답

Cache-Control: no-cache, no-store, must-revalidate 

위에 조건을 모두 넣어줘야지만 캐시가 저장되지 않는다. 

 

(캐시에 대한 설정을 하지 않아도 웹 브라우저에서 지혼자 저장하는 경우가 있음)