반응형

 

Cache-Control이 뭘까?

웹 서버와 브라우저 사이에서 "이 데이터를 얼마나 오래 저장해도 되는지" 알려주는 지시사항이다. 매번 서버에 요청하는 건 비효율적이니까, 브라우저나 중간 프록시 서버가 응답을 저장해두고 재사용할 수 있게 해준다.

왜 필요한가?

간단한 예를 들어보자. 네이버에 접속할 때마다 로고 이미지를 매번 다운로드한다면? 네트워크 낭비고 서버 부하도 늘어난다. 하지만 로고는 자주 바뀌지 않으니 브라우저에 저장해두고 재사용하면 훨씬 빠르고 효율적이다.

기본 동작 원리

  1. 첫 요청: 브라우저가 서버에 리소스를 요청한다
  2. 응답 + 헤더: 서버가 리소스와 함께 Cache-Control 헤더를 보낸다
  3. 캐시 저장: 브라우저가 헤더의 지시사항에 따라 캐시를 저장한다
  4. 재요청: 같은 리소스를 다시 요청할 때, 캐시가 유효하면 서버에 요청하지 않고 저장된 것을 사용한다

주요 지시어들

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로 설정하는 것이 일반적인 패턴이다.

반응형

+ Recent posts