2024. 11. 23. 20:11ㆍ 프로그래밍/Front-end
캐시 무효화를 위한 응답 헤더 설정법
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
💡 `Expires: 0` 응답 헤더를 함께 사용하는 경우도 있는데,
이는 문법 위반이며 몇몇 소프트웨어와 충돌할 가능성이 있으므로 사용을 지양해야 함
(응답을 받는 쪽에선 대비 필요)
(우선순위 순. 함께 쓰였다면 후순위는 무시됨)
Cache-Control
: 캐시의 신선도를 관리하기 위한 헤더. 문서가 만료되기 전까지 얼마나 오랫동안 캐시될 수 있게 할 것인지 서버가 설정할 때 사용. (HTTP/1.1)no-store
: 응답을 로컬 저장소에 저장하지 말라는 의미. (메모리에서만 사용하고 최대한 빨리 삭제하라)no-cache
: 로컬 캐시 저장소에 응답을 저장하지만, 반드시 항상 원 서버에 검증하고 사용해야 한다.
정확히는 “Do not serve from cache without revalidation”라고 이해해야 함.must-revalidate
: 사본이 만료된 후 최초로 조회했을 땐 원 서버에 검증하고 사용해야 함max-age=<s>
: 캐시의 유효 기간(초 단위). 유효 기간이 다 되면 원 서버에 재검증하고 사용해야 함max-age=0
과no-cache
는 대부분의 브라우저에서 동일한 뜻을 가짐no-store
,no-cache
,must-revalidate
를 썼다면max-age
를 함께 쓰지 않아야 함. 서로 대치되는 의미이기 때문임
Pragma: no-cache
: HTTP/1.0 하위 호환용Expires: <date>
: 캐시의 만료 날짜를 절대 시각으로 명시.Cache-Control: max-age=<s>
와 함께 쓰였다면Expires
헤더가 무시됨
💡 `no-store`가 있는데 `no-cache`까지 필요한 건, IE10과 그 이전 버전에선 `no-cache`만 사용하기 때문
*출처: https://learn.microsoft.com/en-us/troubleshoot/developer/browsers/connectivity-navigation/how-to-prevent-caching*
응답에 캐시의 만료 시점에 대한 정보가 없다면? :: 휴리스틱 만료
서버에서 응답을 생성할 때
Cache-Control: max-age=<s>
나Expires
가 없었다면, 휴리스틱하게 만료 시점을 계산하게 됨다양한 휴리스틱 만료 알고리즘이 있는데, 대표적으로 LM-Factor Algorithm이 있음(Last-Modified 값을 factor로 활용하는 방법)
캐시된 문서가 마지막으로 수정된 게 오래전이다?
→ 안정적인 문서일 것. 갑자기 바뀔 가능성 낮으므로 캐시에 더 오래 보관해도 괜찮을 것캐시된 문서가 최근에 수정됐다?
→ 자주 변경될 가능성이 큼. 서버와 재검사하기 전까지 짧은 기간 동안만 캐시해야 함Research and Implementation of HTTP Caching Freshness Algorithm - Scientific Figure on ResearchGate. Available from: https://www.researchgate.net/figure/Calculate-fresh-cycle-with-LM-Factor-algorithm_fig1_300619144 [accessed 23 Nov 2024]
휴리스틱 신선도 유지 기간의 상한은 보통 일주일. 보수적인 사이트는 하루 정도로 설정함
만약 최종 수정 시간도 없으면, 기본값을 사용함(한 시간 ~ 하루)
Nginx 캐시 설정
캐시 무효화
location / {
root /home1/irteam/deploy/dist;
+ add_header Cache-Control "no-cache, no-store, must-revalidate";
+ add_header Pragma "no-cache";
try_files $uri $uri/ /index.html;
}
특정 타입의 리소스는 별도로 캐시 설정을 하고 싶다면
location / {
root /home1/irteam/deploy/dist;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
try_files $uri $uri/ /index.html;
}
+ location ~* \.(gif|jpeg|jpg)$ {
+ add_header Cache-Control "public, max-age=86400";
+ }
💡
`Cache-Control: private`: End user만 개인 PC의 디스크나 메모리에 캐시를 저장할 수 있음
`Cache-Control: public`: 모든 사용자와 공용 프락시 서버가 캐시를 저장할 수 있음.
공용 프락시 서버에 리소스를 캐싱하면, 사용자가 자주 찾는 리소스를 원 서버에서 딱 한 번만 가져와 모든 클라이언트의 요청에 대해 공유된 사본을 제공할 수 있음
⇒ 네크워크 트래픽 감소
Q. 캐시의 만료 시점에 대해 딱히 지정하지 않았다가, 갑자기 캐시 무효화 하도록 설정해서 서버를 배포하면 어떻게 될까?
A.
- 서버에서 응답을 생성할 때 캐시의 만료 시점을 휴리스틱하게 계산해서 설정했을 것임
- 참고: RFC 7234 - Hypertext Transfer Protocol (HTTP/1.1): Caching - 4.2.2. Calculating Heuristic Freshness*
- 만약 서버가 응답에 만료 시점을 명시하지 않았더라도, 클라이언트가 얼마나 캐시를 오래 보존할지 결정할 수 있음
(max-stale
,min-fresh
,max-age
값이 설정되었는지에 따라 적절한 한계값을 계산해서 서버가 준 유효 기간을 덮어씀) - 서버와 클라이언트에서 결정한 캐시의 유효 기간이 지나 캐시가 만료되면, 그때 서버에 캐시를 재검증하게 됨.
이때Cache-Control: no-store, no-cache, must-revalidate
헤더를 포함한 응답을 받게 되어,
로컬 저장소에 있는 캐시를 삭제함과 동시에 이후의 캐시는 저장하지 않게 됨
클라이언트에서 강제로 캐시를 갱신하는 방법
- 리로드(Reload)
- 브라우저가 캐시된 리소스를 무시하고 모든 리소스를 다시 다운로드하여 페이지를 완전히 새로고침 하는 것
- 개발자 도구를 연 상태에서 주소 표시줄 옆의 새로고침 버튼을 Windows: Ctrl, Mac: Cmd 함께 클릭하여 “캐시 비우기 및 강력 새로고침” 선택
- Disable cache
- 개발자 도구 > Network > Disable cache 클릭
- 이 옵션을 활성화하면, Request Header에
Cache-Control: no-cache
,Pragma: no-cache
헤더가 포함되어 요청이 감
- 요청 URL에 무작위한 쿼리 문자열 추가
- 페이지가 로드될 때 특정 리소스에 대한 요청을 다시 보내도록 할 수 있음
(ex. img, script 태그의 src 또는 href 속성에 쿼리 문자열을 추가) - 브라우저는 매번 다른 URL을 사용하여 리소스를 가져오기 때문에 캐시를 무시하고 새로운 리소스를 다운로드함
- 페이지가 로드될 때 특정 리소스에 대한 요청을 다시 보내도록 할 수 있음
참고문헌
- 데이빗 고울리, 브라이언 토티, 마조리 세이어, 세일루 레디, 안슈 아가왈 (지은이), 정상일, 이응준 (옮긴이). (2014). HTTP 완벽 가이드. 201쪽 ~ 213쪽
- ✨ HTTP 프록시 캐시와 캐시 무효화 (no-cache, Must-revalidate) | leemember.log
- nginx에서 정적 리소스 캐싱하기 (성능 최적화) | votogether.log
'프로그래밍 > Front-end' 카테고리의 다른 글
훨씬 더 정교해진 반응형 구현 방법: 컨테이너 쿼리 (0) | 2024.11.22 |
---|---|
Modern CSS Colors (0) | 2024.11.08 |