이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • cache 정합성 장애를 stale data, cache key 섞임, purge 실패, 배포 mismatch로 어떻게 나누는가?
  • 가격, 재고, 권한, 공지처럼 최신성이 중요한 데이터는 어떤 cache 전략이 필요한가?
  • 캐시 장애 보고에서 어떤 증거를 모아야 원인을 빠르게 좁힐 수 있는가?

개요

cache 정합성 장애는 사용자가 보는 응답과 origin의 실제 상태가 달라지는 문제다. 사용자는 “수정했는데 안 바뀐다”, “가격이 다르다”, “권한을 뺐는데 계속 보인다”라고 말한다. 백엔드는 이 증상을 브라우저 cache, CDN edge, application cache, DB replication, search index 지연 중 어디에서 생겼는지 분리해야 한다.

  • stale data는 TTL이나 revalidation 정책 때문에 이전 값이 보이는 문제다.
  • cache key 섞임은 서로 다른 요청이 같은 cache entry를 공유하는 문제다.
  • purge 실패는 무효화 이벤트가 edge/app cache에 도달하지 않은 문제다.
  • 배포 mismatch는 HTML, JS, API version이 서로 다른 시점의 조합으로 동작하는 문제다.

원리

cache 정합성은 세 가지 계약으로 관리한다.

  1. 허용 가능한 stale 시간
  2. 어떤 이벤트가 cache를 무효화하는지
  3. cache key가 어떤 요청 차이를 반영하는지

이 세 가지가 문서화되어 있지 않으면 장애 때 각 팀이 서로 다른 기대를 갖는다. 인프라 팀은 TTL대로 동작했다고 보고, 앱 팀은 수정 즉시 반영되어야 한다고 생각하는 식이다.

데이터 유형별 전략

데이터권장 전략이유
정적 assetfingerprint URL + 긴 TTLURL 변경으로 최신화
공지/블로그짧은 TTL + purge약간의 stale 허용
상품 가격짧은 TTL 또는 event purge잘못된 가격 노출 위험
재고cache 신중, 조건부 재검증구매 가능 여부와 연결
권한/멤버십private 또는 no-store권한 회수 지연 위험
사용자 프로필private cache, 사용자별 key개인정보 섞임 방지

배포 Mismatch

SPA나 SSR 서비스에서 자주 보는 문제는 HTML이 새 JS를 가리키는데 CDN에는 아직 JS가 없거나, 오래된 HTML이 새 API와 맞지 않는 경우다.

안전한 패턴은 다음과 같다.

  • asset은 content hash 파일명으로 배포한다.
  • 이전 asset을 즉시 삭제하지 않는다.
  • HTML은 짧은 TTL 또는 재검증을 사용한다.
  • API는 일정 기간 backward compatibility를 유지한다.
  • rollback 때 필요한 이전 asset이 남아 있는지 확인한다.

코드와 명령으로 확인하기

사용자가 보는 CDN 응답과 origin 응답을 비교한다.

curl -sI https://www.example.com/products/1 | grep -iE 'cache-control|age|etag|last-modified|x-cache|cf-cache-status'
 
curl -s https://www.example.com/products/1 -H 'Cache-Control: no-cache' -o cdn.json
 
curl -s https://origin.internal.example.com/products/1 \
  -H 'Host: www.example.com' \
  -o origin.json
 
diff -u origin.json cdn.json

사용자별 API라면 cookie/auth를 명시해 재현한다.

curl -i https://api.example.com/me \
  -H 'Authorization: Bearer test-token' \
  -H 'Cache-Control: no-cache'

Purge/Event 점검

정합성 장애에서는 시간 순서가 중요하다.

10:00 admin updates price
10:00 app commits DB transaction
10:00 event published price.updated
10:01 purge requested /products/1
10:02 edge A serves new price
10:05 edge B still serves old price

이 타임라인을 만들면 DB commit, event bus, purge API, CDN propagation, browser cache 중 어디가 늦었는지 보인다.

인프라 협업 포인트

  • purge 요청 로그와 CDN edge별 cache status를 앱 변경 이벤트와 같은 시간대로 맞춘다.
  • 인프라 팀에는 URL, cache key 후보, header, 사용자 영향 범위, stale 허용 시간을 제공한다.
  • 앱 팀은 수정 이벤트가 실제로 발행됐는지, purge 대상 URL/tag가 맞는지 확인한다.
  • 상품/가격/권한처럼 사업 위험이 큰 데이터는 TTL 결정을 PO/보안/운영과 함께 한다.

주니어가 자주 하는 오해

  • cache 문제는 purge 한 번으로 끝난다고 생각한다.
  • DB 값이 맞으면 사용자 화면도 곧 맞을 것이라 생각한다.
  • TTL을 짧게 줄이면 정합성 문제가 모두 해결된다고 생각한다.
  • cache key에 query/header/user 차이가 반영되는지 확인하지 않는다.

시니어의 설계 판단 기준

  • 데이터별로 stale 허용 시간, 무효화 이벤트, cache key 계약을 먼저 정한다.
  • 가격/권한/결제처럼 잘못 보이면 사업 리스크가 큰 데이터는 HIT율보다 정합성을 우선한다.
  • purge보다 versioned URL, tag 기반 purge, event-driven invalidation 중 어떤 방식이 실패를 덜 만드는지 비교한다.
  • 기업 운영에서는 CDN POP별 반영 지연, purge 권한, 감사 로그, 장애 영향 범위를 같이 본다.

실전 팁

  • cache invalidation은 “삭제”보다 “버전 전환”이 안전한 경우가 많다.
  • stale 허용 시간이 0초에 가까운 데이터는 cache 계층을 단순하게 유지한다.
  • 관리 화면에서 수정 후 “사용자 화면 확인” 버튼을 제공하면 실제 CDN 경로 검증에 도움이 된다.
  • cache key에 사용자 id를 넣는 것은 HIT율을 낮춘다. 정말 개인화가 필요한지, 아예 private/no-store가 나은지 판단한다.
  • 장애 보고에는 같은 URL의 여러 지역/브라우저/CDN POP 결과가 있으면 좋다.
  • 개인 프로젝트에서도 가격/권한/관리자 화면은 cache를 끄거나 매우 짧게 두고, asset은 fingerprint로 분리하면 단순하면서 안전하다.

위험 신호!

  • 가격/권한 변경이 TTL 만료까지 반영되지 않아도 된다는 합의가 없다.
  • purge 대상이 URL인지 tag인지 팀마다 다르게 이해한다.
  • cache key에서 query string을 무시하는데 API는 query로 필터링한다.
  • 배포 시 이전 asset을 삭제해 rollback이 깨진다.

확인 질문

확인 질문

  • cache 정합성 장애에서 타임라인이 중요한 이유는 무엇인가?
    • 데이터 변경, 이벤트 발행, purge 요청, edge 반영, 사용자 재요청 중 어디서 지연됐는지 분리할 수 있기 때문이다.
  • 정적 asset은 왜 purge보다 fingerprint URL이 유리한가?
    • 새 파일명이 새 cache key가 되어 긴 TTL을 유지하면서도 배포 최신화를 안전하게 만들 수 있기 때문이다.
  • 권한 변경 데이터는 cache에서 왜 위험한가?
    • 권한이 회수된 사용자가 stale 응답이나 공유 cache를 통해 계속 데이터를 볼 수 있기 때문이다.

참고 문서