본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 26. 10:27

단 한 줄의 캐시 키 버그로 인해 매달 187달러를 낭비하고 테넌트 간 광고주 데이터가 유출되었습니다

요약

Cloudflare Worker 환경에서 테넌트 ID가 누락된 캐시 키로 인해 데이터 유출과 비용 폭증이 발생한 사례를 분석합니다. 모듈 범위 변수가 요청 간에 공유되어 발생하는 격리 문제를 다루며, 이를 해결하기 위한 캐시 키 네임스페이스 수정 및 검증 로직 구현 방법을 제시합니다.

핵심 포인트

  • Cloudflare Worker의 모듈 범위 변수는 요청 간에 공유되어 상태가 유지됨
  • 잘못된 캐시 키로 인해 테넌트 간 데이터 유출 및 불필요한 토큰 소비 발생
  • 캐시 키에 테넌트 ID를 포함하고 PostToolUse 훅으로 검증 필요
  • 장기 실행 프로세스(Node.js)에서는 AsyncLocalStorage 사용 권장

지난달 제 Anthropic 청구 금액 312달러 중 60%는 단 하나의 버그, 즉 테넌트 ID(tenant ID)가 누락된 MCP 라우터 캐시 키(cache key) 때문에 발생했습니다.

해결책은 말 그대로 이것이었습니다:

// 수정 전
const cacheKey = `mcp:context:${requestId}`;

...

그 누락된 한 구간 때문에, 활성화된(warm) Cloudflare Worker 인스턴스들이 광고주 A의 Vectorize 결과를 광고주 B의 도구 응답으로 제공하고 있었습니다. 데모가 아닌 실제 운영 중인 광고 분석 SaaS에서 말이죠.

직관에 어긋나는 부분은 이 점입니다: 저는 V8 격리(isolate) 경계가 저를 보호해 줄 것이라고 가정했습니다. 하지만 그렇지 않습니다 — 대부분의 사람들이 생각하는 방식으로는 말이죠. 격리 수준의 격리(Isolate-level isolation)는 별도의 Worker 배포 사이에 적용되는 것이지, 동일한 활성화된 Worker 인스턴스에 접속하는 두 개의 동시 요청 사이에는 적용되지 않습니다. 모듈 범위 변수(Module-scope variables)는 요청 간에 유지됩니다. 따라서 모듈 수준에서 초기화한 모든 컨텍스트 매니저(context manager)나 캐시 객체는 Worker에서도 공유 상태(shared state)가 됩니다.

이 실패 모드는 찾아내는 데 6주가 걸릴 정도로 매우 미묘했습니다. Vectorize 쿼리량이 예상보다 3배 많았던 것이 첫 번째 신호였습니다. 로그를 파헤친 결과, 테넌트 a9f2에 대한 캐시 히트(cache hit)가 테넌트 b3c1에 속한 세션에 제공되고 있음을 발견했습니다. 오염된 캐시에는 벡터 검색(vector search) 결과가 포함되어 있었고, 이로 인해 잘못된 히트가 발생할 때마다 다운스트림 재요청(re-fetch) 체인이 트리거되었습니다. 그 연쇄 반응이 토큰 소비를 폭증시킨 원인이었습니다: 잘못된 캐시 데이터 → Claude가 새로운 컨텍스트로 재시도 → Sonnet 입력 토큰이 빠르게 누적됨.

캐시 키 네임스페이스(namespace)를 수정하고, 도구 응답 메타데이터에서 테넌트 ID 불일치 시 예외를 던지는 PostToolUse 훅(hook)을 추가한 후, Sonnet 입력 비용은 월 약 187달러에서 약 94달러로 감소했습니다. 같은 기간 동안 Vectorize 쿼리는 약 40% 감소했습니다.

유사한 스택을 사용하는 분들에게 주의를 당부하고 싶은 점이 하나 있습니다: 모든 것을 요청당 Workers의 ExecutionContext로 범위화하는 이 특정 해결 방식은 Fly.io와 같은 곳에서 실행되는 장기 실행 Node 프로세스에는 깔끔하게 적용되지 않습니다. 그곳에서는 AsyncLocalStorage가 적절한 기본 요소(primitive)입니다. Workers 패턴을 그대로 이식하면 잘못된 안전감을 느끼게 될 것입니다.

저는 PostToolUse 훅 (hook) 구현, KV/D1 캐시 키 강제 적용 패턴 (enforcement pattern), 그리고 이러한 격리 설계가 과한 경우를 포함한 전체적인 분석 내용을 riversealab.com에 작성했습니다.

전체 포스트 보기 →

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0