목차
Cache-Control이 뭘까?
웹 서버와 브라우저 사이에서 "이 데이터를 얼마나 오래 저장해도 되는지" 알려주는 지시사항이다. 매번 서버에 요청하는 건 비효율적이니까, 브라우저나 중간 프록시 서버가 응답을 저장해두고 재사용할 수 있게 해준다.
왜 필요한가?
간단한 예를 들어보자. 네이버에 접속할 때마다 로고 이미지를 매번 다운로드한다면? 네트워크 낭비고 서버 부하도 늘어난다. 하지만 로고는 자주 바뀌지 않으니 브라우저에 저장해두고 재사용하면 훨씬 빠르고 효율적이다.
기본 동작 원리
- 첫 요청: 브라우저가 서버에 리소스를 요청한다
- 응답 + 헤더: 서버가 리소스와 함께 Cache-Control 헤더를 보낸다
- 캐시 저장: 브라우저가 헤더의 지시사항에 따라 캐시를 저장한다
- 재요청: 같은 리소스를 다시 요청할 때, 캐시가 유효하면 서버에 요청하지 않고 저장된 것을 사용한다
주요 지시어들
max-age=초
캐시를 몇 초 동안 유효하게 저장할지 지정한다.
Cache-Control: max-age=3600
이 경우 1시간(3600초) 동안은 서버에 재요청하지 않고 캐시된 데이터를 사용한다.
no-cache
이름과 달리 "캐시하지 마라"가 아니다. "캐시는 하되, 사용하기 전에 서버에 확인해라"라는 의미다. 서버가 "변경 없음(304)"이라고 응답하면 캐시를 사용하고, 변경되었으면 새 데이터를 받는다.
Cache-Control: no-cache
no-store
진짜로 캐시하지 말라는 지시어다. 민감한 정보(개인정보, 금융 데이터 등)에 사용한다.
Cache-Control: no-store
public vs private
- public: 중간 프록시 서버나 CDN도 캐시할 수 있다
- private: 브라우저만 캐시할 수 있다 (사용자별 데이터에 적합)
Cache-Control: public, max-age=86400
Cache-Control: private, max-age=3600
must-revalidate
캐시가 만료되면 반드시 서버에 재검증을 요청해야 한다. 만료된 캐시를 절대 사용하지 않는다.
Cache-Control: max-age=3600, must-revalidate
실전 사용 예시
정적 파일 (이미지, CSS, JS)
자주 바뀌지 않으니 오래 캐시한다.
Cache-Control: public, max-age=31536000
1년 동안 캐시한다. 파일이 변경되면 파일명을 바꿔서 배포하는 것이 일반적이다 (예: style.v2.css).
API 응답 (자주 변하는 데이터)
Cache-Control: no-cache
또는
Cache-Control: max-age=60
짧은 시간만 캐시하거나, 매번 서버에 확인하도록 한다.
민감한 데이터
Cache-Control: no-store, private
절대 캐시하지 않고, 혹시 모를 상황에 대비해 private도 지정한다.
FastAPI에서 사용하기
FastAPI에서는 Response 객체를 통해 헤더를 설정할 수 있다.
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/static-data")
def get_static_data(response: Response):
response.headers["Cache-Control"] = "public, max-age=3600"
return {"data": "이 데이터는 1시간 동안 캐시됨"}
@app.get("/dynamic-data")
def get_dynamic_data(response: Response):
response.headers["Cache-Control"] = "no-cache"
return {"data": "항상 최신 데이터"}
@app.get("/sensitive-data")
def get_sensitive_data(response: Response):
response.headers["Cache-Control"] = "no-store, private"
return {"data": "민감한 정보"}
주의사항
1. 기본값은 브라우저마다 다르다
Cache-Control 헤더가 없으면 브라우저가 임의로 판단한다. 명시적으로 지정하는 게 좋다.
2. HTTPS에서만 제대로 작동하는 경우도
일부 브라우저는 HTTP에서는 캐시를 제한적으로 처리한다.
3. 조합이 중요하다
Cache-Control: public, max-age=3600, must-revalidate
이렇게 여러 지시어를 조합해서 사용할 수 있다.
4. ETag와 함께 사용
Cache-Control: no-cache와 함께 ETag 헤더를 사용하면, 서버는 실제 내용이 변경되지 않았을 때 304 응답만 보내서 대역폭을 절약할 수 있다.
정리
- max-age: 캐시 유효 시간 설정
- no-cache: 캐시하되 매번 서버 확인
- no-store: 아예 캐시하지 않음
- public/private: 누가 캐시할 수 있는지 제어
- must-revalidate: 만료 시 반드시 재검증
적절한 캐시 전략은 서버 부하를 줄이고 응답 속도를 크게 개선한다. 정적 파일은 길게, API는 짧게 또는 no-cache, 민감한 데이터는 no-store로 설정하는 것이 일반적인 패턴이다.
'Web 일반' 카테고리의 다른 글
| [Web 일반] IP Binding (0) | 2025.10.09 |
|---|---|
| [Web 일반] IP 주소 0.0.0.0의 의미와 활용 (0) | 2025.05.31 |
| [Web 일반] HTTPS 동작 원리 (0) | 2025.05.08 |
| [Web 일반] 의존성 관리: Dependency 파일과 Lock 파일 (0) | 2025.04.11 |
| [Web 일반] CORS 에러 발생과 해결 방법 (2) | 2025.01.02 |