개요
웹 서비스를 빠르고 안정적으로 제공하기 위해 캐싱은 반드시 이해해야 할 기술이다. 잘 설계된 캐싱 전략은 서버 부하를 줄이고 사용자 경험을 크게 향상시킬 수 있다. 이 글에서는 『HTTP 완벽가이드』를 기준으로 HTTP 캐싱을 구성하는 핵심 요소들과, 프론트엔드 개발자가 실무에서 마주치는 다양한 상황에 적용할 수 있는 전략을 설명한다.
목차
- 개요
- 캐시 제어의 핵심: HTTP 헤더
- Cache-Control
- ETag / If-None-Match
- Last-Modified / If-Modified-Since
- 블로그 서비스에서의 기능별 캐싱 전략 생각해보기
- 실무에서 마주치는 캐싱 상황과 해결법
- 정리
- 참고자료
캐시 제어의 핵심: HTTP 헤더
HTTP 캐싱은 헤더를 통해 동작한다. 응답 헤더와 요청 헤더를 조합하여, 클라이언트가 리소스를 저장할지, 재검증할지, 또는 매번 새로 요청할지를 판단하게 된다.
Cache-Control
HTTP/1.1부터 도입된 표준 캐시 제어 헤더이다. Expires 대신 사용되며 훨씬 정교한 제어가 가능하다.
- public: 모든 캐시(브라우저, 프록시, CDN 등)에 저장 가능하다.
- private: 개인 사용자 전용 데이터로, 브라우저에만 저장되며 공유 캐시에는 저장되지 않는다.
- no-cache: 캐시 저장은 가능하지만, 사용 전 반드시 서버에 검증을 요청해야 한다.
- no-store: 민감하거나 일회성 데이터에 사용되며, 절대로 저장해서는 안 된다.
- max-age: 리소스의 유효 기간을 초 단위로 설정한다. 예를 들어
max-age=600
은 10분 동안 유효하다. - must-revalidate: 만료된 캐시는 서버 확인 없이 사용할 수 없다.
- s-maxage: 공용 캐시(CDN 등)에만 적용되며, max-age를 덮어쓴다.
ETag / If-None-Match
ETag
은 리소스의 고유한 식별자 역할을 한다. 해시값 형태로 리소스 변경 여부를 추적할 수 있다. 클라이언트는 이전에 받은 ETag 값을 If-None-Match
요청 헤더에 담아 보내며, 서버는 리소스가 변경되지 않았다면 304 Not Modified
로 응답한다. 이 방식은 정확한 캐시 검증을 가능하게 한다.
Last-Modified / If-Modified-Since
Last-Modified
는 리소스의 최종 수정 시점을 나타낸다. 클라이언트는 해당 값을 If-Modified-Since
요청 헤더로 전송하며, 서버는 리소스가 그 이후로 수정되지 않았다면 304 Not Modified
로 응답한다. 시간 단위로 동작하기 때문에 ETag보다 정밀도는 낮지만 구현이 간단하다.
블로그 서비스에서의 기능별 캐싱 전략 생각해보기
블로그 서비스를 개발한다고 가정하고 각 기능에 맞는 캐싱 전략을 판단해보려한다.
정적 리소스 (CSS, JS, 이미지 등)
빌드 시 해시를 포함한 파일명을 생성하여 URL이 변경되도록 구성한다. 브라우저는 해당 URL에 대해 Cache-Control: public, max-age=31536000, immutable
헤더를 통해 1년 동안 캐시한다. 이때 immutable은 리소스가 절대 변경되지 않음을 의미하며, 불필요한 재검증 요청을 차단할 수 있다.
블로그 글 본문
상대적으로 덜 자주 변경되지만, 변경 가능성이 있는 콘텐츠이다. Cache-Control: public, max-age=600
과 함께 ETag 또는 Last-Modified 헤더를 활용하여 유효 시간이 지나면 서버 검증을 거쳐 캐시를 갱신하도록 한다.
관리자 페이지 및 글쓰기 화면
민감한 데이터를 포함하거나 실시간성이 필요한 페이지이다. 캐시 저장을 방지하기 위해 Cache-Control: no-store
헤더를 적용한다. 이는 로그인 페이지나 결제 페이지에도 동일하게 적용된다.
API 응답
- 변경이 자주 일어나는 API는
Cache-Control: no-cache 또는 no-store
를 적용한다. - 인기 글 목록처럼 변동이 적은 데이터는
s-maxage, stale-while-revalidate 등을 활용하여 CDN 캐싱
을 구성한다. 이 방식은 프론트엔드 프레임워크의 ISR 방식과 유사한 형태이다.
실무에서 마주치는 캐싱 상황과 해결법
이미지가 변경되지 않는 문제
이미지를 변경했음에도 브라우저에서 이전 이미지를 계속 보여주는 경우가 있다. 이는 브라우저 캐시 때문이다. 해결 방법으로는 URL에 버전 쿼리 파라미터를 추가하거나(?v=2), 파일명을 해시 기반으로 변경하여 캐시 무효화를 유도한다.
HTML 문서 갱신 문제
새로운 배포 후에도 브라우저에서 구버전 HTML이 유지되는 경우, 브라우저가 HTML을 캐시하고 있기 때문이다. Cache-Control: no-cache, must-revalidate
를 설정하여 서버 재검증을 강제해야 한다. 최신 HTML을 통해 최신 JS와 CSS가 로딩되므로 중요하다.
로그인 정보 노출 문제
공용 캐시가 설정된 경우, 다른 사용자의 데이터가 잘못 보여질 수 있다. 이를 방지하기 위해 로그인 후 응답에는 Cache-Control: private 또는 no-store
를 반드시 적용해야 한다.
정리
캐시는 단순히 성능 향상 도구가 아니다. 제대로 설계하지 않으면 오히려 버그와 보안 문제가 발생할 수 있다. 정적 자원, HTML, API 응답 등 각 리소스의 특성을 고려한 전략적 캐싱이 필요하다.