HTTP 캐싱으로 브라우저가 요청을 줄이는 방법
2024년 4월 23일
같은 이미지, 같은 JS 파일을 매 요청마다 서버에서 새로 받아오는 건 낭비다. 브라우저가 이미 가지고 있는 걸 활용하면 되는데, 그 기준을 정하는 게 HTTP 캐싱이다.
HTTP 캐싱이란?
한 번 받아온 리소스를 브라우저나 중간 서버(CDN)에 저장해두고, 다음 요청 때 서버에 다시 가지 않고 재사용하는 기술이다.
Cache-Control 헤더
HTTP 캐싱은 Cache-Control 응답 헤더로 한다. 즉 서버가 브라우저에게 캐시 저장 방식을 지시하는 헤더를 포함해서 응답한다.
자주 쓰이는 옵션들
max-age=3600: "앞으로 1시간 동안은 서버에 묻지 말고 이 파일을 그대로 써." 정적 에셋(이미지, 번들된 JS)에 주로 쓴다.no-cache: 캐시는 저장하되, 매번 서버에 "이거 아직 써도 돼?"라고 검증 요청을 보낸다. 저장을 막는 게 아니라 검증을 강제하는 옵션이다.no-store: 절대 저장하지 않는다. 매번 새로 받아와야 하는 민감한 정보에 사용한다.public: CDN 같은 중간 서버에도 저장할 수 있다.private: 오직 사용자의 브라우저에만 저장한다. 로그인한 사용자 데이터처럼 개인화된 응답에 쓴다.
no-cache와 no-store는 이름이 비슷해서 자주 헷갈린다. no-cache는 저장은 하고 매번 확인, no-store는 저장 자체를 금지한다.
ETag로 변경 여부 확인하기
no-cache를 쓰면 브라우저는 매 요청마다 서버에 확인을 보낸다. 그런데 서버가 어떻게 "데이터 안 바뀌었으니 캐시 써도 돼"라고 알려줄까?
이때 사용하는 게 **ETag(Entity Tag)**다. 리소스의 버전을 식별하는 해시값이다.
- 첫 요청: 서버가 리소스와 함께
ETag: "abc123"헤더를 반환한다. - 재요청: 브라우저가
If-None-Match: "abc123"헤더를 포함해 유효성을 확인한다. - 응답: 데이터가 변경되지 않았다면 서버는 본문 없이 **
304 Not Modified**만 반환한다. 브라우저는 기존 캐시를 그대로 쓴다.
데이터가 바뀌었다면 서버가 새 리소스와 새 ETag를 담아. status를 200 OK로 응답한다. no-cache와 ETag를 함께 쓰면 매번 확인하되 변경이 없을 때 304로 처리해 대역폭을 절약할 수 있다.