Cache / CDN / Conditional Request

3줄 요약

  • 캐시는 latency와 origin 비용을 줄이지만, 잘못 쓰면 오래된 데이터와 다른 사용자의 데이터를 정답처럼 보여 주는 장애가 된다.
  • 백엔드는 Cache-Control, ETag, Last-Modified, Vary, CDN cache key, purge 정책을 API 계약의 일부로 다뤄야 한다.
  • 실전 디버깅은 브라우저 cache, CDN edge, origin app, application cache를 분리하고 Age, Via, X-Cache, CF-Cache-Status, ETag, origin log 도달 여부를 함께 본다.

핵심 정리

  • max-age는 신선하다고 볼 수 있는 시간이고, no-cache는 저장 금지가 아니라 재검증 필요이며, no-store는 저장 자체를 금지한다.
  • public은 공유 캐시에 저장될 수 있고, private은 브라우저 같은 개인 캐시에 한정된다. 인증/개인화 응답은 공유 캐시에서 매우 조심해야 한다.
  • 조건부 요청은 ETag/If-None-Match, Last-Modified/If-Modified-Since로 body 전송을 줄인다. 304 Not Modified는 오류가 아니라 재사용 허가다.
  • CDN은 origin 앞의 분산 cache다. cache HIT이면 origin app log가 없을 수 있고, cache key가 틀리면 query/header/cookie별 응답이 섞일 수 있다.
  • Purge는 긴 TTL 리소스를 즉시 무효화하지만, 범위가 넓으면 전 세계 edge가 한꺼번에 origin으로 몰리는 장애를 만들 수 있다.

헷갈리는 지점

  • no-cache를 “캐시하지 말라”로 이해하기 쉽다.
    • 핵심 판단 포인트는 no-cache는 저장은 가능하지만 재사용 전 origin revalidation이 필요하다는 것이다.
  • CDN HIT가 많으면 서버가 정상이라고 생각하기 쉽다.
    • 핵심 판단 포인트는 edge가 응답했을 뿐 origin, database, backend dependency는 죽어 있을 수 있다는 것이다.
  • 정적 파일과 개인화 API에 같은 캐시 정책을 적용하기 쉽다.
    • 핵심 판단 포인트는 fingerprint된 asset은 긴 TTL이 좋고, 사용자별 API는 private 또는 no-store가 필요한 경우가 많다는 것이다.
  • 304를 빈 body 오류로 오해하기 쉽다.
    • 핵심 판단 포인트는 client가 가진 cached body를 재사용하라는 정상 응답이며 관련 cache header가 유지되어야 한다는 것이다.

확인 질문

  • Cache-Control: no-cacheno-store의 차이는 무엇인가?
    • no-cache는 저장 후 재사용 전에 재검증하라는 뜻이고, no-store는 저장하지 말라는 뜻이다.
  • CDN cache key를 모르면 어떤 사고가 생길 수 있는가?
    • query, header, cookie, auth 상태가 다른 요청에 같은 캐시 응답이 재사용되어 잘못된 데이터나 개인정보가 노출될 수 있다.
  • purge보다 versioned URL이 더 안전한 경우는 언제인가?
    • 정적 asset처럼 파일명이 바뀌어도 되는 리소스는 purge보다 fingerprint/versioned URL과 긴 TTL이 배포 안정성에 유리하다.
  • cache 장애에서 origin log가 없다는 것은 무엇을 의미할 수 있는가?
    • 요청이 CDN이나 브라우저 cache에서 처리되어 origin app까지 도달하지 않았을 수 있다.