한 사용자가 저희 번역 플러그인이 입력값과 관계없이 모든 요청에 대해 동일한 캐시 결과를 반환한다고 보고했습니다. 조사 결과 더 심각한 문제가 발견되었습니다. 플랫폼 전체에서 발생한 시맨틱 캐시 적중(hit)의 95%가 오탐(false positive)이었습니다. 199개의 서로 다른 번역 요청 중 198개의 요청 본문이 서로 달랐음에도 불구하고, 단 하나의 캐시된 응답이 모두에게 제공되고 있었습니다.
장기적인 에이전트 상태 유지와 프로덕션 요청 처리에 관심이 있다면, 이 게시물과 함께 AI 에이전트가 기억을 계속 잃어버리는 이유, 단일 API 키 챗봇 가이드, 그리고 AI API 속도 제한 가이드를 읽어보시는 것을 추천합니다.
핵심 요약
- 플랫폼 전체 시맨틱 캐시 적중의 95%가 오탐이었으며, 198개의 고유한 요청이 모두 동일한 하나의 캐시된 응답을 받았습니다.
- 근본 원인은 구조화된 입력입니다. 고정된 템플릿 텍스트가 임베딩 벡터를 지배하여, 내용이 바뀌어도 코사인 유사도(cosine similarity)에는 거의 영향을 주지 못합니다.
- 유사도 임계값을 높이는 것은 해결책이 되지 않습니다. 올바른 적중과 잘못된 적중의 분포가 겹치기 때문입니다. 시맨틱 캐시 신뢰성에 대한 최근 연구들도 동일한 패턴을 확인했습니다.
- 해결책은 2단계로 이루어집니다. 임베딩 전에 의미 있는 콘텐츠를 추출하고, 각 적중을 빠른 FNV-1a 핑거프린트 해시로 검증하는 것입니다. 이를 통해 오탐률을 약 95%에서 5% 미만으로 낮췄습니다.
- 모델 선택도 노출에 영향을 미칩니다. 긴 시스템 프롬프트와 JSON으로 감싼 입력은 어떤 모델이 완료(completion)를 수행하든 문제를 악화시킵니다. 캐시된 트래픽을 라우팅할 모델을 결정 중이라면 TokenLab의 모델 디렉토리(2026-07-07 관측 기준)에서 현재 모델 옵션을 확인하세요.
버그 보고서
보고 내용은 간단했습니다: "시맨틱 캐시를 비활성화했는데 모든 번역이 같은 결과를 반환합니다."
3개의 요청 ID, 3개의 다른 번역 세그먼트, 동일한 캐시 응답. 요청 본문은 1,564바이트에서 8,676바이트까지 다양했습니다. 캐시된 응답 ID는 모두 chatcmpl-DG6J03nhdvcF7Ek0C8rJkjh7lN9pF로 동일했습니다.
첫 번째 의심은 사용자의 캐시 설정이 적용되지 않았다는 것이었습니다. 확인 결과 이는 별도의 데이터 소스 동기화 버그(관리자 패널은 한 테이블에 쓰고, API 게이트웨이는 다른 테이블에서 읽는 문제)였습니다. 이를 수정해도 문제의 절반만 해결되었습니다. 캐시가 활성화되고 올바르게 작동하더라도, 시맨틱 캐시는 절대 일치해서는 안 될 요청들을 일치시키고 있었습니다.
프로덕션 데이터
ClickHouse에서 24시간 동안의 캐시 적중 데이터를 추출했습니다. 수치는 매우 나빴습니다.
| 모델 | 총 요청 | 캐시 적중 | 고유 요청 | 고유 응답 | 적중률 |
|---|---|---|---|---|---|
| DeepSeek V4 Flash | 200 | 199 | 198 | 1 | 99.5% |
| glm-4.6-thinking | 100 | 38 | 13 | 1 | 38% |
| gpt-5-nano | 31 | 29 | 28 | 2 | 93.5% |
| gpt-oss-120b | 18 | 17 | 17 | 1 | 94.4% |
| qwen3-vl-flash | 17 | 16 | 16 | 1 | 94.1% |
198개의 고유한 번역 요청이 모두 동일한 하나의 캐시된 응답을 반환했습니다. 이것은 캐시가 아닙니다. 상수를 반환하는 고장 난 함수일 뿐입니다.
영향을 받은 모든 모델은 두 가지 공통점이 있었습니다. 모든 요청이 단일 사용자로부터 왔으며, 가변적인 사용자 콘텐츠와 함께 고정된 시스템 프롬프트 템플릿을 사용했다는 점입니다. 플랫폼에서 사용 가능한 현재 모델 목록은 라인업이 자주 변경되므로 TokenLab의 모델 디렉토리(2026-07-07 관측 기준)를 확인하는 것이 정확합니다.
시스템에서 이를 감지하는 방법
같은 문제가 있는지 확인하기 위해 저희 로그가 필요하지는 않습니다. 가장 빠른 신호는 모델별 응답 다양성입니다. 모델의 캐시 적중률은 높은데 고유 응답이 거의 없다면, 여러 질문에 대해 하나의 답변만 제공하고 있는 것입니다.
일반화된 ClickHouse 스타일 쿼리는 다음과 같습니다:
SELECT
model,
count() AS total_hits,
uniqExact(substring(response_body, 1, 200)) AS unique_responses,
round(uniqExact(substring(response_body, 1, 200)) / count(), 3) AS diversity_ratio
FROM request_logs
WHERE cache_hit = true
GROUP BY model
ORDER BY total_hits DESC;
건전한 캐시는 diversity_ratio가 1.0에 가깝습니다. 즉, 대부분의 적중이 서로 다른 입력에 대해 서로 다른 응답을 반환합니다. 비율이 0에 가깝다면 많은 요청이 소수의 캐시된 답변으로 수렴되고 있다는 뜻입니다. 실제 입력이 다양한 모델에서 이 비율이 0.5 미만이라면 조사가 필요합니다.
응답 본문을 로깅하지 않는다면 더 저렴한 대안도 있습니다. 고유 요청 본문 수와 캐시에서 제공된 고유 응답 수를 비교하는 것입니다. 198개의 고유 요청이 1개의 응답에 매핑된다면, 캐시가 의미를 일치시키는 것이 아니라 상용구(boilerplate)를 일치시키고 있는 것입니다.
두 번째 징후는 구조화된 워크로드에서 발생하는 사용자 불만입니다. 번역 플러그인, 요약 도구, 양식 작성 도구, JSON 입출력 도구 등이 일반적인 범인입니다. 이들은 가변적인 콘텐츠를 고정된 템플릿으로 감싸기 때문입니다.
구조화된 입력에서 임베딩이 실패하는 이유
번역 플러그인은 다음과 같은 요청을 보냅니다:
System: "번역 API로 작동하십시오. 원시 JSON 객체 하나만 출력하십시오.
입력: {"targetLanguage":"<lang>","title":"...","segments":[...]}"
User: {"targetLanguage":"zh","title":"제품 페이지",
"description":"제품 설명 번역",
"tone":"격식체",
"segments":[{"text":"여기에 실제 가변 콘텐츠"}]}
시스템 프롬프트는 모든 요청에서 동일합니다. 사용자 메시지는 targetLanguage, title, description, tone이 고정된 JSON 객체입니다. 오직 segments[].text만 변경됩니다.
시맨틱 캐시가 임베딩을 위해 텍스트를 추출할 때, 시스템 프롬프트와 사용자 메시지를 연결합니다. 고정된 템플릿이 전체 텍스트의 약 80%를 차지합니다. 임베딩 모델(all-mpnet-base-v2, 768차원)은 이를 템플릿 구조가 지배하는 벡터로 압축합니다. 실제 번역 내용은 거의 영향을 주지 못합니다.
결과: "'Hello world' 번역"과 "'분기별 재무 보고서에 따르면 수익이 15% 증가했습니다' 번역" 사이의 코사인 유사도가 0.95를 초과합니다. 저희 임계값은 0.95입니다. 모든 번역 요청이 첫 번째 캐시된 항목과 일치하게 됩니다.
로그를 파헤쳐 본 결과, 이 문제가 발생하는 세 가지 방식을 발견했습니다:
번역 플러그인이 가장 심각합니다. 고정된 JSON 키와 값이 실제 번역 세그먼트를 압도합니다. DeepSeek V4 Flash와 gpt-5-nano 모두 이 문제에 해당합니다.
문맥 요약 어시스턴트는 같은 문제의 다른 형태를 보였습니다. 시스템 프롬프트가 너무 길어서 5KB에서 47KB에 이르는 사용자 콘텐츠가 임베딩에 거의 반영되지 않았습니다. 이것이 glm-4.6-thinking이 모든 대화에 대해 동일한 요약을 반환하게 된 이유입니다.
세 번째 패턴은 더 미묘합니다. gpt-oss-120b와 qwen3-vl-flash의 경우, 모든 요청의 처음 500자가 바이트 단위로 동일했습니다. 가변적인 콘텐츠는 그 뒤에 나왔지만, 임베딩은 이미 공유된 접두사에 의해 지배된 상태였습니다.
연구 결과
이는 새로운 문제가 아닙니다. 최근 논문들이 이를 정량화했습니다.
UC Berkeley의 vCache 프로젝트는 올바른 캐시 적중과 잘못된 캐시 적중의 유사도 분포가 크게 겹친다는 것을 발견했습니다. 즉, 고정된 임계값으로는 실제 일치 항목과 구조적으로 유사한 오탐 항목을 명확하게 분리할 수 없습니다. 이 발견은 저희가 프로덕션에서 본 것과 정확히 일치합니다. 번역 플러그인의 오탐은 0.95 이상에 집중되었으며, 이는 합법적인 의역 일치 항목이 존재하는 범위 내에 있습니다.
시맨틱 캐시 신뢰성에 대한 다른 최근 연구들도 비슷한 결론에 도달했습니다. 원시 임베딩 유사도는 캐시 정확성을 위한 필요조건일 뿐 충분조건은 아니며, 이에만 의존하는 모든 프로덕션 시스템은 구조화되고 템플릿이 많은 트래픽에서 상당한 오탐률을 예상해야 합니다.
2단계 해결책
1단계는 콘텐츠 추출입니다. 임베딩 전에 고정된 시스템 프롬프트와 템플릿 스캐폴딩을 제거하고, 주변 JSON 키나 상용구가 아닌 실제 segments[].text 콘텐츠와 같은 가변 페이로드만 임베딩합니다. 이것만으로도 임베딩 벡터의 신호 대 잡음비가 극적으로 증가합니다.
2단계는 핑거프린트 검증입니다. 더 나은 추출을 하더라도 거의 동일한 콘텐츠는 여전히 높은 유사도 점수를 생성할 수 있습니다. 캐시 적중을 제공하기 전에, 들어오는 요청과 캐시된 항목의 추출된 콘텐츠에 대해 빠른 해시(저희는 FNV-1a 사용)를 계산합니다. 해시가 정확히 일치하면 캐시를 제공합니다. 일치하지 않으면 새로운 완료를 수행하거나, 더 가치 있는 트래픽의 경우 바이트가 아닌 의미를 점수화하는 저렴한 검증 호출로 라우팅합니다.
실수는 검증을 완전히 건너뛰고 원시 코사인 유사도만 신뢰하는 것입니다. 표에 있는 모든 접근 방식이 그것보다 낫습니다. 쿼리 유형에 맞는 가장 저렴한 방법으로 시작하고, 실제 의역 누락을 측정할 때만 단계를 높이십시오.
이 두 단계를 함께 적용하여 영향을 받는 트래픽의 오탐률을 약 95%에서 5% 미만으로 낮췄습니다.
시맨틱 캐싱이 잘못된 도구인 경우
캐싱은 공짜 엔지니어링이 아니며, 일부 워크로드는 캐싱할 가치가 전혀 없습니다.
- 카디널리티가 높고 반복이 적은 트래픽. 거의 모든 요청이 고유한 경우(예: 일회성 창의적 생성)에는 적중률이 너무 낮아 임베딩 오버헤드를 정당화할 수 없습니다. 모든 것을 임베딩하는 비용을 지불하고 거의 이득을 보지 못합니다.
- 신선해야 하는 출력. 시간 민감성, 실시간 데이터, 개인화된 결과, "오늘"이라는 단어가 포함된 모든 것은 기술적으로 일치하더라도 캐시에서 오래된 답변을 반환할 수 있습니다. 한 시간 전에는 맞았지만 지금은 틀린 답변일 수 있습니다.
- 엄격한 정확성 도메인. 의료, 법률, 금융 답변의 경우 단 한 번의 오탐이 절약한 비용보다 더 나쁠 수 있습니다. 여기서 캐싱을 사용한다면 검증 계층은 선택이 아닌 필수이며, LLM 수준의 확인만이 유일하게 허용될 수 있습니다.
- 모델 호출 자체가 저렴한 아주 작은 프롬프트. 임베딩, 유사도 검색, 검증에는 자체 비용이 듭니다. 기본 완료가 저렴한 모델에서 수백 토큰 정도라면, 캐싱 비용이 절약하는 비용보다 더 클 수 있습니다.
캐싱은 반복적이고 템플릿이 많으며 비용이 많이 드는 완료 작업에서 빛을 발하며, 이는 정확히 오탐이 발생하기 가장 쉬운 워크로드이기도 합니다. 그 긴장감 때문에 검증 계층이 중요합니다. 주된 목표가 비용 관리라면 캐싱과 더 저렴한 모델 라우팅을 결합하는 것도 좋습니다. 가격 비교와 코딩을 위한 최고의 AI 모델 가이드에서 토큰당 절감액이 어디서 발생하는지 다루고 있으며, TokenLab의 모델 디렉토리(2026-07-07 관측 기준)는 DeepSeek V4 Flash나 Gemini 3.5 Flash와 같은 저비용 라우팅 선택지를 포함한 현재 옵션을 보여줍니다. 라우팅 계획을 확정하기 전에 링크된 디렉토리에서 현재 가격을 확인하십시오.
왜 그냥 임계값을 높이지 않나요?
저희 임계값은 이미 0.95입니다. 높여도 도움이 되지 않습니다. 문제는 실제 내용이 무엇이든 구조적으로 유사한 입력은 0.95 이상의 유사도 점수를 생성한다는 것입니다.
vCache의 데이터가 이를 뒷받침합니다. 올바른 적중과 잘못된 적중의 유사도 분포가 너무 많이 겹쳐서 단일 차단값으로는 분리할 수 없습니다. 임계값을 0.99로 올리면 진정한 의역에 대한 합법적인 캐시 적중을 차단하게 되며, 저희의 번역 JSON 페이로드처럼 구조적으로 동일한 요청들은 내용과 관계없이 여전히 0.99 이상으로 집중될 것입니다. 임계값은 레버가 아닙니다. 입력 표현이 레버입니다. 이것이 바로 임계값을 높이는 것보다 1단계(콘텐츠 추출)와 2단계(핑거프린트 검증)가 효과적인 이유입니다. 이들은 비교가 얼마나 엄격한지가 아니라 무엇을 비교할지를 바꿉니다.
시맨틱 캐시를 구축하거나 유지 관리하는 경우, 임계값을 정확성 보장이 아닌 거친 필터로 취급하십시오. 임베딩이 요청의 가변 부분을 실제로 나타내도록 콘텐츠 추출과 결합하고, 저렴한 검증 단계를 추가하여 근소한 차이의 임베딩 일치가 프로덕션에서 조용히 잘못된 답변이 되지 않도록 하십시오.
캐시 검증 계층을 연결하기 전에 TokenLab의 모델 디렉토리를 시작하여 프론티어, 코딩 및 저비용 라우팅 모델 전반의 현재 가격과 벤치마크를 비교하십시오. 완료 엔드포인트 뒤에 어떤 모델이 있든, 추출과 핑거프린트를 결합한 접근 방식이 실제로 오탐을 해결하는 방법입니다.
자주 묻는 질문(FAQ)
유사도 임계값을 높이면 시맨틱 캐시 오탐이 해결되나요? 아니요. vCache 및 관련 연구에 따르면 올바른 적중과 잘못된 적중의 분포가 임계값 범위 전반에 걸쳐 겹치므로, 차단값을 높이는 것은 구조적으로 유사하지만 의미가 다른 요청을 안정적으로 필터링하지 못하면서 합법적인 일치 항목만 차단하게 됩니다.
시맨틱 캐시 적중을 검증하는 가장 저렴한 방법은 무엇인가요? 추출된 의미 있는 콘텐츠에 대한 핑거프린트 해시(FNV-1a 등)는 1밀리초 미만의 지연 시간을 추가하며 계산 비용이 무료입니다. 의역은 잡아내지 못하지만, 여기서 설명한 것과 같은 정확한 오탐을 제거하며, 이는 구조화된 워크로드에서 발생하는 대부분의 피해를 차지합니다.
이 문제는 완료를 수행하는 모델에 따라 달라지나요? 아니요. 오탐 문제는 완료 모델이 아니라 임베딩 및 매칭 계층에 있습니다. 시맨틱 캐시 뒤에 있는 모델이 DeepSeek V4 Flash든, glm-4.6-thinking이든, 혹은 더 새로운 모델이든, 캐시가 가변 콘텐츠와 함께 고정된 템플릿 텍스트를 임베딩한다면 동일한 방식으로 영향을 받습니다. 캐시된 파이프라인을 통해 라우팅할 모델을 결정할 때는 TokenLab의 모델 디렉토리(2026-07-07 관측 기준)에서 현재 모델 가용성을 확인하십시오.
출처
2026-07-07 기준 가격
- TokenLab model directory2026-07-07 기준 확인
- Generative Caching for Structurally Similar Prompts and Responses2026-07-09 기준 확인
- GPTCache paper2026-07-09 기준 확인
- RedisVL semantic caching docs2026-07-09 기준 확인
- GPTCache quick start2026-07-09 기준 확인



