- 웹 캐시는 사용될 일이 많은데, 최근에는 사용할 일이 없었던 것 같다.
- 그렇기에, 까먹기 전에 HTTP와 관련된 웹 캐시에 대해서 배웠던 내용을 정리하기로 하였다.
클라이언트 앱이 서버에 요청을 보낼 때, 이미 가지고 있는 용량이 큰 데이터(이미지 등)에 대한 요청을 다시 보낼 수도 있다.
만약, 요청을 보냈을 때 마다 이미 가지고 있던 데이터라도(수정 되지 않은 데이터) 다시 받아오게 된다면 대단히 비효율적일 것이다.
🍝 인터넷 네트워크는 느리고 비싸다. 브라우저의 로딩 속도가 느려지면 느린 사용자의 경험이 제공되어 버린다.
🍝 용량이 큰 파일을 받을수록 당연히 로딩은 느려질 것이다.
데이터나 값을 미리 복사하여 저장하는 임시장소인 캐시를 사용하면, 브라우저가 이를 기억하고 저장할 수 있다.
캐시를 사용하면 데이터 접근에 걸리는 시간이나 같은 값을 계산하는 시간을 줄일 수 있다.
🍚 캐시의 데이터를 사용하면, 접근 시간이나 계산이 필요없이 더 빨리 데이터에 접근할 수 있다.
브라우저의 캐시를 저장할 땐 cache-control 속성을 이용하여 캐시가 유효한 시간을 정할 수 있다.
응답을 받은 경우 cache-control에 지정된 시간만큼 응답에 대한 결과를 브라우저 캐시에 저장한다.
만약, 캐시가 존재할 때 cache-control에 지정된 시간 이내에 다시 이 데이터에 대한 요청이 온다면, 캐시에 있는 데이터를 가져오게 된다.
🍙 cache-control 속성의 값을 60초로 설정하면, 60초 동안 이 캐시가 유효하다는 것을 의미한다.
🍙 캐시를 사용하면, 네트워크를 사용하지 않고 데이터를 가져올 수 있기에 브라우저 로딩이 빠르다. 그렇기에 빠른 사용자 경험을 제공할 수 있다.
🍙 비싼 네트워크를 적게 사용할 수 있다.
🍡 유효 기간이 지난 뒤 네트워크를 통해 다시 받은 응답의 결과는 기존에 유효기간이 지난 캐시에 덮어씌워(업데이트)진다. 그리고 유효기간은 다시 갱신된다.
캐시를 검증할 수 있는 캐시 검증헤더가 있다. 그리고 이를 통해서 조건부로 요청을 보낼 수 있다.
cache-control에 지정된 캐시 유효기간이 지났어도, 데이터가 변하지 않았다면 다시 캐시의 데이터를 사용할 수 있는 방법이 있다.
🍩 이때, 데이터를 검증을 한 뒤에 기존의 캐시 데이터를 사용할 수도 있다.
🍫 응답 결과가 캐시에 저장될 때 Last Modified(데이터 최종 수정 시간)도 저장된다.
캐시의 유효기간이 초과 되었어도, If-Modified-Since HTTP 요청 헤더를 사용하여 조건부로 요청을 할 수 있다.
서버는 데이터를 검증하고, 데이터가 수정되지 않았다면 바디를 제외한 HTTP 헤더만 보내어 데이터 수정이 없었음을 알려준다. (상태 코드 304 Not Modified)
🍧 클라이언트는 서버가 보낸 헤더의 정보로 캐시의 메타데이터를 갱신한다.
이 응답을 받은 뒤 다시 캐시의 유효 기간은 갱신된다. 유효기간이 지났어도, 데이터가 변경되지 않았다면 서버에서 데이터 다운로드가 일어나지 않는 아주 효율적인 방법이다.
다만, Last-Modified와 If-Modified-Since는 1초 미만의 단위로 캐시를 조정할 수 없고 날짜 기반의 로직을 사용한다.
🍪 따라서 같은 데이터라도 수정한 날짜가 다르면 다시 데이터를 전송한다. 그리고 서버에서 캐시 로직를 관리하고자 할 때 유효하지 않을 수 있다. (ex. 주석, 공백 제거 후 캐시 유지 하기)
🍡 서버에서 완전히 캐시를 컨트롤 하고자 한다면, ETag(Entity Tag)를 사용한다. ETag는 캐시 데이터에 고유한 버전 이름을 명시한다. 데이터가 변경되면 이 이름이 변경된다. (ETag가 변경되면 다른 데이터로 인식)
응답의 ETag 값은 클라이언트 캐시에 저장되고 캐시 시간이 초과되었을 때, ETag는 ETag 값을 검증하는 If-None-Match를 요청 헤더에 작성되어 보내진다. (조건부 요청)
데이터가 변경되지 않았다면 ETag 값은 동일하고, 이때는 body 없이 HTTP 헤더만 전송된다. (상태 코드는 304 Not Modified) 그리고 브라우저는 캐시의 데이터를 재사용한다.
이때, 클라이언트는 서버의 캐시 로직을 알 수 없다.
max-age는 캐시 유효 시간 (초단위)를 의미한다.
no-cache는 데이터는 캐시를 해도 되지만, 항상 origin 서버에서 검증하고 사용되야 함을 의미한다.
no-store는 데이터에 민감한 정보가 있으니, 저장하지 않고 메모리에서만 빨리 사용하고 지우는 것을 의미한다.
Expires 속성으로 캐시 만료일을 정확한 날짜로 지정할 수도 있다.
프록시 서버는 서버와 클라이언트 사이에서 대리(중계 기능)로 통신을 하는 서버를 의미한다.
클라이언트나 서버가 다른 네트워크에 간접적으로 접속할 수 있기에 보안, 캐싱을 통한 성능, 트래픽 분산 등의 장점이 있다.
서버와 클라이언트 중간에 프록시 캐시 서버를 통해서 많은 요청이 온 데이터를 캐시에 등록하여 빠르게 응답할 수 있다.
🍩 이는 Origin 서버에 응답을 보내고 응답을 받는 것 보다 빠르다.
이때 클라이언트에서 사용하고 저장하는 캐시를 private 캐시라 하고, 프록시 캐시 서버의 캐시를 public 캐시라고 한다.
프록시 캐시 서버와 관련된 헤더로 Cache-Control: public, Cache-Control: private, Cache-Control: s-maxage, Age: 60 등이 있다.
클라이언트가 캐시를 저장하지 않아도 브라우저에서 임의로 캐시를 저장할 수 있는데, 이 경우 민감한 데이터를 캐시에 저장하지 못하도록 하는 방법으로 캐시를 무효화 하는 헤더를 사용한다.
🍚 Cache-Control: no-cache, Cache-Control: no-store, Cache-Control: must-revalidate, Pragma: no-cache
확실히 캐시를 무효화하고자 한다면, 위의 캐시 지시어를 모두 사용한다.
no-cache와 must-revalidate 모두 origin 서버에 검증해야 하지만 그에 대한 응답에 대해 다른 점이 있다.
🍚 no-cache의 경우 캐시 서버 요청을 하면, 프록시 캐시 서버에서 origin에 요청을 하고 origin 서버에서 검증 후 304 응답을 한다.
🍚 프록시 캐시 서버와 origin 서버의 연결이 단절된 상태라면, 오류를 응답하지 않고 오래된 데이터를 보여주는 응답을 보낸다. (200OK)
🍚 반면, must-revalidate의 경우 origin 서버에 접근이 불가할 때 504 Gateway Timeout 오류를 보낸다.
🍚 통장 잔고 등 중요한 정보가 Origin 서버를 못 받았다고 해서 예전 데이터로 뜬다면 큰 문제가 생기기 때문에 이런 경우 must-revalidate를 써야 된다.
참고 자료 출처 : 코드 스테이츠