RAG 캐시, 그냥 질문을 키로 쓰면 되는 거 아닌가
← 전체 목차 · 이전: 단일 라운드 RAG는 완벽한데 다중턴만 가면 무너진다 · 다음: 분산된 문서 증거를 어떻게 조립하는가
"사용자 질문을 캐시 키로 저장하고, 같은 질문이 오면 과거 답을 그대로 돌려준다." 이 답은 절반만 맞다. 그것은 정확 매칭(KV) 캐시이지 시맨틱 캐시가 아니다. 트래픽이 많고 의미는 같은데 표현이 다른 질문의 비중이 큰 실서비스에서는, 표현만 바뀌어도 적중하지 못하는 정확 매칭이 거의 무력하다. 그렇다고 적중률을 올리려고 유사도 기준을 느슨히 풀면 곧바로 **오적중(그릇된 매칭)**이라는 새로운 구덩이에 빠진다.
정확 매칭 캐시와 시맨틱 캐시는 같은 "캐시"라는 이름을 쓸 뿐 완전히 다른 기술 축이다.
| 정확 매칭 캐시 | 시맨틱 캐시 |
|---|
| 판단 기준 | 문자열 동일 | 임베딩 유사도 |
| 실패 모드 | 누락(Miss) — 성능만 손해 | 오적중(그릇된 매칭) — 오답을 그대로 출력 |
| 리스크 등급 | 낮음 | 높음 |
왜 위험한가 — 오적중은 침묵하지 않는다
정확 매칭이 실패하면 그냥 다시 계산할 뿐이다. 시맨틱 캐시가 실패하면 "의미는 비슷하지만 정답은 다른" 질문에 과거의 엉뚱한 답을 확신에 찬 어조로 돌려준다. 그리고 이 오답은 캐시에 남아 있는 한 같은 시간대에 들어오는 모든 유사 질문에 반복 적용된다 — 사고 규모가 QPS에 비례해 커지는 이유다.
캐시 오염 사고의 전형적 시간선
──────────────────────────────
① 오염된 응답이 캐시에 쓰인다 (임계값이 관대해 오적중 발생)
② 유사 질문이 동일 캐시를 반복 적중 (사고가 확산)
③ 사용자/모니터링이 이상을 발견
④ 관련 캐시를 일괄 실효(invalidate)
⑤ 사후 복기 — 임계값·트리거 조건을 재정의
이 5단계를 서술하지 못하면 "방안은 압니다"이지 "다뤄 봤습니다"가 아니다.
1층: 유사도 임계값은 상수가 아니라 업무 허용오차의 함수다
가장 흔한 실패는 **전사에 하나의 임계값(예: 0.9)**을 박아 넣는 것이다. 합규/가격/의료처럼 오답 허용오차가 거의 0인 업무와, 사내 잡담형 문의처럼 오답의 대가가 작은 업무를 같은 기준으로 캐시하면, 리스크가 가장 민감한 업무 쪽으로 위험이 그대로 전가된다.
| 업무 등급 | 예시 | 캐시 정책 |
|---|
| 엄금 캐시 | 실시간 가격, 합규 문답, 개인화 답변 | 캐시 대상에서 원천 제외 |
| 고정확 필수 | 고객 응대, 제품 문의 | 시맨틱 캐시 + 답변 일치성 검증 동반 |
| 저민감 | 사내 일반 안내 | 느슨한 TTL 캐시로 시작, 점진 강화 |
2층: 짧은 TTL은 최종 방어이지 근본 관리가 아니다
"만료 시간을 짧게 잡아 둔다"는 후보 답이 시험에서 가장 먼저 탈락하는 이유는, TTL이 오답의 생존 시간만 줄일 뿐 오답 자체를 없애지 못하기 때문이다. 진짜 관리는 두 축이다 — 지식베이스 갱신과 연동된 능동 실효(주동), 그리고 TTL 만료(수동, 최종 방어용).
캐시 일관성 = 능동 실효 + 수동 TTL
능동: 지식베이스 갱신 이벤트 → 관련 캐시 일괄 실효 태스크 트리거
수동: TTL 과기 — 능동 갱신이 누락된 경우의 마지막 방어선
지식베이스가 갱신됐는데 캐시가 여전히 구 응답을 서빙하는
그 구간이 "캐시 불일치 시간 창"이며, 이것도 측정 대상이다.
3층: 캐시 입도 — 정답을 통째로 캐시할 것인가, 조각을 캐시할 것인가
| 캐시 입도 | 적중률 | 저장/조립 비용 |
|---|
| 문답쌍 전체 캐시 | 낮음(질문이 조금만 달라도 미스) | 낮음 |
| 검색 결과(조각) 레벨 캐시 | 높음 | 조립·정렬 비용 발생 |
입도 선택은 적중 수익과 저장 비용을 분리하는 설계 결정이지 기본값이 아니다 — 어느 쪽이 맞는지는 질문 재현율과 지식베이스 갱신 빈도를 보고 정한다.
캐시 방안 3단 판정
| 판정 | 조건 | 처치 |
|---|
| 가용 | 내부 저민감 문의, 짧은 TTL을 최종 방어로 | 우선 적용 후 점진 강화 |
| 수익은 있으나 고위험 | 적중 수익 있음, 그러나 창구 오염 리스크 존재 | 일치성 검증 보강 필수 |
| 불가 | 무검증, 고동시성에서 오답이 대량 확산 | 상용 서비스 배치 금지 |
상용 배치 문 앞의 철칙
실효 메커니즘도 없고 일치성 검증도 없는 시맨틱 캐시는 그대로 배포 금지.
핵심 통찰
- 정확 매칭과 시맨틱 캐시는 실패 모드가 정반대다 — 전자의 실패는 누락(성능 손해)이고 후자의 실패는 오적중(정답 오염)이다. "캐시를 붙였다"는 한 문장으로 두 기술을 뭉뚱그리면, 리스크 모델이 전혀 다른 두 시스템을 같은 잣대로 설계하게 된다.
- 유사도 임계값은 값이 아니라 업무 허용오차의 함수다 — 0.9라는 숫자 자체는 아무 의미가 없다. 같은 임계값을 전사에 하드코딩하는 것은 가장 민감한 업무의 위험 허용치를 가장 둔감한 업무에까지 강요하는 것과 같다.
- 짧은 TTL은 근본 관리 방안이 아니라 최종 방어다 — 오답의 존속 시간을 줄일 뿐 오답의 발생을 막지 못한다. 진짜 치리는 지식베이스 갱신과 캐시 실효를 같은 이벤트 스트림에 묶는 능동 연동이다.
- 캐시 불일치는 "없다"가 아니라 "시간 창의 길이"로 관리해야 한다 — 완벽한 일관성을 주장하는 대신, 지식베이스 갱신부터 캐시 실효까지 걸리는 시간을 측정 가능한 값으로 만들고 그 창을 줄이는 것이 목표다.
- 고동시성은 오적중을 "개별 사례"에서 "대량 확산"으로 바꾸는 배수기다 — 한 번 오염된 캐시가 피크 시간대에 수천·수만 번 읽히면 사고 규모는 QPS에 정비례한다. 이것이 캐시 오염이 일반 버그보다 위험한 구조적 이유다.
- 캐시 입도는 적중 수익과 저장/조립 비용을 맞바꾸는 설계 선택이다 — 문답쌍 전체 캐시는 싸지만 적중률이 낮고, 조각 레벨 캐시는 적중률이 높지만 조립 비용이 든다. 기본값이 아니라 데이터를 보고 결정할 항목이다.
- 사고를 시간선으로 복기할 수 있는가가 "읽었다"와 "다뤄 봤다"를 가른다 — 오염 작성 → 확산 → 발견 → 일괄 실효 → 복기의 다섯 단계를 구체적으로 서술할 수 있어야 실제 운영 경험이 있다는 신호다.
- 캐시는 성능 최적화 컴포넌트가 아니라 정확성 구성요소로 다뤄야 한다 — 실효 메커니즘과 일치성 검증이 없는 시맨틱 캐시를 "속도를 위한 부가기능"으로 취급하는 순간, 그것은 곧 정답 오염 경로가 된다.
엔지니어링 실전 Tips
- 업무 등급별로 캐시 대상 자체를 분리할 것: 실시간 가격·합규 문답처럼 오답 허용오차가 0에 가까운 질의는 애초에 캐시 대상에서 제외하는 것이 임계값 튜닝보다 안전하다.
- 적중률과 오적중률을 항상 짝으로 볼 것: 적중률은 올릴수록 좋아 보이는 단방향 지표라 임계값을 계속 풀게 만든다. 오적중률이라는 대구 지표 없이 적중률만 보고하면 리스크가 숨는다.
- 주동 예열 + 피동 적중을 함께 쓸 것: 순수 피동 적중은 피크 시간대 콜드스타트에서 한꺼번에 관통당하고, 순수 주동 예열은 롱테일 질문을 못 덮는다. 핫 이슈는 예열, 나머지는 피동 적중으로 역할을 나눌 것.
- 실효 태스크는 배치로 처리 가능해야 한다: 지식베이스 갱신은 대량 이벤트다. 실효가 키 단위로만 가능하면 대버전 갱신 한 번에 불일치 시간 창이 크게 벌어진다.
- 고정확 모듈은 별도 링크로 뺄 것: 고객 응대·제품 문의·합규 문답은 독립된 준입 기준과 강제 일치성 검증을 갖고, 내부 저민감 문의와 정책을 공유하지 않는다.
- 캐시 오염 사고 대응은 사전에 템플릿화할 것: "오염 작성 → 확산 범위 → 발견 경로 → 일괄 실효 → 복기 조치"를 고정 포맷으로 만들어 두면 치리 자산이자 사고 대응 매뉴얼이 된다.
- 캐시 키에 지식베이스 버전을 포함시킬 것: 질문이 같아도 지식베이스가 갱신되면 다른 캐시 항목이어야 한다. 버전을 키에 넣지 않으면 갱신 후에도 옛 답이 계속 나온다.
- 더 파고들 방향: 캐시 적중 후 경량 재검증(질문-답 매칭도를 소형 모델로 2차 확인해 "한 번 왕복"을 "한 번 왕복 + 경량 검증"으로 바꾸기), 캐시 불일치 시간 창의 SLO화(지식베이스 갱신 후 N분 내 전량 실효 같은 약속치로 전환), 멀티테넌트 환경에서의 캐시 격리(동일 질문이 테넌트별로 다른 지식베이스에 걸리면 교차 테넌트 적중 자체가 오염이 된다).