2026년 8월 30일 일요일

RAG 종류 총정리 ⑬ (완결) — 한국어 조건과 결정 트리

열두 편을 한 장으로 접는다. 먼저 한국어로 서비스할 때만 적용되는 조건을 모으고, 그다음 "우리는 무엇부터 하나"를 결정 트리로 정리한다.

한국어 RAG의 다섯 가지 조건

  • 임베딩 기본값을 의심하되, 갈아타는 이득은 제한적이다. 고려대 KURE 리더보드 기준 한국어 8종 평균 nDCG@10은 KURE-v1 0.695 > BGE-m3 0.687 > multilingual-e5-large 0.664 > OpenAI text-embedding-3-large 0.617. OpenAI를 쓰고 있다면 5~8점을 그냥 버리는 셈이지만, 오픈 모델끼리는 격차가 0.3% 수준이라 상위권 안에서 바꿔 타는 건 의미가 없다. 예산은 파싱과 리랭커로(②·③편).
  • BM25는 형태소 분석기가 곧 품질이다. 조사 때문에 정확 매칭이 깨지므로 Nori(mecab-ko-dic)나 Kiwi가 필수고, 상품코드·티켓번호·모델명은 형태소 분석에서 빼고 keyword 필드로 색인해야 한다(②편).
  • 토큰 효율이 나빠 한도가 먼저 터진다. 컬리 사례에서 사내 문서의 약 85%가 임베딩 모델의 512토큰 한도를 넘겨 앞부분만 색인되고 있었다. 모델을 고를 때 컨텍스트 길이도 기준에 넣어야 한다.
  • 파싱에 0단계가 하나 더 있다. Mistral OCR·Docling·Marker·LlamaParse 어디도 HWP/HWPX를 네이티브로 받지 않는다. 공공·금융 문서라면 전용 파서가 파이프라인의 시작점이다(⑧편).
  • 생략이 대명사보다 어렵다. "환불돼요?"에는 치환할 앵커조차 없어서, 영어권 재작성 프롬프트를 번역만 하면 원문을 그대로 뱉는다. "생략된 주어·목적어를 복원하라"를 명시해야 한다(⑩편).

그리고 평가 자원의 공백

이 시리즈를 쓰며 반복해 확인한 사실이 있다. 한국어에는 참고할 벤치마크가 거의 없다. 가장 널리 쓰이는 한국어 RAG 리더보드(300문항·5도메인)는 단일 턴이고, 한국어판 MTRAG도 ViDoRe 한국어 스플릿도 없으며, 한국어 text-to-Cypher 자원도, 국내 벤더의 권한 인식 RAG 공개 설계도, 프롬프트 캐시 히트율을 공개한 국내 사례도 찾지 못했다. 결론은 하나다 — 사내 평가셋을 만드는 것 외에 방법이 없다. 300문항·5도메인이면 시작할 수 있고, 근거의 8~33%가 이미지라는 국내 문서 특성상 근거 유형별(문단/표/이미지) 정확도를 나눠 보는 것이 특히 중요하다(⑨편).

결정 트리 — 무엇부터 할 것인가

  1. 지식베이스가 20만 토큰(약 500쪽) 미만인가? → RAG를 짓지 말고 전문을 넣고 캐싱하라. 지연은 절반, 비용은 최대 90% 절감(⑦편).
  2. 숫자·집계를 묻는가? → 벡터가 아니라 text-to-SQL. 단 BIRD 최고 81.95% vs 인간 92.96%이니 초안 생성기로 설계(⑥편).
  3. 그 외 전부 → 하이브리드 검색 + 순서 재정렬부터. mAP 23.99 → 47.14를 지연 +0.14초에 얻는다. 여기서 멈춰도 되는 서비스가 많다(②·④편).
  4. 여전히 못 찾는다면 → 파싱 품질 점검 → 메타데이터 prefix → 리랭커. 리랭커는 지연으로 고른다(0.02초짜리와 82초짜리가 정확도는 4점 차이). 그다음에야 Contextual Retrieval(③편).
  5. 질의가 모호하거나 시간·조건이 붙는가? → step-back(TimeQA +27.2). 파인튜닝 리트리버가 있으면 HyDE는 오히려 손해(④편).
  6. 멀티홉·전역 요약이 핵심인가? → 멀티홉이면 HippoRAG 2, 전역 요약이면 FastGraphRAG + 동적 커뮤니티 선택, 문서가 계속 늘면 LightRAG. MS GraphRAG는 증분 갱신에서 무너진다(⑥편).
  7. 대화형인가? → 질의 재작성이 필수(첫 턴 Recall 0.89 → 이후 0.47). 요약하지 말고 append-only + 캐시 친화적 블록 순서로(⑩편).
  8. 사내 문서인가? → 권한 설계가 먼저다. 파생 청크의 권한 = 기여 원본의 교집합, 공집합이면 만들지 않는다(⑪편).
  9. 운영에 들어가는가? → 삭제·재임베딩·신선도를 예산에 넣는다. 컨텍스추얼 재색인은 평문의 145배이고, 커넥터는 기본적으로 삭제를 전파하지 않는다(⑫편).
  10. 언제나 → 검색과 생성을 따로 재고, judge는 binary + critique으로, 골든셋은 30개에서 시작한다(⑨편).

비용 순서로 다시 정리하면

계층질의당 추가먼저 해야 할 순서
순서 재정렬·하이브리드0원 / +0.14초1
파싱·메타데이터·청킹(일회성)0원2
리랭커약 3원3
질의 변환·크리틱5~10원4
그래프·에이전트150원~1만 원5

이 표가 이 시리즈의 요약이다. 대부분의 팀이 5번부터 검토하고 1·2번을 건너뛴다.

마지막으로

열세 편을 관통하는 사실이 하나 있다. 어떤 변형이 맞는지는 논문이 아니라 측정이 답한다. RAG 실패 7가지 지점 논문의 문장을 다시 인용하면 — "RAG 시스템의 검증은 운영 중에만 실질적으로 가능하고, 견고함은 설계되는 것이 아니라 진화한다." 벤더 숫자와 독립 재현의 간격(Contextual Retrieval −67% vs +0.014), 마케팅과 학술 평가의 방향 차이(GraphRAG), 코드가 공개되지 않은 채 인용되는 절감률(LazyGraphRAG)을 이 시리즈에서 반복해 봤다. 남의 숫자로 결정하지 말고, 우리 로그로 재고 우리 문서로 골든셋을 만들자. 그게 이 시리즈에서 가장 값싼 조언이다.

— RAG 종류 총정리 시리즈 ⑬ (완결) / 관련 시리즈: RAG 실전(구축 실무), LLM 서빙 캐싱(비용), 에이전트 설계, 사용자 의도 분석과 LLM 라우팅

RAG 종류 총정리 ⑫ — 색인 수명주기: 삭제·재임베딩·신선도의 청구서

이 시리즈의 모든 색인 비용은 "일회성"으로 적었다. Contextual Retrieval 문서 100만 토큰당 $1.02, GraphRAG 수천 달러, ColPali 페이지당 443ms. 그런데 정확히 말하면 임베딩 모델 세대당 일회성이고, 리더보드는 해마다 바뀐다. 그리고 "법무팀이 이 문서 파기하래요"라는 한 줄이 예산을 두 배로 만든다. 이 글은 색인의 수명주기 비용을 다룬다.

지웠는데 안 지워졌다 — 벡터 DB의 삭제는 전부 툼스톤이다

세 엔진이 독립적으로 같은 숫자를 골랐다는 게 인상적이다. 삭제율 20%가 정리를 시작하는 공통 임계값이다 — Qdrant의 deleted_threshold=0.2, Milvus의 compaction.single.ratio.threshold=0.2, Lucene의 deletes_pct_allowed=20(범위 5~50). 그 전까지 삭제된 벡터는 HNSW 그래프와 RAM에 그대로 남는다. Qdrant 문서의 표현대로 "질의 중 느린 디스크 작업을 피하려고 삭제 표시만" 하기 때문이다.

더 중요한 건 "검색에 안 나옴"과 "파기됨"이 다르다는 점이다. Milvus의 TTL은 만료 엔티티를 즉시 검색에서 제외하지만 물리 삭제는 "보통 24시간 이내"이고, GC 관용 시간이 3시간, 고아 파일 스캔 주기는 7일이다. 물리 삭제 완료 시각을 조회하는 표준 API를 가진 벡터 DB를 찾지 못했다.

삭제 1건의 진짜 청구서

  • 그래프 하나가 다시 지어진다. Lucene의 IncrementalHnswGraphMerger는 기존 그래프를 재사용하되 조건이 "삭제 문서를 하나도 포함하지 않을 것"이다. 즉 삭제 1건이 있는 세그먼트는 HNSW 그래프 전면 재구축 대상이 된다.
  • pgvector는 삭제 청소가 곧 재빌드다. 공식 권장 절차가 REINDEX INDEX CONCURRENTLYVACUUM이다. 그리고 dead tuple 누적은 조용한 리콜 손실로 나타난다 — hnsw.ef_search 기본 40에서 조건에 맞는 행이 전체의 10%면 평균 4건만 반환된다.
  • force merge는 지우려다 영원히 못 지우게 만든다. 5GB를 넘긴 세그먼트는 이후 정규 병합 대상에서 빠져 소프트 삭제 문서가 계속 쌓인다. max_num_segments=1은 샤드 크기의 최대 3배 디스크를 일시적으로 요구한다. 가벼운 대안은 only_expunge_deletes=true.
  • 삭제도 과금된다. Pinecone 서버리스는 삭제에 1KB당 1 WU, 요청당 최소 5 WU를 매긴다.

문서를 지워도 텍스트는 일곱 군데에 남아 있다

이 시리즈에서 소개한 기법들이 여기서 부메랑이 된다. 원문을 지웠을 때 그 텍스트를 여전히 들고 있는 것들:

  • Contextual Retrieval의 접두 컨텍스트(청크마다 문서 요약 ~100토큰) — ③편
  • RAPTOR 트리의 상위 요약 노드, GraphRAG의 커뮤니티 리포트 — ③·⑥편
  • doc2query·HyDE로 생성해 색인한 질문들 — ③·④편
  • 시맨틱 캐시 엔트리(답변 본문 전체) — 캐싱 시리즈 ⑥편
  • LLM 요청·응답 로그와 트레이싱(프롬프트에 들어간 청크 원문)
  • 평가 golden set과 회귀 픽스처 — ⑨편
  • 리랭커·파인튜닝 학습 데이터

연쇄 삭제를 문서로 보장하는 벤더는 사실상 OpenAI Vector Stores 하나이고, 그마저 "최종적 일관성이라 제거된 파일의 내용이 잠시 검색에 남을 수 있다"고 적혀 있다(지연 수치는 없다). 나머지는 전부 애플리케이션 책임이다.

법적 요구와 대조하면 간극이 분명해진다. 개인정보 보호법 제21조는 "지체 없이" 파기하고 "복구 또는 재생되지 아니하도록" 조치하라고 하며, 시행령 제16조는 전자적 파일의 경우 "복원이 불가능한 방법으로 영구 삭제"를 요구한다 — 툼스톤 상태를 인정하지 않는다. GDPR 17조 2항의 "copy or replication" 삭제 통지 의무는 위 목록을 그대로 가리킨다. 실무 파기 증적은 다섯 개가 필요하다: ① 요청 수신 시각, ② 논리 삭제 시각, ③ compaction/vacuum 완료 = 물리 삭제 확정 시각, ④ 파생물별 삭제 확인, ⑤ 백업·스냅샷 만료. ③을 API로 주는 벡터 DB가 없다는 게 이 항목의 핵심 리스크다.

임베딩 모델을 갈아끼우는 데 드는 돈 — $2 vs $290

100M 토큰 코퍼스를 재색인한다고 하면:

방식100M 토큰 재색인
평문 임베딩 (text-embedding-3-small)약 $2
Contextual Retrieval 재생성약 $290 (배치 시 ~$145)
GraphRAG 전체 추출 재실행$537~1,075
ColPali형 시각 인덱스 (10만 페이지)약 10.8 GPU시간 + 저장 25.75GB

평문과 컨텍스추얼의 차이가 145배다. 여기서 설계 규칙이 하나 나온다 — 접두 컨텍스트 텍스트를 임베딩과 분리해 원본 저장소에 보존하면 모델을 바꿔도 그 $290을 다시 내지 않는다. 그리고 GraphRAG는 "임베딩만 교체"가 애초에 불가능하다는 점(⑥편)이 여기서 다시 비용으로 나타난다. 시각 인덱스는 색인이 표준 파이프라인보다 18배 빠른 대신 저장이 30배 크다(페이지당 257.5KB vs 8.60KB)는 트레이드오프가 있다.

국내 레퍼런스로는 토스의 기록이 정확하다 — "임베딩 모델을 바꾸면 벡터 저장소 운영이 따라와요." 대응책 세 가지를 명시했다: 벡터의 생성 버전 추적, 서빙 버전의 일관성 유지, 모델과 인덱스를 함께 교체. 한 인덱스에 서로 다른 모델의 벡터가 섞이는 사고를 구조로 막은 것이다. blue-green 전환 기간에는 저장·질의 비용이 2배로 뜨니 이중 보유 기간을 짧게 잡아야 한다.

신선도는 주기가 아니라 이벤트로

엔터프라이즈 RAG의 실질 신선도 하한은 생각보다 느리다 — Azure AI Search 인덱서 최소 5분(실행 창 2시간, 반복 실패 시 최대 24시간까지 자동 후퇴), Amazon Q Business 시간별, Vertex AI Search는 1일·3일·5일 세 옵션뿐이다. 더 위험한 건 커넥터가 기본적으로 삭제를 전파하지 않도록 설계돼 있다는 점이다. Vertex의 기본 INCREMENTAL 모드는 upsert라 원본 삭제가 반영되지 않고(전파하려면 FULL), Amazon Q에는 삭제 예정 비율이 임계를 넘으면 삭제 단계를 통째로 건너뛰는 safeguard가 있다. 파기 파이프라인을 커넥터에 의존시키면 안 된다.

대안적 설계로 LY Corporation의 사례가 참고할 만하다. 주기 배치 대신 PR 머지가 갱신 트리거이고, 저장을 raw(원본 근거·변경 이력)와 knowledge(현시점 유효 내용만)로 나눈 뒤 staleness lint 5종(깨진 참조, 식별자 무결성, raw 변경 미반영, 메타데이터 누락, 배포본 비동기화)을 자동으로 돌린다. 마지막으로 낡음이 만드는 오답은 전체 정확도로는 안 보인다 — ⑨편의 CRAG 벤치마크는 질문을 실시간 10% / 일 단위 13% / 연 단위 23% / 불변 54%로 나눠 두었다. 자사 평가셋도 이렇게 쪼개고 색인 지연을 바꿔 가며 슬라이스별 정확도를 재는 것이 신선도를 측정하는 유일한 방법이다. 다음 글은 이 열두 편을 한국 상황에 맞춰 하나의 결정 트리로 접는다.

— RAG 종류 총정리 시리즈 ⑫ / 다음 글: 한국어 조건과 결정 트리 (완결)

RAG 종류 총정리 ⑪ — 권한 인식 검색과 보안: 인사팀 문서가 영업 답변에 섞이면

사내 RAG 파일럿을 실제로 중단시키는 질문은 nDCG가 아니다. "인사팀 문서가 영업사원 답변에 섞이면 어떡하죠?"다. 그리고 이건 부가 기능이 아니라 아키텍처 결정이다 — 앞의 열 편에서 다룬 기법 중 상당수가 문서 경계를 지우는 방식으로 동작하기 때문이다.

검색은 관련성으로 줄 세운다, 권한으로 줄 세우지 않는다

벡터 검색은 "질문과 가장 비슷한 것"을 올린다. 다른 부서의 연봉 테이블이 질문과 제일 비슷하면 top-1이 된다. 흔한 구현은 top-k를 뽑은 뒤 권한으로 걸러내는 사후 필터인데, 두 가지가 잘못된다. 첫째, 권한이 희소한 사용자(신입·외부 파트너)에게는 k개가 전부 걸러져 검색되는 게 없다. 둘째, 더 위험하게는 버리기 전에 이미 로그와 LLM 컨텍스트에 들어간 구현이 많다.

사전 필터 vs 필터러블 HNSW — recall과 지연의 삼각형

  • 사전 필터(권한 통과 집합만 완전 탐색)는 recall 100%지만 집합이 커지면 선형 스캔이라 지연이 터진다. Qdrant의 full_scan_threshold 기본값이 10,000KB(대략 1만 벡터)인 이유다 — 그 아래에서만 경제적이고, 넘어가면 조용히 그래프 탐색으로 돌아간다.
  • 필터러블 HNSW는 권한 값 기반으로 그래프에 추가 간선을 심어 조각남을 막는다. ACORN은 같은 recall에서 처리량이 2~1,000배 차이 난다고 보고했다. 다만 Qdrant 공식 문서도 필터가 아주 강하면 "HNSW 그래프가 무너지기 시작한다"고 인정한다.
  • 구현 디테일이 초 단위를 가른다. Azure 공식 문서에 따르면 그룹 수백~수천 개를 Id eq 'a' or Id eq 'b' ...로 나열하면 응답이 "수 초" 느려지지만 search.in()을 쓰면 1초 미만이다. AD 그룹이 수백 개인 조직에서는 아키텍처 결정에 가깝다.
  • 권한 필드는 처음부터 잡아라. Qdrant는 payload 인덱스를 데이터 적재 후에 만들면 HNSW 재구축 비용이 든다고 명시한다.

인덱스를 나눌 것인가 — 진짜 비용 계산

"공유 인덱스가 싸다"는 통념은 인프라 요금 이야기이고, 질의 요금은 반대일 수 있다. Pinecone 공식 문서의 계산이 명료하다 — 1GB짜리 테넌트 100개일 때 네임스페이스를 나누면 질의당 1 RU, 단일 100GB 인덱스에 메타데이터 필터를 걸면 100 RU다. 필터를 걸어도 데이터 전체를 스캔하기 때문이고, 그래서 같은 질의에 100배가 나온다.

그렇다고 무작정 쪼개면 벤더가 말린다. Qdrant는 "컬렉션마다 자원 오버헤드가 있어 금방 비싸진다"며 클러스터당 1,000개를 상한으로 두고, Milvus는 DB 64 / 컬렉션 65,536 / 파티션 1,024 / 파티션 키 수백만이라는 층위를 갖는데 파티션 이하에는 RBAC이 없다. 즉 격리가 필요한 단위와 비용이 싼 단위가 어긋난다. 관리형 서비스의 하드 리밋도 미리 봐야 한다 — Vertex AI Search는 문서당 reader 3,000개에 데이터 스토어 생성 후 접근제어 변경 불가(= 전량 재색인), Kendra는 문서당 ACL 200개에 속성 필터 그룹 100개, Bedrock Knowledge Bases는 필터 5개 × 그룹 5개에 중첩 1단계다. "부서 × 직급 × 프로젝트" 조합은 이 숫자에 먼저 부딪힌다.

청크를 합치는 순간 권한이 사라진다

이 시리즈에서 가장 덜 알려진 함정이 여기 있다. ③편의 Contextual Retrieval은 청크에 문서 전체 기반 맥락을 주입하고, RAPTOR는 여러 청크를 재귀적으로 요약하며, ⑥편의 GraphRAG는 여러 문서를 가로질러 커뮤니티 리포트를 쓰고, ⑦편의 에이전트 메모리는 세션을 넘나들며 사실을 축적한다. 넷 다 서로 다른 ACL을 가진 원본을 하나의 새 텍스트로 합친다. 그런데 이 합쳐진 산출물의 권한이 무엇인지에 대한 답이 거의 어디에도 없다 — GraphRAG의 출력 스키마에는 접근제어 필드 자체가 없다.

유일하게 이를 문서화한 벤더가 Azure다. 공식 문서는 "스킬셋이 청킹을 하면 ACL 필드를 index projection으로 옮겨야 하고, 민감도 레이블도 각 청크 행에 투영하지 않으면 청크 단위 참조가 필터링되지 않는다"고 못 박는다. 실무 규칙은 한 줄로 정리된다 — 파생 청크의 권한 = 기여한 원본들의 교집합(가장 제한적인 쪽), 교집합이 공집합이면 그 요약은 만들지 않는다. Contextual Retrieval이 문서 100만 토큰당 $1.02에 검색 실패율을 크게 줄여 준다 해도, 권한 설계가 먼저다.

그리고 검색 경로는 공격받는다

권한을 통과한 문서가 명령이 될 수 있다는 것이 다음 층위의 문제다. 코퍼스 크기는 방어가 아니다:

  • PoisonedRAG(USENIX Security 2025): 수백만 건 DB에 표적 질문당 악성 텍스트 5개를 넣어 공격 성공률 90%.
  • BadRAG: 패시지 10개로 검색 성공률 98.2%, GPT-4 거부율이 0.01% → 74.6%로.
  • AgentPoison: 에이전트 메모리 오염률 0.1% 미만으로 평균 ASR 80% 이상, 정상 성능 저하는 1% 미만 — 대시보드에 안 잡힌다.
  • InjecAgent: 도구를 쓰는 에이전트에서 ReAct GPT-4가 약 24% 취약, 유도 프롬프트를 더하면 거의 두 배.

그리고 벡터 DB 자체가 개인정보다. 임베딩 역전 연구는 32토큰 입력의 92%를 정확히 복원했고 임상 노트에서 실명을 뽑아냈다. OWASP의 LLM08:2025가 교차 컨텍스트 유출과 임베딩 역전을 공식 위험으로 등재한 이유이고, "임베딩이니 가명처리됐다"는 논리가 성립하지 않는다는 뜻이다.

마지막으로 방어 전략의 순서. Microsoft 연구팀은 2025년 논문에서 프롬프트 새니타이즈·출력 필터·시스템 격리·학습단 프라이버시가 모두 확률적이라 권한 통제로는 신뢰할 수 없다고 단언하고, "참여한 모든 사용자에게 명시적으로 인가된 콘텐츠만 사용한다"는 결정론적 원칙을 제시했다(Copilot Tuning에 실제 배포). 가드레일은 권한 통제가 아니다.

한국 상황을 덧붙이면, 2026-08-20 개인정보 보호법 개정안이 국회를 통과해 AI 개발 활용 특례가 신설됐고 민감정보·고유식별정보 처리 시 사전 위험평가가 필수, 공포 후 6개월 시행이다. 사내 RAG는 대개 "수집 목적 외 이용"에 해당하므로 이 설계가 곧 아키텍처 요구사항이 된다. 그리고 망분리·CSAP 환경에서는 Azure·Vertex의 네이티브 ACL을 쓸 수 없는데 국내 벤더의 권한 인식 RAG 공개 레퍼런스를 찾지 못했다 — 직접 만들어야 하고 참고할 설계가 없다는 뜻이다. 다음 글은 또 하나의 숨은 비용, 색인의 수명주기다.

— RAG 종류 총정리 시리즈 ⑪ / 다음 글: 색인 수명주기 — 삭제·재임베딩·신선도의 청구서

RAG 종류 총정리 ⑩ — 멀티턴 대화형 RAG: 두 번째 질문에서 무너지는 이유

지금까지 아홉 편은 전부 질문 하나를 가정했다. 그런데 실제로 출시되는 RAG는 대부분 챗봇이고, 두 번째 질문은 이렇게 온다 — "그거 환불돼요?" 여기서 무너지는 방식이 단일 턴과는 완전히 다르다.

39%는 어디로 사라지는가 — 무너지는 건 능력이 아니라 일관성

Microsoft·Salesforce가 20만 건 이상의 시뮬레이션 대화를 분석한 "LLMs Get Lost in Multi-Turn Conversation"이 기준점이다. 같은 과제를 한 번에 주느냐 여러 턴에 나눠 주느냐만 바꿨을 때 6개 태스크 평균 39% 성능 하락이 나왔다. 중요한 건 분해다:

  • 능력치(aptitude) 하락은 16% — 최상위 성능은 크게 안 떨어진다.
  • 비신뢰도(unreliability)는 112% 증가 — 같은 과제를 반복했을 때 최고와 최저의 격차가 두 배 이상 벌어진다.

"못 하게 되는" 게 아니라 "될 때도 있고 안 될 때도 있게 된다." QA에서 재현이 안 되는 버그 리포트의 정체가 이것이다. 모델 크기나 추론 능력과 무관하게 테스트한 15개 모델 전부에서 나타났다. 원인으로 지목된 행동은 넷 — 정보가 부족한데 성급히 답을 시도하고, 이전 시도에 기대어 답이 계속 길어지고, 마지막 턴에 과잉 반응하며 중간 턴을 잊고, 장황한 답변이 새 가정을 주입한다. 모델은 자기가 만든 잘못된 가정을 히스토리에 "사실"로 박아 두고 그 위에 계속 쌓는다.

진짜 범인은 리트리버다

IBM의 멀티턴 RAG 벤치마크 MTRAG(사람이 만든 110개 대화, 평균 7.7턴, 4개 도메인)이 결정적 숫자를 준다. 같은 코퍼스, 같은 리트리버인데:

조건Recall@5
첫 턴0.89
이후 턴 (마지막 발화만 검색)0.47
이후 턴 + 질의 재작성0.52

검색 리콜이 절반으로 떨어진다. 데모는 통과하고 실사용 3턴째부터 무너지는 이유가 여기 있다. 그리고 MTRAG의 결론은 명확하다 — 질의 재작성이 모든 리트리버에서 마지막 턴만 던지는 것보다 일관되게 낫다. 난이도를 더 높이는 건 토픽 전환이다. TopiOCQA(대화당 평균 13턴, 4개 토픽을 넘나듦)에서 같은 기법의 NDCG@3이 QReCC 39.1 → 24.3으로 떨어진다. 배송 → 환불 → 회원등급 → 다시 배송으로 오가는 상담봇이 정확히 이 유형이다.

재작성의 가격표, 그리고 "사람만큼"이 목표가 아닌 이유

구현별 비용은 이렇다. LangChain의 create_history_aware_retriever첫 턴 0회, 2턴부터 매 턴 LLM 1회(히스토리가 비면 원문을 그대로 검색하는 분기가 있다). LlamaIndex의 CondensePlusContext는 턴당 2회(축약 1 + 생성 1). Bedrock Knowledge Bases는 관리형인데도 오케스트레이션 프롬프트가 "사용자 프롬프트를 검색 질의로 바꾼다"고 문서에 적혀 있고, 질의 분해를 켜면 검색 호출이 N배가 된다. "알아서 해준다"는 "청구서에 숨어 있다"는 뜻이다.

목표 설정도 다시 해야 한다. 흔히 "사람이 쓴 재작성문만큼 하면 된다"고 하는데, ConvGQR은 QReCC NDCG@3에서 사람 재작성 35.6을 39.1로 넘었고, LLM4CS는 CAsT-19에서 사람 0.461 대비 0.515를 냈다. 리트리버가 좋아하는 질의와 사람이 읽기 좋은 질의는 다르다. 다만 LLM4CS는 턴당 LLM 5회에 임베딩 5~10회라 비용이 5배다. 비용 관점의 정답에 가장 가까운 건 RetPO 노선 — 큰 모델로 후보를 잔뜩 만들고 리트리버의 실제 검색 성능을 피드백으로 작은 재작성기를 오프라인에서 증류하는 것. 런타임 추가 비용이 사실상 0에 수렴한다.

요약하지 마라 — 프롬프트 캐시가 순위를 뒤집는다

토큰 총량만 보면 대화 요약을 유지하는 방식(running summary)이 가장 싸 보인다. 턴이 늘어도 상수니까. 그런데 프롬프트 캐시를 넣는 순간 순위가 뒤집힌다. 캐시 읽기는 정가의 0.1배인데, 요약은 프롬프트 앞부분을 매 턴 갱신하므로 매 턴 전체를 정가로 다시 계산한다. OpenAI 문서도 compaction을 명시적 캐시 무효화 요인으로 규정한다.

턴 20 기준으로 계산하면 append-only 히스토리의 실효 비용이 약 2,850토큰 상당, running summary가 약 5,700토큰 상당 — 두 배 차이가 반대 방향으로 난다. 품질도 마찬가지다. 매 턴 전체를 재진술하는 SNOWBALL 방식조차 멀티턴 열화를 15~20%만 회복한다. 캐시 90% 할인을 통째로 버리고 사는 이득치고는 작다.

실전에서 한 줄만 고칠 수 있다면 블록 순서다.

  • [system][검색 청크][히스토리][질의] — 청크가 매 턴 바뀌므로 뒤의 히스토리 전체가 매 턴 무효화된다.
  • [system][히스토리][검색 청크][질의] — 안정적인 히스토리까지 캐시에 태우고, 변동하는 청크는 마지막에.

재작성 호출을 싼 모델로 돌릴 때는 최소 캐시 프리픽스를 확인해야 한다 — 모델마다 512~4,096토큰으로 다르고, 미달이면 에러 없이 조용히 캐시가 안 된다(캐싱 시리즈 ④편). 그리고 재작성 호출 하나로 세 가지를 흡수할 수 있다: 출력 스키마를 {standalone_query, hypothetical_answer, stepback_query}로 확장하면 추가 호출 0회로 HyDE와 step-back(④편)까지 얻는다. 별도 호출로 쌓으면 턴당 3~4회가 된다.

한국어에서 더 나쁜 이유, 그리고 무엇을 계측할까

영어 "Is it refundable?"에는 치환할 앵커(it)가 있다. 한국어 "환불돼요?"에는 슬롯 자체가 표면에 없다. 한국어는 주어·목적어가 문맥에서 복원되면 아예 나타나지 않는 언어라, 영어권 재작성 프롬프트를 번역만 하면 모델이 "바꿀 대명사가 없다"고 판단해 원문을 그대로 뱉는다. "생략된 주어와 목적어를 복원하라"를 명시해야 하고, 격조사가 사라지면 주제와 주어가 뒤섞인다는 점도 감안해야 한다("배송은 언제요?"의 생략어가 "제 주문의"인데 "배송 정책의"로 복원되면 완전히 다른 청크를 검색한다).

계측에는 함정이 하나 있다. 재작성이 실패해 엉뚱한 청크를 가져와도, 모델이 그 엉뚱한 청크에 충실하게 답하면 Faithfulness는 오히려 높게 나온다. 진짜 신호는 Context Recall/Precision이다. 더 흔한 버그는 평가 파이프라인에 재작성된 질의를 사용자 입력으로 넣는 것 — "그거"가 이미 "제품 A 환불 정책"으로 바뀌어 있으니 재작성 실패가 지표에서 사라진다. 반드시 원 발화로 채점할 것.

마지막으로 한국어 자원의 공백을 짚어 둔다. ⑨편에서 본 한국어 RAG 리더보드(300문항)는 단일 턴이고 한국어판 MTRAG는 없다. 0.847이라는 점수로 프로덕션을 예측하면 안 된다는 뜻이다. 재작성기 학습 시드로는 AI Hub의 민원·콜센터 데이터(약 110만 대화쌍)가 현실적 1순위이고, 사내 평가셋에는 턴 인덱스별 리콜 리포트를 필수 산출물로 넣어야 한다. KPI도 턴별 정확도 평균보다 CRAG-MM 방식의 대화 생존율(2턴 연속 오답이면 이탈로 간주)이 현실에 가깝다. 다음 글은 사내 RAG 파일럿을 실제로 중단시키는 문제 — 권한이다.

— RAG 종류 총정리 시리즈 ⑩ / 다음 글: 권한 인식 검색과 보안 — 인사팀 문서가 영업 답변에 섞이면

RAG 종류 총정리 ⑨ — 평가: 무엇을 어떻게 재야 개선이 증명되나

여덟 편 동안 변형을 늘어놨지만, 어느 것을 쓸지 정하는 건 결국 측정이다. 그리고 측정 자체에 비용과 함정이 있다. 이 글은 무엇을 재야 개선이 증명되는지, 그리고 왜 대부분의 팀이 잘못된 지표를 비싸게 재고 있는지를 다룬다.

가장 싸고 가장 정확한 평가는 "검색만 따로 재기"

recall@k, nDCG@10, MRR은 정답 문서 ID만 있으면 LLM 호출 0회, 비용 0원, 결정론적으로 계산된다. 반면 RAGAS의 Context Precision은 검색된 청크마다 judge를 호출한다 — top-k 20에 골든셋 300문항이면 지표 하나에 6,000회다. 같은 지표를 ID 기반 모드로 돌리면 0원이 된다.

DeepEval과 promptfoo 모두 공식 문서에서 retriever 지표와 generator 지표를 분리하라고 권한다. 이유는 비용만이 아니다. 검색 실패인지 생성 실패인지 먼저 갈라야 ⑤편의 처방(순위 실패면 리랭커, 근거 실패면 grounding 게이트)이 적용된다. Amazon의 RAGChecker도 답변을 claim 단위로 쪼개 retriever/generator 진단을 분리 제공하는 방향이다.

LLM judge를 믿기 전에 judge를 먼저 평가하라

  • 흔들린다. judge 13종 × 피평가 9종을 교차 검증한 Judging the Judges에서 가장 크고 좋은 모델만 사람과 그럭저럭 정렬됐고, 그조차 사람 점수와 최대 5점 차이였다. 관대 편향과 프롬프트 길이 민감성도 확인됐다.
  • 작은 판별 모델이 더 낫다. 10만 건 규모의 RAGBench의 결론은 "LLM 기반 RAG 평가법이 파인튜닝된 RoBERTa 하나를 못 이긴다"였다. ARES도 경량 judge 파인튜닝 + 수백 개 사람 라벨(통계 보정)로 충분함을 보였다.
  • 1~5점 척도를 버려라. 실무 컨설턴트 Hamel Husain의 조언이 직설적이다 — "1~5점 척도 메트릭을 잔뜩 쓰고 있다면 잘못하고 있는 것". 3점과 4점의 차이를 아무도 정의하지 못하고 전문가 판단과 상관도 거의 없다. 대안은 binary pass/fail + 상세 critique(critique은 few-shot에 그대로 쓸 수 있을 만큼 구체적으로), 그리고 클래스 불균형 때문에 raw agreement 대신 precision/recall 분리.

골든셋은 30개로 시작해 수백 개로 끝난다

"수천 문항을 만들어야 시작할 수 있다"는 생각이 도입을 막는다. 실제 권고는 반대다 — 약 30개부터 시작해 새로운 실패 유형이 더 안 나올 때까지 늘린다. Honeycomb 사례에서는 3회 반복 만에 judge와 전문가 일치율 90%를 넘겼다. ARES는 "수백 개"면 충분하다고 본다.

한국어의 현실적 기준선은 Allganize의 공개 데이터셋이 보여 준다 — 300문항, 5개 도메인(금융·공공·의료·법률·커머스), 문서 63개 약 1,337페이지. 여기서 한국 기업 문서의 특성이 드러난다: 정답 근거가 문단 50~75%, 표 8~25%, 이미지 8~33%다. 근거의 3분의 1이 이미지일 수 있다는 건 파서 품질이 검색기 품질만큼 중요하다는 뜻이고(③·⑧편), 리더보드 상위 점수가 0.847(254/300)이라는 것도 기대치 설정에 도움이 된다.

무료로 쓸 수 있는 한국어 자원도 있다. Ko-StrategyQA로 멀티홉을, KorQuAD 2.0(위키 47,957문서 위 102,960 QA, 표·HTML 포함)으로 구조화 문서를 점검할 수 있다. 다만 KorQuAD 2.0의 사람 성능이 EM 68.82 / F1 83.86이라는 점은 기억해야 한다.

변형을 가르는 벤치마크, 그리고 천장

벤치마크무엇을 가르나 / 대표 수치
CRAG (Meta KDD Cup)RAG 도입 효과의 현실. LLM 단독 ≤34% → 단순 RAG 44% → 최고 솔루션 63%
FRAMES단발 vs 멀티스텝. 검색 없이 0.40 → 멀티스텝 0.66
RGB노이즈 견딤·근거 없을 때 거절·정보 통합·허위정보 걸러내기를 분리 측정
MultiHop-RAG멀티홉에서 그래프·에이전틱이 값을 하는지
FinanceBench / LegalBench-RAG도메인 특화의 냉혹함. 검색 붙인 GPT-4-Turbo가 81% 실패
LongBench v2롱컨텍스트의 천장. 사람 전문가 53.7% vs 최고 모델 50.1%

RGB의 결과가 특히 실무적이다 — LLM들은 노이즈에는 그럭저럭 견디지만 "근거 없을 때 거절하기", "여러 근거 통합하기", "허위정보 걸러내기"에서 심각하게 실패한다. 사내 RAG 사고의 대부분이 이 세 가지에서 나온다. ⑤편의 기권 경로를 별도 지표로 재야 하는 이유다.

그리고 천장을 인정해야 한다. KorQuAD 2.0 사람 F1 83.86, LongBench v2 사람 전문가 53.7%, BIRD 인간 92.96%. 목표를 "정확도 95%"로 잡는 순간 그 프로젝트는 실패로 끝난다.

오프라인으로는 안 끝난다

RAG 실패 7가지 지점 논문의 결론 두 문장을 다시 인용한다 — "RAG 시스템의 검증은 운영 중에만 실질적으로 가능하고, 견고함은 설계되는 것이 아니라 진화한다." LangSmith의 안내도 같은 구조다: 프로덕션 trace를 데이터셋으로 승격시키고, 온라인 평가는 정답이 없으니 reference-free judge를 쓰되 필터 + 샘플링 비율로 비용을 통제한다.

온라인 지표는 단순한 것이 낫다 — 👍/👎, 에스컬레이션율, 인용 클릭률, 재질문율. 그리고 시맨틱 캐시를 붙였다면(캐싱 시리즈 ⑥편) 이 지표들이 A/B 게이트가 된다. 마지막으로 도구 하나를 덧붙이면, 국내 팀이 만든 AutoRAG가 청킹·리트리버·리랭커 조합을 자동 탐색해 준다. 흥미로운 신호는 이 프로젝트의 무게중심이 2026년에 파이프라인 AutoML에서 에이전트로 옮겨갔다는 것 — RAG 지형 변화가 도구에도 그대로 나타난다. 다음 글은 대부분의 실서비스가 실제로는 챗봇이라는 사실에서 출발한다.

— RAG 종류 총정리 시리즈 ⑨ / 다음 글: 멀티턴 대화형 RAG — 두 번째 질문에서 무너지는 이유

RAG 종류 총정리 ⑧ — 멀티모달·문서·코드 RAG: PDF를 이미지로 넣는 게 답일까

2024년의 답은 명확해 보였다. OCR·레이아웃 분석·청킹을 전부 버리고 PDF 페이지를 이미지 그대로 VLM에 넣어 late interaction으로 검색하는 ColPali가 ViDoRe v1에서 전통 OCR 파이프라인을 0.81 vs 0.66으로 압도했기 때문이다. 그런데 2026년의 ViDoRe v3 결과를 보면 그림이 뒤집혔다.

ViDoRe v3: 차이를 만든 건 모달리티가 아니라 리랭커였다

v3는 실제 기업 문서 8개 도메인에서 모델이 아니라 파이프라인 전체(OCR→청킹→임베딩→재순위)를 등록하고 인덱싱·검색 시간까지 기록한다. HR 도메인(1,110페이지/318쿼리, A100 1장) 결과 일부:

파이프라인NDCG@5인덱싱 ms/page검색 ms/query
텍스트 임베딩 단독(경량)0.5014.64.0
시각 late-interaction(8B)0.664443.21,146
텍스트 + 강한 리랭커0.666145.19,786
에이전틱(VLM + Opus 4.5)0.73161.6101,715

금융 도메인에서는 격차가 더 분명하다 — 텍스트+리랭커 0.724 > 시각 late-interaction 0.680(텍스트 단독은 0.519). 즉 2024년의 승부는 "시각 vs OCR"이 아니라 "좋은 후처리가 있느냐"였던 셈이다. 인프라 차이도 크다: 인덱싱이 4.6ms vs 443ms/page(10만 페이지면 8분 vs 12.3시간)이고, 시각 방식은 페이지당 1,030벡터라 float32로 10만 페이지 51.5GB가 필요하다. 바이너리 양자화하면 1.6GB로 32배 줄고 nDCG 손실은 1점 미만이니 사실상 필수다.

파서를 고르는 법 — 기준은 표(TEDS)다

범용 VLM에 페이지를 그냥 던지는 게 가장 나쁜 선택이다. OmniDocBench 종합 점수는 PaddleOCR-VL 96.34 / MinerU2.5-Pro(1.2B) 95.75 / GPT-4o 86.59 / Marker 78.44인데, 표 인식(TEDS)만 보면 94.76 vs 82.95 vs 65.77로 격차가 더 벌어진다. 1.2B 전용 모델이 프런티어 모델보다 9점 높고 수백 배 싸다.

10만 페이지 기준 단가는 이렇다 — Mistral OCR 약 $100(1,000페이지당 $1), Upstage Document OCR 약 $150, Document Parse 약 $1,000(Enhanced $3,000), Docling 자체 호스팅은 CPU 16코어로 약 17.7시간에 한 자릿수 달러. 여기서 중요한 비교가 하나 나온다. Contextual Retrieval의 청크 맥락 생성이 페이지당 약 $0.0005인데 Upstage DP는 $0.01/page다 — 전처리 LLM보다 파싱이 20배 비싸다. 원가를 줄이려면 임베딩 모델이 아니라 파서 등급을 먼저 손봐야 한다는 뜻이고, 반대로 표가 중요한 문서라면 그 $1,000이 유일하게 값을 하는 지출이다.

모달리티마다 청구서가 다르다

  • 표(정형 DB) — text-to-SQL. BIRD 최고 81.95% vs 인간 92.96%(⑥편). 5건 중 1건은 틀린다는 전제로 설계.
  • 표(문서 안) — Markdown/HTML로 직렬화하고 헤더를 모든 청크에 복제. 통째로 한 청크에 넣으면 컨텍스트가 폭발한다.
  • 차트·그래프아직 자동화 금지 구역이다. CharXiv에서 사람 80.5% vs GPT-4o 47.1%, 최고 오픈소스 29.2%. 사전 캡셔닝을 믿지 말고 원본 이미지를 보존해 질의 시 VLM에 직접 넣는 편이 낫다.
  • 음성 — STT 후 텍스트 RAG. Deepgram Nova-3 시간당 약 $0.26, Whisper 계열 $0.36. 타임스탬프를 메타데이터로 남겨야 근거 재생이 된다.
  • 영상 — 전용 영상 인덱싱은 시간당 $2.52로 STT 경로의 약 10배다. ASR+OCR+객체탐지를 텍스트로 떨어뜨리는 Video-RAG 방식이 학습 없이도 상위 모델을 앞선 사례가 있다. 먼저 텍스트로 떨어뜨릴 수 있는지 묻고, 안 될 때만 멀티모달로.

코드 RAG — 벡터 DB를 만들기 전에 물어볼 것

이 영역은 "임베딩이냐 grep이냐"가 아니라 코드베이스 크기의 문제로 정리됐다. Cursor의 자체 측정에서 시맨틱 검색은 grep 대비 정답률 평균 +12.5%이지만 코드 유지율은 전체 +0.3%였고, 파일 1,000개 이상 코드베이스에서만 +2.6%로 의미 있어졌다. Anthropic은 Claude Code에서 파일 경로 같은 식별자만 들고 런타임에 grep/head/tail로 회수하는 just-in-time 방식을 쓰되 하이브리드를 권한다. 극단적으로는 Agentless가 임베딩 검색 없이 디렉터리→파일→함수 순 탐색만으로 SWE-bench Lite 32%를 이슈당 $0.70에 달성했다 — 저장소 구조가 이미 좋은 인덱스라는 뜻이다.

인덱스를 만들기로 했다면, 임베딩 모델보다 청킹을 고치는 게 싸다. AST 기반 청킹(cAST)만으로 RepoEval Recall@5 +4.3, SWE-bench Pass@1 +2.67이 나왔다. 그리고 진짜 운영 비용은 임베딩 단가가 아니라 재인덱싱 빈도다.

한국 문서에는 0단계가 하나 더 있다

Mistral OCR, Docling, Marker, LlamaParse — 어디도 HWP/HWPX를 네이티브로 받지 않는다. PDF로 변환해 넘기면 표 구조가 깨진다. 2026년 상반기에만 순수 Python HWP/HWPX 파서 저장소가 여러 개 새로 생겼고 공통 기능이 "표를 Markdown/CSV로 직접 추출"인 것 자체가 이 공백의 증거다. 공공·금융 RAG라면 HWP 전용 파서가 파이프라인 0단계다.

그리고 ViDoRe v3에는 한국어 스플릿이 없다(영어 7 + 프랑스어 1). Upstage의 DP-Bench(TEDS 93.48)와 표 인식 연구(TFLOP), CLOVA OCR 정도가 국내 레퍼런스이고, 한국어 문서 RAG의 성능은 결국 자체 평가셋으로 재는 수밖에 없다. 마침 다음 글의 주제가 그것이다.

— RAG 종류 총정리 시리즈 ⑧ / 다음 글: 평가 — 무엇을 어떻게 재야 개선이 증명되나

RAG 종류 총정리 ⑦ — 에이전틱 RAG와 "RAG는 죽었나" 논쟁

"검색 툴 하나 붙였는데 왜 안 똑똑해지죠?" — 에이전틱 RAG를 검토하는 팀이 가장 먼저 겪는 실망이다. 숫자가 그 이유를 정확히 말해 준다. BrowseComp(웹을 뒤져야 풀리는 1,266문항)에서 GPT-4o는 0.6%, 브라우징을 붙여도 1.9%인데, 검색을 위해 훈련된 딥리서치 시스템은 51.5%다. 참고로 숙련된 사람도 29.2%만 풀고 70.8%는 두 시간 만에 포기했다.

반복의 순수 이득과 그 청구서

반복 검색 자체의 이득은 측정돼 있다. FRAMES에서 검색 없는 SOTA LLM이 0.40, 멀티스텝 검색 파이프라인이 0.66(+50% 이상). RL로 검색을 학습시킨 Search-R1은 7B에서 RAG 베이스라인 대비 +41%였다.

대가는 Anthropic이 공개한 숫자가 가장 정직하다 — 에이전트는 챗의 약 4배, 멀티에이전트는 약 15배 토큰을 쓴다. 그 대신 리드 Opus + 병렬 Sonnet 서브에이전트가 단일 모델 대비 90.2% 우위였고, BrowseComp 성능 분산의 80%가 토큰 사용량으로 설명됐다. 성능을 사려면 토큰을 사야 한다는 뜻이다.

Sonnet 5($2/$10) 기준으로 질의 하나의 실제 청구액을 계산하면 이렇다.

방식질의당배수지연
단발 RAG24원1배2~4초
반복 에이전트(도구 5회)175원7.4배15~40초
같은 조건 + 프롬프트 캐싱63원2.6배동일
+ 웹검색 5회245원10.4배30~90초
딥리서치(리드+서브4, 검색 40회)7천~1.1만 원300~470배5~30분

월 1만 쿼리면 단발 RAG 약 $170, 캐싱 켠 에이전트 $450, 딥리서치는 $5만~8만이다. 캐싱만 켜도 에이전트가 7.4배에서 2.6배로 내려온다(캐싱 시리즈 ④편). 그리고 이 표는 토큰 시나리오를 가정한 모델링이니 자사 단가로 다시 계산해야 한다.

"RAG는 죽었다"는 반만 맞다

1M 컨텍스트가 나오면서 나온 주장인데, 2025~2026년 증거는 반대다.

  • NoLiMa: 질의와 문서의 어휘 중첩을 제거하면 128K를 표방한 모델 13개 중 11개가 32K에서 단문맥 성능의 절반 이하로 떨어진다. GPT-4o는 99.3% → 69.7%.
  • Context Rot(18개 모델): 방해 문서가 단 1개만 들어가도 정확도가 떨어지고 4개면 가중된다. Claude는 기권하는 쪽으로, GPT는 자신 있게 틀리는 쪽으로 갈린다.
  • OP-RAG: 검색 청크를 원문 순서로 유지하면 ∞Bench EN.QA F1이 48K 토큰에서 47.25인데, 같은 모델에 117K를 통째로 넣으면 34.26이다. 토큰을 1/2~1/7로 줄이면서 정확도가 오른다.

정답은 대체가 아니라 라우팅이다. Self-Route는 비용을 39~65% 줄이면서 성능을 유지했다(⑤편). 실무 컷라인도 명확하다 — 지식베이스가 20만 토큰(약 500쪽) 미만이면 RAG를 짓지 말고 통째로 넣고 캐싱하라는 게 Anthropic의 권고다. 롱컨텍스트 경제학은 벤더마다 다르다는 점도 계산에 넣어야 한다: Claude는 1M 전체가 표준 단가이지만 Gemini 3.1 Pro는 200K 초과 시 단가가 2배이고, 1M 컨텍스트를 캐시로 유지하면 코퍼스당 시간당 $4가 나간다.

검색하지 말고 실행하라

2026년의 실질적 변화는 "무엇을 미리 계산할 것인가"의 재배치다.

  • MCP 코드 실행: 도구 정의를 전부 컨텍스트에 넣는 대신 코드 API로 노출하고 실행 환경에서 필터링하면 150,000 → 2,000 토큰(98.7% 절감).
  • 서브에이전트 요약: 수만 토큰을 탐색하고 1,000~2,000 토큰 요약만 반환시키는 패턴. 컨텍스트를 "수확 체감이 있는 유한 자원"으로 다루는 설계다.
  • 메모리도 RAG 변종이다: Mem0는 LongMemEval에서 67.8 → 94.4를 7K 토큰·1초 안에 냈고, Zep은 지연 −90%를 보고했다. 대화형 제품이라면 이쪽이 먼저다.

프로덕션 3원칙

LangChain이 자체 딥리서치를 만들며 남긴 결론이 실용적이다 — "멀티에이전트는 조율이 어렵고, 리포트를 병렬로 쓰면 품질이 나쁘다. 조사에만 멀티에이전트를 쓰고 작성은 한 번에 하라." 여기에 둘을 더한다. 예측 불가능성은 버그가 아니라 성질이므로 도구 호출 상한·타임아웃·비용 캡을 코드로 강제할 것. 그리고 모델의 자기확신을 믿지 말 것 — HLE 리더보드에서 상위 모델들의 캘리브레이션 오차가 57~89%였고, OpenAI 자신도 딥리서치가 소문을 인용하고 불확실성 전달에 실패한다고 밝혔다.

한국 상황을 덧붙이면, 스택은 갖춰졌는데 평가가 비었다. Solar Pro 4(512K 컨텍스트, $0.30/$1.20)·KURE·AutoRAG로 조립은 가능하지만 BrowseComp는 영어·중국어만, DeepResearch Bench도 영중 50:50이라 한국어 딥리서치 벤치마크가 사실상 없다. 사내 평가셋을 직접 만드는 수밖에 없고, 그 방법은 ⑨편에서 다룬다. 다음 글은 텍스트가 아닌 자료 — 표·도면·코드의 RAG다.

— RAG 종류 총정리 시리즈 ⑦ / 다음 글: 멀티모달·문서·코드 RAG — PDF를 이미지로 넣는 게 답일까

RAG 종류 총정리 ⑥ — GraphRAG와 구조화 데이터: 색인에 1,000배를 쓸 것인가

GraphRAG는 제안서에 가장 자주 등장하고 실제로는 가장 자주 후회하는 선택이다. 문서에서 엔티티와 관계를 뽑아 그래프를 만들고 커뮤니티 요약을 미리 생성해 두면 "이 코퍼스의 주요 테마는?" 같은 전역 질문에 답할 수 있다 — 벡터 검색이 구조적으로 못 하는 일이다. 문제는 값이다. 이 계층은 비용이 배수가 아니라 자릿수로 갈린다.

원문 1토큰을 색인하려고 100토큰을 태운다

가장 신뢰할 만한 실측은 HippoRAG 2 논문의 부록 표다. MuSiQue 11,656 passage를 같은 조건에서 색인했을 때 소모 토큰:

방식입력 토큰출력 토큰
RAPTOR1.7M0.2M
HippoRAG 29.2M3.0M
LightRAG68.5M18.3M
MS GraphRAG115.5M36.1M

같은 코퍼스에 HippoRAG 2의 12.5배다. 진짜 병목은 시간이다 — 원논문은 100만 토큰 색인에 GPT-4-turbo로 281분이 걸렸고, 미시간주립대·Meta의 통일 평가에서는 벡터 RAG 135초 vs KG-GraphRAG 7,702초(57배)였다. PoC를 한 번 돌리고 프롬프트를 고치면 그 시간을 통째로 다시 낸다.

질의 비용도 상식 밖이다. LightRAG 논문의 Legal 데이터셋 측정에서 GraphRAG의 검색 1회가 61만 토큰 + API 약 610회인데 LightRAG는 100토큰 미만 + 1회였다. GraphRAG-Bench도 global 질의당 최대 331,375토큰(vanilla RAG는 900~950토큰)을 기록했다.

Microsoft도 알고 있다 — 다만 해법은 아직 안 줬다

공식 레포 README 첫 줄이 "인덱싱은 비쌀 수 있으니 작게 시작하라"는 경고이고, 레포는 현재 사실상 유지보수 모드(신규 기능 PR 미수용)다. LazyGraphRAG는 색인 비용을 full GraphRAG의 0.1%, 전역 질의 비용을 1/700로 줄였다고 발표했지만 2026년 8월 현재 코드가 공개되지 않았다. 재현 불가능한 벤더 주장으로 취급하는 게 맞다.

지금 켤 수 있는 스위치는 둘이다. FastGraphRAG(LLM 추출을 명사구·동시출현으로 대체) — 공식 문서가 "그래프 추출이 색인 비용의 약 75%"라고 명시했으니 약 1/4로 떨어진다. 동적 커뮤니티 선택 — 정적 global이 리포트 1,500개를 전부 읽는 것을 라우터로 평균 470개만 고르게 해 비용 77% 절감, 품질 차이는 통계적으로 유의하지 않았다. 안 켤 이유가 없다.

그래프가 이기는 질문은 딱 세 가지다

학술 평가들은 마케팅과 반대 방향을 가리킨다. GraphRAG-Bench에서 소설 도메인 단순 사실 조회는 basic RAG 60.92%가 GraphRAG 전군(49~60%)을 이겼고, 의학도 64.73% vs 38~66%였다. 미시간주립대·Meta 평가에서도 NQ는 RAG F1 64.78 > Community-GraphRAG 63.01이었다. 선행 연구 인용으로는 NQ 정확도 13.4% 낮고 시간 민감 질의에서 16.6% 하락한다.

반대로 확실히 이기는 셋:

  • 멀티홉 — Recall@5가 73.4% → 87.8%(+19.6%p), 2Wiki +28점, MuSiQue +31점. HippoRAG 2는 평균 Recall@5 78.2로 NV-Embed-v2(73.4)를 앞선다.
  • 전역 요약 — "주요 테마는?" 류에서 MS-GraphRAG 64.40 vs 51.30, naive RAG 대비 승률 80~82%.
  • 엔티티 중심 탐색 — 원래 구조가 있는 데이터일 때. 가장 믿을 만한 프로덕션 사례가 LinkedIn 고객지원이다 — 티켓의 이슈 구조를 그래프로 보존해 약 6개월 실운영, MRR +77.6%, 이슈당 중앙값 해결시간 −28.6%.

단, 승률표 대부분이 LLM 심판 기반이라는 점은 감안해야 한다. 같은 평가에서 심판의 순서 편향을 보정하자 어떤 방식의 승률이 66.7% → 약 39%로 무너진 사례가 보고됐다.

문서가 계속 늘어나면 구조적으로 못 버틴다

MS GraphRAG는 증분 갱신 시 커뮤니티를 전면 재구축한다 — LightRAG 논문 계산으로 약 1,400만 토큰이 다시 든다. 월간 문서 유입이 있는 사내 위키·티켓 시스템에 MS GraphRAG를 넣으면 안 된다. LightRAG(GitHub 39.3k stars)·nano-graphrag·HippoRAG는 증분 삽입을 지원하고, LightRAG는 품질에서도 GraphRAG와 승률 49.6~54.8%로 무승부다. 이긴 건 비용이다. 2026년에 "GraphRAG 도입"이라고 쓴다면 MS 구현이 아니라 이쪽 계열을 뜻해야 한다.

DB에 물어보는 건 벡터가 아니라 SQL이다

"지난 분기 지역별 매출 상위 5"는 벡터 검색으로 풀 수 없다. 정형 데이터는 text-to-SQL인데 여전히 어렵다 — BIRD(95개 DB, 33.4GB) 최고 81.95% vs 인간 92.96%, 그리고 Spider 2.0의 실제 웨어하우스 환경에서는 GPT-4o가 12.98%로 무너진다(Spider 1.0에서는 86.6%였다). 테이블 하나가 1,000~3,000 컬럼이고 정답 SQL이 100줄을 넘기 때문이다. 처방은 모델 교체가 아니라 시맨틱 레이어로 질의 표면적을 줄이는 것이고, 무엇보다 text-to-SQL은 정답 생성기가 아니라 초안 생성기로 설계해야 한다. 리더보드 90%대는 벤더 자체 제출 에이전트라는 점도 기억할 것.

한국에서 검토 중이라면

세 가지를 먼저 확인해야 한다. 첫째, 국내 공개 사례와 수치가 사실상 없다 — 국내 벤더 백서에는 비용·정확도·지연 수치가 없고 사례도 해외 기업뿐이다. 제안서에 실려 오는 "정확도 3배" 류는 대개 Neo4j 매니페스토의 2차 인용이고 원출처 표본이 질문 43개다. 둘째, 진짜 실패 지점은 한국어 엔티티 해소다 — 뉴스에서 "LG전자"와 "LG에너지솔루션"을 가르는 문제처럼 약칭·보통명사·조사 때문에 같은 회사가 노드 서너 개로 갈라진다. 삼성SDS도 순수 딥러닝이 아니라 형태소 분석 → NER(딥러닝+사전 하이브리드) → 관계 추출 순서를 택했다. 셋째, 그래프를 만들어도 질의할 자원이 없다 — Neo4j의 text-to-Cypher 데이터셋(44.4k)은 영어 전용이고 한국어 공개 자원을 찾지 못했다.

결정 규칙으로 접는다: 10만 토큰 이하면 통째로 넣고, 사실 조회면 벡터, 멀티홉이면 HippoRAG 2, 전역 요약이면 FastGraphRAG + 동적 선택, 문서가 계속 늘면 LightRAG, 숫자 질문이면 text-to-SQL. 다음 글은 비용이 한 번 더 자릿수로 뛰는 계층이다.

— RAG 종류 총정리 시리즈 ⑥ / 다음 글: 에이전틱 RAG와 "RAG는 죽었나" 논쟁

RAG 종류 총정리 ⑤ — Adaptive·Self·Corrective RAG: 언제 검색을 건너뛸까

지금까지는 "어떻게 잘 찾을까"였다. 이 글은 다른 질문을 던진다 — 애초에 찾아야 하나? 그리고 찾은 게 쓸모없으면 어떻게 하나? 검색 여부·횟수·재시도를 시스템이 판단하는 계열(Self-RAG, CRAG, Adaptive-RAG)인데, 여기서부터는 크리틱 호출이 붙으므로 산수를 먼저 해야 한다.

"일단 검색"이라는 기본값은 정확도까지 깎는다

두 개의 실측이 같은 방향을 가리킨다. KAIST의 Adaptive-RAG가 GPT-3.5로 6개 데이터셋을 평균한 결과, 검색을 안 한 쪽이 EM 35.77로 단일 스텝 검색 34.73보다 높았다. FLARE의 StrategyQA에서도 무검색 72.9 > 1회 검색 68.6이었다. 모델이 이미 아는 걸 물었을 때 관련 없는 문서를 밀어 넣으면 오히려 방해가 된다.

프로덕션 트래픽에서 이 비율은 생각보다 크다. Self-Route 측정에서 질의의 57~77%가 RAG만으로 해결됐고 63%는 RAG와 롱컨텍스트의 답이 완전히 동일했다. 나머지에만 비싼 경로를 쓰는 것만으로 토큰 비용이 38.6~61.6% 줄었다. 게다가 Self-Route의 라우팅 판단은 첫 호출 프롬프트에 한 줄 얹는 것이라 추가 호출이 사실상 0이다.

세 갈래 계보: 비판하기, 고치기, 나누기

  • Self-RAG — 제너레이터 안에 판단을 넣는다. reflection 토큰 4종(Retrieve / IsREL / IsSUP / IsUSE)으로 검색 여부와 근거 품질을 스스로 판정한다. PopQA 54.9, Bio FactScore 81.2로 좋지만 대가가 크다 — 7B 크리틱 학습 + 15만 쌍으로 제너레이터 재학습이 전제다. 자체 파인튜닝 파이프라인이 없으면 선택지가 아니다.
  • CRAG — 파이프라인 옆에 평가기를 붙인다. 0.77B T5 평가기가 검색 결과를 Correct/Incorrect/Ambiguous로 분류하고, Incorrect면 웹 검색으로 대체한다. 재학습이 필요 없는 plug-and-play인데 효과가 크다 — LLaMA2-7B 기준 PubHealth 48.9 → 59.5(+10.6), ARC 43.4 → 53.7(+10.3). 대가는 지연 0.363초 → 0.908초(2.5배). 가성비 1위.
  • Adaptive-RAG — 진입점 앞에서 나눈다. 770M 분류기가 질의를 무검색(A)/단일(B)/멀티스텝(C)으로 라우팅한다. GPT-3.5 6개 데이터셋 평균 EM 34.73 → 37.97, 지연은 멀티스텝(3.33배) 대비 1.46배. 멀티스텝 이득(+3.40 EM)의 95%를 추가 지연의 20%로 회수한다.

판단을 어디에 두느냐 — 제너레이터 안 / 파이프라인 옆 / 진입점 앞 — 가 곧 도입 비용을 결정한다.

추가 호출 산술: 크리틱 한 번에 얼마인가

LangGraph의 레퍼런스 구현(라우터 → 문서별 grader → 생성 → 환각 grader → 답변 grader → 실패 시 재작성)은 질의당 최소 4 + k회 호출이다. 청크 5개 × 600토큰 입력, 출력 300토큰, 본답변 Sonnet 5 기준으로 계산하면:

구성질의당 추가
관리형 groundedness 게이트(Bedrock)$0.0012
리랭커 1회(100청크)$0.002
Haiku 크리틱 1패스$0.0033
풀 Adaptive 그래프(Haiku grader)$0.007 (+78%)
같은 그래프, Sonnet grader+145%

여기서 나오는 실무 규칙: 실패 원인이 "순위"면 리랭커가 3배 싸고, "근거 없음"이면 관리형 게이트가 자체 grader보다 2.75배 싸다. 자체 LLM grader를 만들 근거는 도메인 특수 규칙이 있을 때뿐이다. 그리고 재작성 루프가 한 번만 돌아도 이 비용은 다시 배가 된다.

그런데 복잡한 파이프라인이 필요 없을 수도 있다

적응형 검색 35종을 6개 데이터셋 × 10개 지표로 전수 비교한 2025년 연구의 결론이 냉정하다 — "단순 불확실성 추정 기법이 복잡한 파이프라인보다 효율성과 self-knowledge에서 앞서면서 QA 성능은 비슷하다." 로짓 엔트로피 임계값 하나면 학습 0, 추가 호출 0이다. 첫 실험은 여기서 시작해야 한다.

분류기 자체가 새로운 오류원이라는 점도 있다. Adaptive-RAG의 실제 EM 37.97 vs Oracle 분류기 47.70 — 라우팅 오류가 EM 9.7점(상대 26%)을 태운다. 게다가 Oracle은 평균 0.50 스텝인데 실제는 1.03 스텝이니 오분류는 정확도와 비용을 동시에 악화시킨다. 임계값 캘리브레이션 비용도 무시할 수 없다 — CRAG의 임계값이 데이터셋마다 (0.59,−0.99) / (0.5,−0.91) / (0.95,−0.91)로 제각각이고 FLARE의 θ도 0.4~0.8이다. 논문 기본값을 그대로 쓰면 게이트가 열린 채 혹은 닫힌 채 고정된다.

도입 순서, 그리고 "모르겠습니다"

권장 순서는 이렇다. (1) 로그에서 무검색으로 풀리는 질의 비율을 재고(57~77%가 기준선), (2) 엔트로피 임계값으로 무검색 경로를 먼저 열고, (3) 실패를 "순위 실패 vs 근거 실패"로 분류해 리랭커 또는 grounding 게이트를 배정하고, (4) 그다음 CRAG, (5) 마지막에 멀티스텝 라우팅. 앞선 "사용자 의도 분석과 LLM 라우팅" 시리즈의 분류기가 여기서 그대로 쓰인다.

마지막으로 기권(abstention)은 부산물이 아니라 기능이다. CRAG의 Incorrect 판정, Adaptive-RAG의 A 라우트, groundedness 게이트가 전부 같은 문제의 다른 구현이고, 기권 서베이는 이를 환각 완화·안전성의 핵심 수단으로 규정한다. ⑨편에서 볼 RGB 벤치마크가 지적하듯 현행 LLM이 가장 못하는 것 중 하나가 "근거 없을 때 거절하기"다. 다음 글은 비용 자릿수가 완전히 달라지는 계층, GraphRAG다.

— RAG 종류 총정리 시리즈 ⑤ / 다음 글: GraphRAG와 구조화 데이터 — 색인에 1,000배를 쓸 것인가

RAG 종류 총정리 ③ — 청킹·Contextual Retrieval·파싱: 색인 단위를 똑똑하게

검색을 고쳤는데도 못 찾는다면 다음은 색인 단위다. 청크를 어떻게 자르고 무엇을 붙여 넣을지의 문제인데, 이 계층의 장점은 비용이 일회성이라는 것이다. 질의당 부담이 0이라 트래픽이 늘어도 청구서가 안 늘어난다. 다만 여기엔 벤더 숫자와 재현 숫자의 간격이 가장 큰 구간이기도 하다.

Contextual Retrieval — 그리고 그 숫자의 분해

Anthropic의 방식은 청크를 색인하기 전에 LLM으로 50~100토큰짜리 맥락 문장을 앞에 붙이는 것이다. 발표된 개선은 top-20 검색 실패율 5.7% → 1.9%(−67%)인데, 이 숫자는 세 기법의 합이다.

  • 맥락 임베딩만: 5.7% → 3.7% (−35%)
  • + 맥락 BM25(하이브리드): → 2.9% (−49%)
  • + 리랭킹: → 1.9% (−67%)

즉 −67% 중 절반 이상은 ②편에서 다룬 훨씬 오래되고 싼 기술이 벌어준 몫이다. 비용은 프롬프트 캐싱을 쓰면 문서 100만 토큰당 $1.02의 일회성이고, 공개된 쿡북을 보면 입력 토큰의 61.8%가 캐시 읽기로 처리되어 $9.20 → $2.85(−69%)가 됐다. 문서 단위로 배치를 묶지 않으면 이 캐시 적중률이 무너진다는 게 실무 함정이다. 평가셋 규모도 알아 둘 만하다 — 코드베이스 9개, 청크 737개, 쿼리 248개. Pass@5 80.92% → 88.12%는 약 18개 쿼리를 더 맞힌 결과다.

독립 재현은 더 차분하다. NFCorpus에서 contextual 0.308 vs late chunking 0.294로 격차가 nDCG@10 +0.014였고, contextual 청크 생성에 VRAM 20GB가 필요해 데이터셋의 20%만 평가할 수 있었다. late chunking은 LLM 호출이 0회인데도 이 정도다 — 문서를 롱컨텍스트 임베딩에 한 번 통과시킨 뒤 pooling 직전에 자르는 방식으로, 평균 +1.9%p(NFCorpus 23.5→30.0)지만 Quora는 변화 0, MsMarco+Stella에서는 0.630 → 0.503으로 오히려 손해였다. 일관된 규칙은 하나 — 문서가 길수록 이득이 크다.

시맨틱 청킹은 돈값을 못 한다

"시맨틱 청킹이 연산 비용만큼 가치가 있나"가 정면으로 답했다. 합성 데이터셋에서는 화려하다(NQ 43.79 → 63.93). 그런데 실제 문서에서는 반대다 — HotpotQA는 고정 크기 90.59 > breakpoint 87.37 > clustering 84.79, MSMARCO도 고정이 최고, 근거 검색 5종은 전부 고정 크기 우세. 결론 문장이 인상적이다: "청킹 전략의 영향은 임베딩 품질에 가려진다."

청크 크기와 오버랩은 어떨까. Chroma의 토큰 단위 평가에서 OpenAI 기본값(800토큰/오버랩 400)이 최하위였고 승자는 200/0이었다. 화학 도메인에서 청킹 25설정 × 임베딩 48모델을 돌린 연구의 승자도 100토큰/오버랩 0이다. 단, 최적값은 무엇을 재느냐에 따라 정반대로 나온다 — Chroma(토큰 IoU 기준)는 200, LlamaIndex(faithfulness/relevancy 기준)는 1024가 정점이다. "검색 정밀도냐 답변 충실도냐"부터 정해야 한다.

더 싼 대안들

  • 메타데이터 prefix — LLM 없이 제목·섹션·날짜를 청크 앞에 붙이는 것만으로 precision 82.5%, nDCG 0.813(최고), P95 30ms 미만. 파서 출력을 재활용하니 사실상 공짜다. 가성비 1위.
  • 구조 인식 청킹 — 기업 문서 연구에서 top-K 최고에 연산 비용은 현저히 낮았다. 파서가 제목·절 구조를 주면 거의 공짜.
  • RAPTOR(재귀 클러스터링+요약 트리) — QuALITY 82.6%가 눈에 띄지만 QASPER 기준 실제 마진은 DPR 대비 +1.8%p, BM25 대비 +5.3%p다. 여러 청크를 종합해야 답이 나오는 질문이 많을 때만.
  • Proposition 색인(문장을 원자 명제로 쪼개 색인) — Recall@5 42.5→50.1이지만 위키 규모에서 P100 500 GPU-시간, 인덱스 768GB, 단위 6배 팽창. 게다가 리트리버가 좋을수록 이득이 사라진다(지도학습 +2.7, DPR은 −0.6).
  • 질문 생성 색인Doc2Query--의 교훈은 필터가 본체라는 것. 생성 질의 상당수가 환각이라 필터링만으로 검색 +16%, 질의시간 −23%, 인덱스 −33%였다. 필터 없이 "청크마다 질문 5개"는 마이너스가 날 수 있다.

진짜 병목은 파싱이다

기업 문서 연구에서 네 가지 청킹 전략이 전부 P&ID 도면에서 실패했다. 청킹을 아무리 튜닝해도 파서가 표를 깨뜨리면 소용이 없다는 뜻이다. OmniDocBench의 표 인식(TEDS) 점수를 보면 격차가 선명하다 — PaddleOCR-VL 94.76, GPT-4o 82.95, Marker 65.77. 상용 최고 수준인 Upstage Document Parse가 TEDS 93.48이라는 건, 나머지 6.5%는 표가 깨진 채 색인된다는 뜻이기도 하다.

한국어에는 조건이 둘 더 붙는다. 첫째, 맥락 BM25는 형태소 분석기 없이 성립하지 않는다 — 조사가 붙어("예진의", "예진에서") 정확 매칭이 깨지므로 Nori나 Kiwi가 필수고, 문장 경계도 불안정해 별도 분리기가 필요하다(②편). 둘째, HWP/HWPX를 네이티브로 받는 글로벌 파서가 없다(⑧편). 그리고 한국어 임베딩 1·2위 격차가 0.3% 수준이라는 점을 생각하면, 예산 순서는 분명하다: 파싱 → 메타데이터 prefix → 하이브리드+리랭커 → 그래도 부족하면 Contextual Retrieval. 청킹 파라미터 튜닝은 마지막이다. 다음 글은 질의를 다시 쓰는 계층이다.

— RAG 종류 총정리 시리즈 ③ / 다음 글: 질의 변환 — HyDE·분해·step-back의 손익계산서

RAG 종류 총정리 ④ — 질의 변환: HyDE·분해·step-back의 손익계산서

여기서부터 비용 구조가 바뀐다. 앞의 두 계층(검색·색인)은 질의당 LLM 호출이 늘지 않았지만, 질의 변환은 요청마다 LLM을 한 번 이상 더 부른다. 그래서 "정확도가 얼마나 오르나"만이 아니라 "지연이 몇 초 늘고 그만큼 값을 하나"를 같이 봐야 한다. 다행히 Fudan의 전수 비교가 점수와 지연을 함께 측정해 뒀다.

한 장의 표: 정확도와 지연을 같이 보기

구성 (TREC DL19)mAP쿼리당 지연
원본 질의 (dense)23.993.06초
+ 하이브리드47.143.20초
+ 질의 재작성44.56
+ 질의 분해41.9314.98초
+ HyDE50.877.21초
+ HyDE + 하이브리드52.1311.16초

읽는 법은 이렇다. 하이브리드는 +23.15점을 0.14초에 산다. HyDE는 거기서 +5점을 얻으려고 8초를 더 쓴다. 그리고 질의 재작성(44.56)과 분해(41.93)는 둘 다 하이브리드보다 낮다. 실시간 챗봇이라면 이 표만으로 결론이 난다 — 하이브리드에서 멈추고, 남는 예산은 리랭커에 쓴다.

HyDE — 라벨 없는 신규 도메인 전용 부스터

HyDE는 질의로 가짜 답변 문서를 생성해 그걸로 검색한다. 효과는 확실하다 — TREC DL19 nDCG@10이 Contriever 44.5 → 61.3, TREC-Covid는 27.3 → 59.3. 라벨이 전혀 없는 새 도메인에서 특히 강하다.

그런데 원논문에 지는 구간도 정직하게 적혀 있다. 파인튜닝된 리트리버가 있으면 HyDE가 진다 — FiQA 27.3 vs Contriever-FT 32.9, DBPedia 36.8 vs 41.3. 더 중요한 건 다국어다. Mr.TyDi 전 언어에서 mContriever-FT에 졌고 한국어는 30.6 vs 34.2였다. 자사 임베딩을 한국어로 튜닝했거나 KURE 같은 한국어 특화 모델을 쓴다면(②편), HyDE는 지연 +4초를 내고 점수를 잃을 수 있다. 가짜 문서를 8개로 늘리면 14.15초까지 가는데 수확은 체감한다.

Step-back — 대박 구간이 따로 있다

Step-back prompting은 구체적 질문에서 한 걸음 물러난 상위 개념 질문을 먼저 만든다("이 조건에서 압력은?" → "이상기체 법칙은?"). 이득의 분포가 극단적이다 — TimeQA 41.5 → 68.7(+27.2), 화학 70.9 → 81.8, 물리 66.4 → 73.2인데 StrategyQA는 82.8 → 86.4(+3.6)에 그친다. 시간·조건·제약이 붙은 질의("2023년 기준 규정은", "A 조건일 때 B는")에 몰빵하고 나머지엔 걸지 않는 게 맞다.

주의할 점 둘. 논문의 오류 분석에서 실패의 90% 이상이 추상화가 아니라 추론 단계였다 — 추론이 약한 소형 모델에서는 효과가 사라진다. 그리고 기존 오류 20~40%를 고치는 대신 새 오류를 5~12% 만든다.

멀티쿼리·RAG-Fusion과 후처리

실무에서 가장 많이 쓰이는 멀티쿼리(RAG-Fusion)는 정작 근거가 얇다. 원논문은 수동 평가 위주이고, 스스로 약점을 적어 뒀다 — "생성된 질의가 원 질의와 충분히 관련되지 않으면 답이 주제를 벗어난다." 비용은 확실히 는다: LLM 1회 + 검색과 임베딩이 N배. N=5면 벡터 DB 비용도 5배다.

후처리 쪽은 계산이 더 분명하다.

  • 순서 재정렬은 공짜다. Fudan 실험에서 Reverse repacking 0.560 vs Forward 0.542, OP-RAG는 검색 청크를 원문 순서로 유지하는 것만으로 128청크에서 F1 38.40 → 44.43. 추가 호출 0회다.
  • 압축에는 공짜 점심과 명시적 거래가 있다. LongLLMLingua는 토큰 약 4배 절감에 최대 +21.4%, 비용은 LooGLE 기준 $93.60 → $5.60(−94%), 지연도 1.4~2.6배 빨라진다. 반면 RECOMP의 요약형은 토큰을 5~10%로 줄이는 대가로 EM이 NQ −2.35, HotpotQA −4.60 떨어진다. 정확도 최우선 도메인에서는 후자를 쓰지 말 것.
  • 청크를 더 넣는 건 답이 아니다. Databricks 측정에서 recall은 0.097 → 0.916까지 계속 오르지만 정확도는 꺾인다 — GPT-4-turbo는 16k, Llama-3.1-405b는 32k에서 정점이고 DBRX는 32k에서 0.255로 붕괴했다(실패의 50.4%가 지시 무시). recall 곡선을 정확도 곡선으로 착각하지 말 것.

가장 저평가된 기법: 질의를 변환하지 않는 것

같은 Fudan 실험에 조용히 들어 있는 결과가 있다. BERT-base 다국어 분류기(정확도 0.95)로 "검색이 필요한 질의인가"를 먼저 거르면 평균 점수는 0.428 → 0.443으로 오르고 지연은 16.41초 → 11.58초로 줄어든다. 품질과 비용이 동시에 좋아지는 드문 케이스다. 다음 글은 이 아이디어를 끝까지 밀어붙인 계열 — 언제 검색하고 언제 다시 검색할지를 시스템이 판단하는 Adaptive·Self·Corrective RAG다.

— RAG 종류 총정리 시리즈 ④ / 다음 글: Adaptive·Self·Corrective RAG — 언제 검색을 건너뛸까

RAG 종류 총정리 ② — 하이브리드 검색과 리랭킹: BM25는 왜 아직 안 죽었나

RAG 개선안 중 가장 싼 것부터 쓰는 게 맞다. 그리고 가장 싼 것은 LLM 호출을 늘리지 않는 것들 — 순서 바꾸기, 하이브리드 검색, 리랭킹이다. 이 글은 검색 레이어 자체를 다룬다. 결론부터 말하면 BM25는 아직 안 죽었고, 한국어에서는 더 안 죽었다.

같은 모델로 통제한 비교: 하이브리드는 언제 이기나

BGE-M3는 하나의 모델이 dense·sparse·multi-vector 세 점수를 동시에 내기 때문에, 모델을 바꾸지 않고 검색 방식만 바꾼 비교가 가능하다. nDCG@10 기준:

벤치마크BM25DenseSparseDense+Sparse
MIRACL (짧은 질의)31.969.253.970.4
MLDR (장문 문서)53.652.562.264.8

짧은 질의에서 하이브리드 이득은 +1.2점뿐이지만 장문 문서에서는 dense 52.5 → 64.8로 +12.3점이고, 무엇보다 BM25(53.6)가 dense(52.5)를 이긴다. 사내 위키·계약서·매뉴얼처럼 문서가 긴 RAG라면 하이브리드는 선택이 아니다. Fudan의 전수 비교도 같은 방향이다 — TREC DL19 mAP가 BM25 30.13에서 하이브리드 47.14로 오르는데 지연은 0.07초 → 3.20초, 그리고 여기에 HyDE를 얹으면 52.13이지만 11.16초다(④편).

dense가 구조적으로 못 잡는 것들

Azure의 문서는 키워드가 유리한 경우를 못 박아 뒀다 — 제품 코드, 고도로 전문화된 은어, 날짜, 사람 이름. 국내 사례가 더 생생하다. 컬리가 사내 문서 RAG를 두 번 갈아엎은 기록에서:

  • 역인덱스만 쓰던 1차에서는 "샛별"과 "새벽배송"이 매칭되지 않았다 — dense가 필요한 지점.
  • 임베딩만 쓴 2차에서는 "DOS-bot", "TICKET-1234" 같은 약어·식별자가 서브워드로 분해되며 의미를 잃었다 — BM25가 필요한 지점.
  • 결정적으로, 문서의 약 85%가 임베딩 모델의 512토큰 한도를 넘어 앞부분만 색인되고 있었다.
  • 최종안은 요약 임베딩 + 본문 BM25 하이브리드(시맨틱 top3 + 키워드 top2 병합).

마지막 항목이 한국어의 함정이다. 한글은 토큰 효율이 나빠 900자만 넘어도 512토큰을 넘긴다. 임베딩 모델을 고를 때 컨텍스트 길이도 기준이어야 한다 — gemini-embedding-001은 2,048토큰, BGE-M3는 8,192, voyage-4는 32,000이다.

합치는 방법: RRF는 기본값이지 정답이 아니다

Elasticsearch의 RRF1/(60+rank)로 두 순위를 합치고 "튜닝이 필요 없다"고 홍보한다. 그런데 Amazon의 융합 함수 분석은 반대 결론이다 — RRF가 오히려 파라미터에 민감하고, 가중 점수 합(convex combination)이 도메인 안팎 모두에서 더 강건하며 튜닝할 파라미터가 하나뿐이라 소량 샘플로 맞출 수 있다. Weaviate는 v1.24부터 relativeScoreFusion을 기본값으로 바꾸며 FIQA에서 recall 약 +6%를 근거로 들었다. 평가셋 100~200건만 있으면 가중치 하나 튜닝으로 얻는 공짜 이득이다.

리랭커: 후보를 좁힌 뒤에만

  • 한계효용: Anthropic 측정에서 top-20 검색 실패율은 임베딩만 5.7% → 하이브리드 2.9% → 리랭킹 1.9%. 하이브리드가 절반을 줄이고 리랭커가 남은 것의 1/3을 더 줄인다. 순서는 반드시 하이브리드 먼저.
  • 리랭커는 정확도가 아니라 지연으로 고른다: 같은 Fudan 실험에서 TILDEv2 MRR@10 27.83에 0.02초, monoT5 31.78에 4.5초, RankLLaMA 32.35에 82.4초. 제일 정확한 모델이 온라인 서빙 불가다.
  • 작아도 된다: Qwen3-Reranker는 4B(MTEB-R 69.76)와 8B(69.02)가 사실상 동급이고, 0.6B만으로도 같은 크기 임베딩 대비 MTEB-R +4.0, 장문(MLDR) +17.0을 얹는다.
  • 과금 단위를 확인하라: Cohere는 건당(Bedrock 기준 1,000쿼리당 $2.00)인데 "1 search = 질의 1 + 문서 최대 100개"이고 500토큰 넘는 문서는 청크마다 1문서로 카운트된다. Voyage는 토큰당(rerank-2.5 $0.05/1M). 긴 청크를 많이 넣으면 유불리가 뒤집힌다.

한국어 검색의 두 갈래 준비물

BM25 쪽은 형태소 분석기가 곧 품질이다. Nori(mecab-ko-dic)는 Elasticsearch 기본이지만 사전이 고정적이고, Kiwi는 오타 교정과 사전 갱신이 있으며 정확도는 웹문서 약 87%·문어체 약 94%다. LY의 일본어 사례가 교훈적이다 — 모델번호 "AW-10DP3"이 "AW/10/DP/3"으로 쪼개졌다. 상품코드·티켓번호·식별자는 형태소 분석에서 빼고 keyword 필드로 따로 색인해야 한다.

Dense 쪽은 기본값을 의심해야 한다. 고려대 KURE 리더보드의 한국어 8종 평균 nDCG@10은 KURE-v1 0.695 > BGE-m3 0.687 > multilingual-e5-large 0.664 > OpenAI text-embedding-3-large 0.617. 다만 평균으로 고르지 말 것 — 데이터셋별 편차가 모델 편차보다 훨씬 크고(XPQA는 최고가 0.444, Belebele은 최저가 0.895), 상위 두 모델 격차는 0.3% 수준이라 임베딩 교체로 얻을 게 많지 않다. 예산은 파싱과 리랭커에 쓰는 편이 낫다(③편). 마지막으로 토스의 경고 — 임베딩 모델 교체는 인덱스 전면 리빌드이고, 호환 안 되는 벡터가 섞이지 않게 버전 관리 인프라가 따로 필요하다. 다음 글은 색인 단위를 손보는 계층이다.

— RAG 종류 총정리 시리즈 ② / 다음 글: 청킹·Contextual Retrieval·파싱 — 색인 단위를 똑똑하게

RAG 종류 총정리 ① — 어떤 RAG를 언제 쓰나: 비용으로 그린 지도

"RAG를 붙였는데 왜 안 되죠?"라는 질문에는 대개 두 가지가 섞여 있다. 어떤 RAG를 쓸지 안 정한 것과, 잘되는지 재는 방법을 안 정한 것. 이 시리즈는 2026년 현재 쓰이는 RAG 변형들 — 하이브리드, HyDE, Contextual Retrieval, Self·Corrective·Adaptive, GraphRAG, Agentic, 멀티모달 — 을 "무엇인지"가 아니라 언제 값을 하고 얼마가 드는지로 정리한다. 앞선 "RAG 실전" 시리즈가 구축 방법이었다면, 이번은 선택 기준이다.

먼저 냉정한 숫자부터

  • RAG를 붙이는 것만으로는 부족하다. Meta의 CRAG 벤치마크(4,409문항, 5개 도메인)에서 LLM 단독 34% 이하, 단순 RAG 44%, 업계 최고 솔루션도 환각 없는 정답률 63%였다. FinanceBench에서는 검색을 붙인 GPT-4-Turbo가 81%를 틀리거나 거절했다.
  • Naive RAG는 종종 "검색 안 함"보다 나쁘다. Rewrite-Retrieve-Read 논문에서 HotpotQA EM은 검색 없이 답할 때 32.36, retrieve-then-read가 30.47이었다.
  • 컨텍스트에 넣었다고 읽는 것도 아니다. Lost in the Middle: GPT-3.5-Turbo에 문서 30개를 주고 정답을 가운데 두면 50.5% — 문서를 아예 안 준 56.1%보다 낮다.
  • 우리가 넣는 컨텍스트의 대부분은 쓰레기다. Chroma의 토큰 단위 측정에서 청킹 전략별 precision은 2.7~8.0%(recall은 87~92%). 92~97%가 낭비라는 뜻이고, 그만큼 토큰 비용을 줄일 여지가 남아 있다.

RAG 변형의 다섯 계층

이름이 수십 개지만 손대는 지점은 다섯 곳뿐이다. 각 계층은 뒤로 갈수록 비싸진다.

  • ① 검색 자체 — BM25, dense 임베딩, 하이브리드, 리랭킹. LLM 호출이 늘지 않아 가장 싸다. (②편)
  • ② 색인 단위 — 청킹, Contextual Retrieval, late chunking, RAPTOR, 파싱. 일회성 비용이라 질의당 부담이 0이다. (③편)
  • ③ 질의 변환 — 재작성, 분해, HyDE, step-back. 질의당 LLM 호출이 1회 이상 붙는다. (④편)
  • ④ 흐름 제어 — Self-RAG, CRAG, Adaptive RAG, 라우팅. 크리틱·평가기 호출이 추가된다. (⑤편)
  • ⑤ 구조·자율성 — GraphRAG, 에이전틱 RAG, 딥리서치. 색인 비용이 1,000배, 질의 비용이 수백 배까지 뛴다. (⑥·⑦편)

비용은 자릿수로 갈린다

Sonnet 5($2/$10 per 1M) 기준으로 질의 하나의 실제 청구액을 계산하면 계층 간 차이가 선명하다.

방식질의당배수지연
단발 RAG (top-8)약 24원1배2~4초
+ 리랭커+3~5원1.2배+0.02~4.5초
반복 에이전트 (도구 5회)약 175원7.4배15~40초
같은 조건 + 프롬프트 캐싱약 63원2.6배동일
롱컨텍스트 200K 통째로약 563원24배10~25초
딥리서치 (리드+서브 4, 검색 40회)7천~1.1만 원300~470배5~30분

읽을 점 셋. 첫째, 캐싱만 켜도 에이전트가 7.4배에서 2.6배로 내려온다(앞 시리즈 ④편). 둘째, 색인 쪽은 반대로 계산한다 — Contextual Retrieval은 문서 100만 토큰당 $1.02의 일회성이고 질의당 추가가 0인 반면, full GraphRAG는 색인이 벡터 RAG의 1,000배다(⑥편). 셋째, 이 표는 토큰 시나리오를 가정한 모델링이니 자사 단가로 다시 계산해야 한다.

이 시리즈의 지도

② 하이브리드 검색과 리랭킹(가장 싼 개선) → ③ 색인 단위: 청킹·Contextual Retrieval·파싱 → ④ 질의 변환: HyDE·분해·step-back의 손익 → ⑤ Adaptive·Self·Corrective RAG: 언제 검색을 건너뛰나 → ⑥ GraphRAG와 구조화 데이터 → ⑦ 에이전틱 RAG와 "RAG는 죽었나" 논쟁 → ⑧ 멀티모달·문서·코드 RAG → ⑨ 평가: 무엇을 어떻게 재나 → ⑩ 멀티턴 대화형 RAG → ⑪ 권한 인식 검색과 보안 → ⑫ 색인 수명주기: 삭제·재임베딩·신선도 → ⑬ 한국어 조건과 결정 트리(완결).

미리 밝혀 두면, 이 시리즈의 결론은 "최신 변형을 쓰라"가 아니다. RAG 실패 7가지 지점 논문의 문장이 정확하다 — "RAG 시스템의 검증은 운영 중에만 실질적으로 가능하고, 견고함은 설계되는 것이 아니라 진화한다." 다음 글은 가장 싸고 가장 확실한 개선, 하이브리드 검색이다.

— RAG 종류 총정리 시리즈 ① / 다음 글: 하이브리드 검색과 리랭킹 — BM25는 왜 아직 안 죽었나

LLM 서빙 캐싱 ⑪ (완결) — 한국어 맥락과 CTO 플레이북

마지막 편은 두 가지다. 한국어로 서비스하는 회사에만 해당하는 조건 — 토큰 인플레이션, 국내 API의 캐시 지원, 망분리, 국내 GPU 단가 — 을 숫자로 정리하고, 열 편의 내용을 "우리 회사는 어디서 시작하나"라는 결정 트리로 접는다.

한국어는 정말 토큰을 3배 더 쓰나 — 실측치는 1.5~2.1배

"한국어는 토큰 3~5배"라는 기사가 돌지만 1차 출처가 없다. HyperCLOVA X 기술 리포트의 표가 가장 신뢰할 만하다: 같은 한국어 코퍼스에서 HCX를 1.00으로 두면 GPT-4 토크나이저 2.10배, LLaMA 2 3.07배, Gemma 1.51배. 국내 실측은 영어 대비 한국어 토큰이 Qwen3-8B 1.95배, DeepSeek-V3 1.87배. 원인은 한글 1자 = UTF-8 3바이트. 한글 1자당 토큰은 Claude(4.5 기준) ≈ 1.0, GPT-5.1 ≈ 0.62, Gemini 3 Pro ≈ 0.55 — 10,000자 입력이 9,996 / 6,160 / 5,530 토큰이다. 제공사 간 1.8배 차이가 나므로 단가표가 아니라 토큰화 후 단가로 비교해야 한다. 캐싱에는 두 가지 함의가 있다. 입력이 2배로 부풀면 캐시 절감 절대액도 2배이고, 최소 캐시 길이 1,024토큰은 Claude 기준 한글 약 1,000자·GPT 기준 약 1,650자면 채워져 한국어 시스템 프롬프트와 RAG 문서는 거의 항상 캐시 대상이다.

자체 서빙이라면 토크나이저가 곧 KV 캐시 예산

EXAONE 3.0 리포트의 한국어 단어당 토큰: EXAONE 2.46, Llama 3.1 3.01, Gemma 2 3.31, Qwen2 3.29, Mistral 5.22(영어는 전부 1.35~1.55). SKT A.X 4.0은 GPT-4o 대비 한국어 토큰 33% 절감, 서울대 Thunder-Tok은 Llama-3.1에 한국어 92K 토큰을 추가해 단어당 토큰 −44%. 토큰이 줄면 prefill·KV 메모리·프리픽스 캐시 점유가 같은 비율로 준다. 단, 토큰 절감률 ≠ 비용 절감률 — Thunder-Tok의 비용 절감 주장은 "약 10%"였다. 디코드는 memory-bound라 입력 절감이 선형으로 반영되지 않는다. 국내 대형 서비스의 공개 실측으로는 카카오 Kanana-Flex FP8(H200×8: 처리량 +43%, TTFT −34%, 메모리 −50%, 정확도 +1.5pt)과 SKT의 vLLM V1 전환(1,760→2,154 tok/s, TTFT 372→182ms, 프리픽스 캐싱으로 서비스 시나리오 약 2배)이 있다.

국내 API·망분리·GPU 단가가 만드는 결론

  • 캐시 단가를 공개한 국내 API는 Upstage뿐(④편). CLOVA Studio는 2025-04부터 입출력 분리 과금이지만 캐시 항목이 없고, Kanana·Mi:dm은 단가 미공개. 국내 모델은 오픈 웨이트 자체 서빙이 주 경로이므로 절감은 ③·⑦편의 서버 쪽 캐시에서 나온다.
  • 망분리: 금융 망분리 로드맵에 따라 2026-04-20부터 금보원 평가를 통과한 SaaS는 내부망 허용이지만 개인신용정보·고유식별정보 처리는 여전히 불가, 공공은 N2SF 기밀·민감 등급이 자체 구축이다. 금융·공공은 외부 API의 캐시 할인을 받을 수 없으니 서버 쪽 캐싱이 유일한 레버다.
  • 국내 GPU는 AWS보다 싸지 않다: KT클라우드 A100×2 12,090원/시간 vs AWS 약 11,664원, 그것도 고정 할당이라 유휴 시에도 과금. AWS H100 $6.88 vs 국내 네오클라우드 $2.39~2.98(VESSL 기준). 고정 할당 GPU는 "항상 따뜻하지만 항상 켜져 있는" 캐시다 — ⑨편의 워밍 경제학이 뒤집힌다.
  • 한국어 시맨틱 캐시 임베딩은 0.6B급이면 충분하다. Ko-StrategyQA에서 snowflake-ko 0.805, KURE-v1 0.800, bge-m3 0.794 — 모델 간 1pt 이내. 국내 히트율 공개 사례는 당근(⑥편) 하나뿐이니 직접 재라(⑧편).

CTO 결정 트리 — 어디서 시작하나

  • API 사용 + 요청 간격 5분 미만 → 프롬프트 정렬(고정→도구→사용자, ⑤편) + 5분 캐시 + cached_tokens 스트림별 계측(④편). 첫 주에 25~50%.
  • API 사용 + 간격 5~60분 → 1시간 TTL, 그 이상이면 워머 손익 계산(⑨편). 저볼륨이면 Gemini 암묵 캐싱이나 DeepSeek 디스크 캐시.
  • FAQ·분류처럼 반복 질의 30% 이상 → 정확일치 캐시 먼저, 시맨틱은 로그에서 반복률을 재고(⑧편) 임계값 0.92부터(⑥편).
  • 자체 서빙, 레플리카 1대 → 프리픽스 캐시는 이미 켜져 있다. 히트율 대시보드 → 프롬프트 정렬 → FP8 KV(7K 토큰 이상) 순(②·③·⑦편).
  • 자체 서빙, 레플리카 2대 이상 → 세션 스티키 → 프리픽스 라우팅 → 멀티턴·에이전트면 DRAM 오프로드와 공유 스토어(③·⑦편). 오토스케일링은 캐시를 깬다(⑨편).
  • 5K 토큰 이상 고정 프롬프트가 월 100만 건 이상 → 캐시 vs 파인튜닝 손익분기(⑩편).
  • 금융·공공 망분리 → 위의 자체 서빙 경로만 해당. 토크나이저 선택이 첫 번째 캐시 최적화.

KPI는 토큰당 비용이 아니라 "해결된 대화당 비용"

FinOps 재단의 AI 프레임워크는 쿼리·대화·워크플로 완료당 비용을 권하고, RAG·에이전트의 주변 인프라(벡터 DB·임베딩·관측)가 기능 지출의 40~60%라고 본다. 시맨틱 캐시의 Redis 청구서는 같은 줄에 적어야 하고, 시맨틱 캐시 도입은 CSAT·에스컬레이션 A/B 게이트를 통과해야 한다. 그리고 이 시리즈를 쓰며 확인한 사실 하나 — 2026년 8월 현재 프롬프트 캐시 히트율과 절감액을 숫자로 공개한 국내 기업 사례는 없다(네이버의 "운영비 1/3"은 sLM 라우팅 이야기다). 처음으로 공개하는 회사가 기준이 된다.

— LLM 서빙 캐싱 시리즈 ⑪ (완결) / 관련 시리즈: 에이전트 설계 ⑤ 컨텍스트 엔지니어링, RAG 실전 ⑨ 증분 색인, 사용자 의도 분석과 LLM 라우팅 ④ 라우팅과 비용

LLM 서빙 캐싱 ⑩ — 캐시 vs 파인튜닝 vs 프롬프트 압축: 프리픽스를 안 보내는 선택

5K 토큰짜리 시스템 프롬프트에 few-shot 예시 스무 개를 넣고 있다면, 이 시리즈의 암묵적 답은 "캐시해라"였다. CTO의 대안은 둘 더 있다. 그 프롬프트를 파인튜닝으로 모델에 구워 넣어 아예 안 보내거나, 압축해서 짧게 보내거나. 이 글은 2026년 8월 가격으로 세 선택의 100만 요청당 비용을 계산하고, 파인튜닝이 진짜 이기는 조건과 자체 서빙에서 LoRA 어댑터가 프리픽스 캐시를 쪼개는 함정을 다룬다.

"캐시하지 말고 없애라"는 유혹과 1.5배 프리미엄

OpenAI의 파인튜닝 모델 추론은 베이스의 1.5배다: ft:gpt-4.1 입력 $3/캐시 $0.75/출력 $12(베이스 $2/$0.50/$8), 학습 $25/M토큰. GPT-5 계열은 파인튜닝이 불가하고 SFT/DPO는 4.1 계열, RFT는 o4-mini뿐이다. Anthropic은 1st-party 파인튜닝이 없고 Bedrock의 Claude 3 Haiku만 가능한데 커스텀 모델은 Provisioned Throughput 필수(시간당 고정비, 단가는 영업 문의). Gemini API의 파인튜닝은 2025-05 종료됐고 Vertex 전용이다. 세 벤더 모두 "캐시가 기본, 튜닝은 엔터프라이즈 옵션"으로 정렬됐고, Anthropic 문서는 아예 "예시 1~2개 대신 20개 이상을 넣고 캐시하라"고 쓴다.

100만 요청 시뮬레이션

가정: 정적 프리픽스 8,000 + 동적 입력 500 + 출력 300 토큰. 파인튜닝 후 프리픽스 −85%(잔여 1,200), 학습 22.5M 토큰.

시나리오$/100만 요청
(a) Sonnet 5, 캐시 없음$20,000
(b) Sonnet 5, 캐시 히트 95% / 80% / 50%$6,520 / $9,280 / $14,800
(b') gpt-4.1 베이스, 캐시 95%$8,000
(c) ft:gpt-4.1, 짧은 프롬프트, 캐시 없음$8,700 + 학습 $562
(c') ft:gpt-4.1 + 잔여 프리픽스 캐시 95%$6,135 + $562
(c'') ft:gpt-4.1-mini (한 단계 작은 모델)$2,320 + $112
(d) Sonnet 5 + LLMLingua-2 3배 압축(고유 문서)$9,334 + 압축 GPU

읽을 점: 같은 티어에서는 캐시가 파인튜닝을 이긴다(b' $8,000 vs c $8,700) — 1.5배 프리미엄이 프리픽스 절감을 상쇄한다. 파인튜닝 모델에도 캐시를 걸어야(c') 역전되고 학습비 회수에 약 30만 요청이 든다. 캐시 손익분기 히트율은 5분 TTL 21.7%, 1시간 52.6%(④편). Bedrock PT 고정비 예시($40/시간)로 Sonnet 5 캐시 95%와 같아지려면 월 450만 요청이 필요하다.

파인튜닝이 진짜 이기는 세 가지 경우

  • 모델 다운그레이드: 표의 c''가 3.4배 싸다. 이건 프리픽스 문제가 아니라 "작은 모델이 이 작업을 하는가"라는 품질 평가 문제다 — sLM 평가 시리즈의 베이스라인 사다리가 여기서 쓰인다. Bedrock Haiku 3 파인튜닝 사례: 모더레이션 정확도 81.5→99.6%, 쿼리당 토큰 −85%.
  • 컨텍스트에 안 들어가는 데이터: Bertsch et al.은 수백~1,500 shot 구간에서 long-context ICL이 대부분 LoRA를 넘고(Clinic-150, 151라벨에서 ICL 1,500 shot ≈ 89%), 고정 예시 집합을 한 번 인코딩해 캐시해도 손실 ≤5점이라고 보고했다. Many-shot ICL(DeepMind)도 "파인튜닝과 비슷하되 추론 비용은 선형 증가" — 즉 캐시 없이는 성립하지 않고, 캐시가 있으면 파인튜닝이 필요 없는 구간이 넓다. 파인튜닝이 이기는 건 데이터가 컨텍스트를 넘을 때다.
  • 최소 캐시 단위 미만: 프리픽스가 1,024(Sonnet 5)·4,096(Haiku 4.5) 토큰 미만이면 캐시 자체가 안 걸린다. "프롬프트 줄이기"가 캐시 자격을 없앨 수 있고, 그 구간에서는 짧은 프롬프트 + 파인튜닝이 합리적이다.

자체 서빙의 함정 — LoRA 어댑터는 프리픽스 캐시를 쪼갠다

vLLM의 블록 해시는 lora_name을 키에 포함하고(③편), SGLang의 RadixKey는 extra_key가 다르면 프리픽스 노드를 공유하지 않는다. 테넌트 100개를 어댑터로 나누면 공유 시스템 프롬프트의 캐시가 100조각이 된다. 계산 오버헤드 자체는 작다 — S-LoRA는 A100 한 장에 어댑터 2,000개, Punica는 토큰당 ≈2ms — 손실은 히트율과 KV 메모리 잠식에서 온다. 결정 매트릭스: 말투·규칙·예시 차이는 프롬프트(공유·캐시 가능), 출력 분포 변경·수천 라벨·컨텍스트를 넘는 지식은 어댑터(격리). 어댑터라도 --max-loras(GPU 상주)·--max-cpu-loras(CPU 대기)로 상위 트래픽만 상주시킨다.

압축의 자리, 그리고 한국어

LLMLingua-2는 3배 압축에서 MeetingBank QA 86.9 vs 87.8, GSM8K 손실 0, 5배에서 LongBench −11%. 캐시 읽기(정가 10%)가 압축(20~33%)보다 싸므로 압축은 캐시의 대체재가 아니라 보완재다 — 캐시가 못 잡는 고유 장문 문서(표의 d)에만 쓰고, 정적 프리픽스에 압축을 걸면 토큰이 바뀌어 캐시 키가 깨진다. 한국어 프리픽스는 1.3~2배 토큰(⑪편)이라 캐시 절감액도 파인튜닝 절감액도 커지고, 한국어 토크나이저 모델(A.X·EXAONE·Solar)이 제3의 길이다. 국내 벤더는 Upstage가 캐시 요율은 공개했지만 튜닝 단가는 비공개, CLOVA Studio는 튜닝 추론 프리미엄이 문서에 없다 — 계약 전 서면 확인 항목이다. LLMLingua-2의 한국어 성능은 미검증이고 조사(은/는/이/가) 삭제 리스크가 있으니 자체 평가가 먼저다. 마지막 글은 한국어 조건 전체와 결정 트리다.

— LLM 서빙 캐싱 시리즈 ⑩ / 다음 글: 한국어 맥락과 CTO 플레이북 (완결)

LLM 서빙 캐싱 ⑨ — 캐시 수명주기 운영: 워밍, 콜드 캐시, 오토스케일링

히트율은 설계 시점의 속성이 아니다. 파드가 늘어날 때, 모델을 교체할 때, 스팟 노드가 회수될 때, 트래픽이 TTL보다 뜸해질 때마다 무너진다. API 사용자에게는 "4분 30초마다 핑을 보내 5분 캐시를 살려둘까"가 곧 청구서 결정이고, 자체 서빙에서는 오토스케일링이 캐시 지역성을 깬다. 이 글은 캐시가 죽는 순간의 비용을 계산한다.

캐시는 쓰는 순간이 아니라 죽는 순간에 돈이 샌다

만료 모델이 벤더마다 다르다. Anthropic은 5분/1시간 TTL이고 읽힐 때마다 무료로 갱신되며 수명은 요청 시작 시점부터다. OpenAI(GPT-5.6+)는 마지막 사용 후 30분 슬라이딩, 구모델은 prompt_cache_retention: "24h"가 추가 요금 없이 제공된다 — 워머가 필요 없다. Gemini 명시적 캐시는 시간당 저장료(2.5 Pro $4.50, Flash·3.x $1.00 per M토큰·시간)가 붙는다. 만료 뒤 첫 요청은 쓰기 할증(×1.25 또는 ×2)을 다시 낸다.

keep-alive 손익분기 — Sonnet 5로 직접 계산

  • 단가(프리픽스 1M 토큰당): 읽기 $0.20, 5분 쓰기 $2.50, 1시간 쓰기 $4.00. 5분 워머(max_tokens: 0, 공식 지원) 유지비 = 시간당 읽기 12회 = $2.40/시간. 미스 1회 추가 비용 = 쓰기 − 읽기 = $2.30. 1시간 캐시 프리미엄 = $1.50/쓰기.
  • 결론 1: 5분 워머는 다음 요청이 ~57분 안에 확실할 때만 이득이고, 1시간 공백을 워머($2.40)로 메우는 것보다 1시간 TTL($1.50)이 싸다. 요청이 시간당 0.55건만 넘어도 1시간 TTL이 5분을 이긴다. 10분 간격 트래픽 예: 5분 캐시 $8.37/시간, 5분+워머 $1.46~2.40, 1시간 캐시 $0.06.
  • 결론 2: 프롬프트 하나의 keep-alive는 동전 단위다(10K 프리픽스면 야간 15시간 유지 vs 재작성 차이 $0.01). 진짜 돈은 요청당 미스율 × 요청 수 — 팬아웃과 롤아웃 — 에서 샌다. 아침 프리워밍은 첫 사용자의 쓰기를 앞당길 뿐 비용 +0, TTFT만 이득.
  • Gemini: 명시적 캐시는 시간당 히트 4건 이상일 때만 회수되고, 2.5 Pro 100K를 야간 15시간 유지하면 재생성의 54배 — 퇴근 시 삭제, 출근 시 재생성(expireTime).

팬아웃과 롤아웃 — 캐시가 한꺼번에 비는 두 순간

  • 팬아웃: 캐시는 "첫 응답이 시작된 뒤"에 생긴다. 10K 프리픽스를 워커 50개가 동시에 콜드로 치면 50 × $0.025 = $1.25, 첫 요청의 first-byte를 기다린 뒤 49개를 보내면 $0.12 — 1/10이다.
  • 스케일아웃: 라운드로빈이면 N→N+1 직후 클러스터 히트율 ≈ 기존 × N/(N+1)(4→5대면 즉시 −20%p). 사용자별 멀티턴이 대부분이면 옮겨진 대화마다 전체 prefill 1회 — "동기화된 재계산 폭풍"이고 롤링 업데이트는 이를 레플리카 수만큼 반복한다. llm-d의 sticky-until-saturated는 캐시 토큰 80% 이상 엔드포인트에 붙이되 미캐시 in-flight 토큰이 임계를 넘을 때만 새 레플리카를 열어 기존 히트율을 보존하고, P2P KV 풀은 48K 프리픽스 재계산 1,988ms를 235ms로 줄였다.
  • 국내 사례: 토스증권(2026-08)은 배포 직후 프리픽스 캐시 히트율 0% — 설정 실수가 아니라 reasoning 모델 특성상 기본으로 꺼져 있었다. 켜니 20초 가까이 걸리던 TTFT가 1/10, 히트율 90%+. 같은 글의 다른 교훈: KV 사용률 1% 미만인데 처리량이 포화 → 동시성 한도만 올려 4배.
  • 롤아웃 = 전체 무효화: 토크나이저·챗 템플릿·모델 버전이 바뀌면 L3 스토어의 KV까지 전부 무효(Claude 4.7+ 토크나이저도 토큰 ~30% 증가). 모델 업데이트는 업무시간 밖에, 카나리 1대를 readiness probe에서 핫 시스템 프롬프트 N개로 한 바퀴 데운 뒤 전환.

게이트웨이가 안 해주는 것, 스케일링 신호, 스팟

동일 요청이 동시에 N건 들어올 때의 in-flight 병합(singleflight)은 Cloudflare가 문서로 명시하듯 아무도 안 해준다("동시에 온 두 번째 요청은 첫 번째가 캐시되기 전일 수 있다") — LiteLLM·Portkey·Helicone·Kong 전부 응답 캐시일 뿐이다. temperature 0 + body 해시로 "동일"을 정의하고 앱에서 Go singleflight나 Redis SET NX로 직접 구현한다. 스케일링 신호는 GKE 권고대로 큐 깊이(3~5) > 배치 크기 > GPU 지표 — vllm:kv_cache_usage_perc는 메모리 압력이지 과부하가 아니다. KEDA 기본 cooldown 300초는 LLM 파드 기동보다 짧을 수 있으니 기동 시간 이상으로. 스팟은 GCP 최대 91% 할인이지만 통지 0~120초·유예 30초, AWS 2분이라 80GB의 KV를 내보낼 수 없다 — HiCache/LMCache의 L3 write-through가 전제이고, 스팟은 배치·오프피크 prefill 풀에, 실시간 디코드는 온디맨드에.

한국 시간대의 트래픽 셰이핑과 고정 GPU

KST 09~18시 형태의 트래픽이면: Anthropic 1시간 TTL 기본(점심 공백 통과, 아침 프리워밍 1회), OpenAI는 24h, Gemini는 09시 생성·18시 만료. DeepSeek의 피크(UTC 01~04·06~10시)는 정확히 KST 10~13시, 15~19시 — 한국 업무시간이라 오프피크 50%를 받으려면 비실시간 작업을 13~15시와 19시 이후로 옮긴다. Batch API는 시간대 무관 50%이고 Anthropic은 캐시 할인과 중첩된다(배치 내 히트율 30~98%, 1시간 TTL 권장). 그리고 ⑪편에서 다룰 KT·NCP 고정 할당 GPU는 scale-in이 없어 "항상 따뜻하지만 야간에 논다" — 여기서는 keep-alive 문제가 사라지는 대신 야간 15시간을 채우는 배치(임베딩 재생성·평가·요약 백로그)가 곧 절감이다. 다음 글은 프리픽스를 캐시하는 대신 아예 안 보내는 선택, 파인튜닝과의 손익 비교다.

— LLM 서빙 캐싱 시리즈 ⑨ / 다음 글: 캐시 vs 파인튜닝 vs 프롬프트 압축 — 프리픽스를 안 보내는 선택

LLM 서빙 캐싱 ⑧ — 도입 전에 재기: 로그 리플레이로 히트율 상한 추정

앞의 일곱 편에 나온 절감률 — 41~80%, 7%→84%, 히트율 25% — 은 전부 남의 트래픽 숫자다. CTO의 진짜 질문은 "우리 트래픽에서는 얼마나 나오나, 엔지니어 몇 주를 쓰기 전에 알 수 있나"다. 답은 있다. 프로덕션 로그를 리플레이해서 히트율의 상한을 재고, 벤치 도구로 타임스탬프까지 재현하고, API의 usage 필드로 실제 절감액을 검증하는 세 층이다. 이 글은 그 방법과 함정, 그리고 추정치와 실측치가 왜 벌어지는지를 다룬다.

상한(ceiling)은 예측이 아니다

무한 캐시를 가정하고 모든 요청을 prefix tree에 넣으면 "공유되는 토큰 비율"이 나온다. Preble의 측정은 도구 사용 85%, 임바디드 에이전트 97%, 프로그램 생성 97%, 장문 QA 91%. TraceLab(코딩 에이전트 4,265세션, 357,161스텝)은 사용자 프롬프트와 도구 결과만 "새 토큰"이라 전체 prefill의 약 81%가 원리상 캐시 가능하고, 실현 히트율은 95.7%였다. 반면 Mooncake(Kimi) 실트레이스는 무한 저장소여도 이론 상한이 ~50%, LRU 1K 블록에서 30%, 50K 블록에서야 50%였고 블록의 절반 이상은 두 번 다시 쓰이지 않았다. TraceLab에서 미스는 5분 유휴부터 시작해 1시간이면 거의 전부였고, 사람이 생각하는 동안의 공백이 비용의 12.8%였다. 상한과 실측을 벌리는 최대 변수는 TTL이다.

로그 분석 3종 — 프리픽스 상한, 정확일치 중복률, 근사중복률

토큰 가중 프리픽스 상한은 이렇게 잰다. 요청을 시간순으로 정렬하고, 실제로 보낸 그대로(tools+system+messages) 렌더링해 로컬 토크나이저로 토큰화하고, 스트림(테넌트·prompt_cache_key)별 radix trie에 넣되 노드마다 마지막 사용 시각을 기록한다. 새 요청은 블록 단위로 trie를 따라가다 (a) 자식이 없거나 (b) 마지막 사용이 TTL 밖이면 멈추고, 그때까지의 토큰 수가 히트다. 함정 둘: 부분 블록은 히트가 아니다(vLLM 16토큰, Mooncake 512토큰 단위로 내림 — vLLM의 오프라인 분석기 RFC가 실제 해시 체인을 그대로 재현한다), 그리고 API 최소 프리픽스(Claude 512~4,096, GPT-5.6+ 1,024) 미만이면 0이다 — OpenAI 쿡북의 예시로 900토큰 프롬프트는 절감 0, 1,100토큰은 히트 70%에서 −55%. TTL ∈ {5분, 30분, 1시간}, 블록 ∈ {16, 512}, 스트림 ∈ {테넌트, 키, 전역}으로 스윕하면 그 퍼짐이 곧 예상 오차다. 정확일치는 정규화 프롬프트의 SHA-256을 TTL 창 안에서 세고, 근사중복은 마지막 사용자 턴을 임베딩해 임계값 이상을 센다 — 단 뒤에서 보듯 이 마지막 숫자는 라벨 없이 믿으면 안 된다.

재현 테스트 — 타임스탬프까지 재생하기

  • vllm bench serve: --dataset-name prefix_repetition(프리픽스·접미사 길이, 프리픽스 수), custom(내 JSONL), timed_trace(Mooncake 형식, --timed-trace-sec-multiplier 0.001로 원속도 재생), --request-rate·--burstiness(1 미만이면 버스트).
  • SGLang bench_serving: generated-shared-prefix--gsp-group-distribution zipf가 "몇 테넌트가 트래픽을 지배"하는 현실을 모델링하고, --mooncake-workload conversation|agent는 한 줄 리플레이다.
  • inference-perf(llm-d): OTel GenAI 스팬에서 에이전트 DAG를 복원해 기록된 대기 시간을 wait_ms로 보존한다 — 사람 공백을 재현하는 유일한 도구. NVIDIA GenAI-Perf는 세션 delay로 "사용자 멈춤 길이 vs TTL"을 스윕한다.
  • 클러스터 단위 추정은 틀린다: llm-d에서 같은 코드 생성 워크로드가 동시성 20에서 48%로 정점을 찍고 레플리카 KV가 차면 무너졌지만, 150테넌트×6K 프리픽스 B2B는 90~95%를 유지했다. 레플리카·라우팅 키 단위로 추정할 것.

API 쪽 검증 — usage 필드와 캐시 진단

절감액 = Σ캐시 토큰 × (정가 − 읽기 단가) − Σ쓰기 토큰 × (쓰기 단가 − 정가). ProjectDiscovery의 방법이 표준이다: 실제 지출 vs "같은 볼륨을 전액으로 냈을 가상 비용"을 스트림별·주별로 — 집계는 오도한다(고정 스트림 84% vs 집계 69%). 작업 길이별 캐시율은 1스텝 35.5%, 20스텝 이상 74%, 1,225스텝 91.8%. 미스 원인은 Anthropic의 cache-diagnosis 베타가 system_changed | tools_changed | messages_changedcache_missed_input_tokens로 알려주고, OpenAI는 prompt_cache_key를 붙이는 것만으로 한 고객이 60%→87%가 됐다(키당 ~15 RPM 초과 시 콜드 레플리카). count_tokens는 무료(2,000~8,000 RPM)라 로그 토큰 가중치를 매기는 데 쓰면 된다.

시맨틱 캐시는 라벨 없이는 숫자를 믿지 말 것

2026년 8월 연구가 결정적이다: LMSYS-Chat·Quora·MOSS 각 10만 질의에서 임계값 0.90의 원시 히트율 50.7~57.0%가, Llama-3.1-8B 심판으로 "답을 대체해도 되는가"를 검사하자 1.6~2.2%로 줄었다. 임베딩 기반 추정은 10배 이상 부풀 수 있다(⑥편의 vCache가 보인 임계값 딜레마와 같은 이야기). 방어 가능한 프로토콜은 유사도 0.80~0.99 구간에서 5,000쌍 샘플, 라벨러 3명, 의도 클래스별 임계값(FAQ 0.94·지원 0.92·거래 0.97), 매주 히트의 1~5% 블라인드 감사 — 이 절차로 18%→67% 히트, 오탐 0.8%, −73%가 나왔다. 한국어는 KLUE-STS(≥4.0을 양성), KorSTS, PAWS-X ko(어휘는 겹치지만 뜻이 다른 적대적 음성 — 임베딩 캐시의 정확한 함정)로 시드를 만들고 자사 로그 쌍으로 교체한다. 평가 비용은 작다: vLLM 분석기는 CPU만, Mooncake 대화 리플레이(12K 요청, 1시간)는 GPU 한 대, 국내 SK 데보션의 부하테스트 글처럼 하루면 돌린다 — 비싼 줄은 라벨링뿐이다. 다음 글은 이렇게 얻은 히트율이 운영 중에 무너지는 순간들이다.

— LLM 서빙 캐싱 시리즈 ⑧ / 다음 글: 캐시 수명주기 운영 — 워밍, 콜드 캐시, 오토스케일링

LLM 서빙 캐싱 ⑦ — KV 압축·오프로딩·클러스터 공유: HBM 밖으로

②편에서 70B 모델의 128K 요청 하나가 KV 40GB, ③편에서 GPU 캐시 용량이 히트율을 막는 순간을 봤다. HBM은 비싸고 2026년에 더 비싸진다 — TrendForce는 3분기 서버 DRAM 계약가 +13~18%, HBM은 2027년 "수 배"를 예고했다. 그래서 KV 캐시를 (a) 작게 만들거나 (b) 싼 메모리로 옮기거나 (c) 클러스터 전체에서 공유하는 세 갈래가 서빙 비용의 다음 전선이다. 각각 언제 이득이고 언제 손해인지를 숫자로 본다.

작게 만들기: FP8은 공짜, 4비트는 계산서가 온다

  • FP8 KV: vLLM 2026-04 재측정에서 --kv-cache-dtype fp8은 처리량 손실 0에 KV 2배, Qwen3.5-27B AIME25 99%·Llama-3.3-70B 128K MRCR 97~98% 회복. 단 손익분기는 H100 ~7K 토큰(B200 ~4K) 이상이고, Hopper FP8 누적 오차로 128K needle이 91%→13%로 무너진 버그가 있었다(two-level accumulation으로 89% 복구). 교훈: 장문 회귀 테스트 없이 켜지 말 것.
  • 3~4비트: TurboQuant 비교에서 4비트는 추론 98% 회복이지만 처리량 BF16의 75~80%, 3비트는 AIME/GPQA −20점에 처리량 66~73%. 디퀀트 오버헤드가 메모리 절감을 되갚는다. 결론 "FP8 기본, 4비트는 극한 상황만". KIVI(2비트, 배치 4배)·KVQuant는 학계 상한선.
  • 토큰 축출: H2O는 heavy hitter 20%만 남겨 처리량 최대 29배, StreamingLLM은 sink 토큰 + 슬라이딩 윈도우로 400만 토큰 스트리밍. 그런데 2025-12 비교 연구는 낮은 예산 축출이 추론 모델의 트레이스를 길게 만들어 절약분을 되갚는다고 보고했다. 출력 토큰이 늘면 청구서는 오른다.

싸게 옮기기: CPU DRAM → NVMe → 원격 스토어

  • vLLM KV Offloading Connector(0.12): --kv_offloading_backend native --kv_offloading_size <GB>. H100/Llama-8B 단일 요청 TTFT 2~22배, 동시 요청 처리량 최대 9배(히트율 비례). "지연보다 처리량 이득이 훨씬 크다."
  • SGLang HiCache: GPU(L1)→CPU(L2)→외부(L3: Mooncake·3FS·NIXL·파일). 최대 6배 처리량, TTFT −80%. Novita AI(Qwen3-Coder-480B, 8턴·25K+)에서 히트율 40%→80%, TTFT −56%; Ant Group(R1-671B)에서 TTFT −84%.
  • LMCache/MI300X: DRAM 64GB만 붙여 TTFT 3.0배, 완료 요청 2.3배. 함정: PYTHONHASHSEED=0 없으면 히트율 0.
  • 하드웨어 의존: TRT-LLM 호스트 오프로드 재사용 TTFT 14배(H100 x86) vs 28배(GH200). CPU-GPU 대역폭이 ROI를 좌우한다.
  • 국내 벤치: 래블업×VAST(Mistral Medium 3.5 128B, 8×H100, 140K 토큰, vLLM+LMCache, GDS 100Gbps)는 첫 턴 +4초(22.3→26.3s), 이후 턴 22.0→6.6초(3.3배), 전체 1.96배. Backend.AI 한국어 해설의 조건표: 70B 이상·10K 토큰 이상·공유 프리픽스가 많으면 이득, 단일 턴 챗봇·TCP NFS면 손해.

클러스터에서 공유하기: Mooncake와 DeepSeek의 숫자

  • Mooncake(Kimi): prefill/decode 분리 + 유휴 CPU·DRAM·SSD를 분산 KV 풀로. 실서비스에서 75% 더 많은 요청(FAST'25 버전 A800 115%), 수천 노드, 일 1,000억+ 토큰. vLLM×Mooncake 에이전트 벤치(SWE-bench 트레이스 610개, 중앙값 33턴, 재사용 프리픽스 94.2%)에서 로컬 캐시 히트율은 1.7%였는데 Mooncake Store로 92.2% — 처리량 3.8배, P50 TTFT 46배, 12→60 GPU 선형. 에이전트 워크로드는 로컬 프리픽스 캐시를 무력화한다(재사용은 94%인데 히트는 1.7%).
  • DeepSeek 공개 손익: 평균 226.75 H800 노드, 일 비용 $87,072 vs 이론 매출 $562,027(마진 545%). 입력 608B 토큰 중 56.3%가 디스크 KV 히트. V4 캐시 히트는 미스의 3.3% — 히트율이 곧 단가다.
  • 라우팅 먼저: ③편의 llm-d 라우팅만으로 P90 TTFT 57배. 오프로드 전에 "요청을 캐시가 있는 파드로". PD 분리는 이제 표준이고 DistServe 기준 KV 전송비는 지연의 0.1% 미만, NIXL이 RDMA부터 S3까지 백엔드화했다. ByteDance AIBrix는 L1 DRAM + L2 원격(RDMA)으로 P99 TTFT 384.6초→0.22초.

CTO 체크리스트: 우리 워크로드에 맞는 계층은

순서는 측정(프롬프트 길이·턴 수·프리픽스 공유율, ⑧편) → FP8 KV(7K 토큰 이상이면) → 프롬프트 정렬과 라우팅(③편) → CPU DRAM 오프로드(멀티턴·긴 문서·70B 이상) → 멀티노드면 공유 스토어. 운영 함정은 PYTHONHASHSEED, 프롬프트 앞의 타임스탬프, 멀티테넌트 cache_salt, 장문 회귀 테스트. 여기까지가 "캐시를 어떻게 쓰나"였다면, 다음 세 편은 "우리 트래픽에서 얼마나 남는지 도입 전에 어떻게 아나"다.

— LLM 서빙 캐싱 시리즈 ⑦ / 다음 글: 도입 전에 재기 — 로그 리플레이로 히트율 상한 추정

LLM 서빙 캐싱 ⑥ — 시맨틱 캐시: 현실 히트율과 오탐의 비용

앞의 세 편이 다룬 캐시는 전부 입력 쪽이었다. 출력 토큰 — 청구서의 30~60% — 을 줄이는 캐시는 하나뿐이다. 호출 자체를 없애는 응답 캐시. 정확일치 캐시는 공짜이고 오탐이 없지만 잡는 게 적고, 시맨틱 캐시는 더 많이 잡지만 틀린 답을 돌려줄 수 있다. 이 글은 벤더의 "히트율 95%"가 무슨 뜻인지, 국내에서 실제로 돌아간 숫자는 무엇인지, 오탐을 어떻게 다루는지를 정리한다.

같은 질문에 두 번 돈 내지 않기 — 정확일치 캐시부터

키는 정규화한 프롬프트 + 모델 + temperature + 도구 + 프롬프트 버전의 해시. MeanCache는 LLM 서비스 질의의 약 31%가 반복이라고 보고했고, 한 10만 건 샘플에서는 18%가 정확 중복, 47%가 유사, 35%가 신규였다. FAQ 봇이나 분류 작업(temperature 0)이라면 이것만으로 15~30%가 바로 빠진다. Helicone은 해시 키 + 버킷(temperature>0일 때 응답 여러 개 저장), Portkey의 simple 모드, Cloudflare AI Gateway가 이 계층이다.

시맨틱 캐시의 구조와 진짜 히트율

쿼리를 임베딩 → 벡터 검색 → 임계값 이상이면 저장된 응답 반환. 절감액 = 출력 토큰 비용 × 히트율, 임베딩 비용은 토큰당 LLM의 1/1,000이지만 매 요청 발생한다. 벤더가 말하는 "95%"는 히트의 정확도이지 히트 빈도가 아니다. 프로덕션 데이터의 현실 히트율은 FAQ·고객지원 40~60%, 분류 50~70%, 사내 KB 30~45%, 문서 RAG 15~25%, 자유 대화 10~20%, 코드·에이전트 5~15%. Portkey는 기업 RAG 반복률 약 20%(정확도 99%)라고 했다. 인프라는 월 $50~200 — 절감액의 5% 미만이지만, 히트율 10% 미만이거나 월 지출 $1~2K 미만이면 운영 비용이 절감을 넘는다.

당근 사례: 임계값 0.65, 히트 25%, 연 2.16억 원

국내 검증된 유일한 프로덕션 숫자는 당근 채팅팀의 2025년 기록이다. AI 메시지 추천의 LLM 비용이 연 8~9억 원. 발화 1,000건을 text-embedding-3-small로 임베딩해 PCA로 50차원으로 줄이고 DBSCAN으로 군집화하니 60% 이상이 노이즈, 13개 군집·약 260개 대표 문장이 남았다. 이 대표 문장만 캐시로 두고 인프로세스 벡터 스토어(chromem-go, 1,000벡터 ≈ 6MB, 검색 2ms)를 붙였다. 코사인 임계값 0.65에서 오프라인 히트 29.55%, 프로덕션 약 25% → 연 약 2.16억 원. 병목은 임베딩 API 호출(400~800ms)이었고, 맥락에 안 맞는 추천이 나와 메타데이터 필터링을 계획했다. 낮은 임계값이 통한 이유는 원시 이력이 아니라 큐레이션된 대표 문장을 캐시했기 때문이다 — SCALM도 같은 접근으로 GPTCache 대비 히트 +63%, 토큰 −77%.

"내일 날씨"와 "어제 날씨": 오탐을 다루는 다섯 가지 방법

임계값은 상수가 아니다. Portkey의 스윕에서 0.99 → 히트 23.5%/정확도 92.1%, 0.95 → 56.0%/92.6%, 0.90 → 74.5%/92.3%, 0.80 → 87.6%/91.8%. 한 금융 봇은 0.88에서 "계좌 해지"를 "결제 취소"에 매칭했고, 0.7로 내린 사례는 오탐 ~99%였다. 오탐이 조정 후에도 3~5%를 넘으면 임계값이 아니라 모델 문제다.

  • 카테고리별 임계값: FAQ 0.94, 상품 0.88, 지원 0.92, 거래 0.97처럼 유형마다 다르게. 거래·가격·재고는 바이패스.
  • 의도+슬롯 정규화 키: 2026년 연구에서 GPTCache의 캐시 키 일관성은 37.9%, SetFit 의도 분류기(2ms)로 {의도, 슬롯}을 키로 쓰면 91.1%. "내일/어제 서울 날씨"는 슬롯이 다르니 자연히 분리된다 — 의도 분류 시리즈와 이어지는 지점이다.
  • 오류 예산 기반 임계값: vCache(ICLR 2026)는 캐시 항목마다 임계값을 온라인 학습해 정적 임계값 대비 히트 12.5배, 오류 26배 감소.
  • 비동기 LLM 판정·캐시 전용 임베딩: Redis LangCache의 20M 파라미터 임베더는 "질문-질문 동치"만 학습했다. 평가는 KorSTS가 아니라 목표 히트율에서의 정밀도(P-CHR)로 — PR-AUC 1위 모델이 고정 임계값에서는 꼴찌일 수 있다.
  • 스코프와 버전: 키에 사용자·테넌트·프롬프트 버전·임베딩 모델·KB 버전. 공유 시맨틱 캐시는 키 충돌 공격(적대적 접미사로 주입 성공 82%, 에이전트 도구 하이재킹 90.6%)의 대상이다.

한국어 임베딩은 bge-m3·KURE-v1(자체 호스팅, MTEB-ko 검색 0.52 vs OpenAI 3-large 0.45)·ko-sroberta·Upstage 중 어느 것도 캐시 동치를 학습한 모델은 없으니, 로그에서 뽑은 유사-비동치 쌍 100개 이상으로 직접 재야 한다. 시작 임계값은 0.92 + 여유 0.02, 응답 캐시는 0.98 이상, TTL은 휘발성 15~30분·FAQ 수일. 다음 글은 다시 서버 쪽으로 돌아가 KV 캐시를 HBM 밖으로 내보내는 이야기다.

— LLM 서빙 캐싱 시리즈 ⑥ / 다음 글: KV 압축·오프로딩·클러스터 공유 — HBM 밖으로

LLM 서빙 캐싱 ⑤ — 에이전트·멀티턴·RAG: 앱 계층의 캐시 다섯 층

에이전트의 청구서는 대화가 아니라 반복에서 나온다. 매 턴 같은 시스템 프롬프트, 같은 도구 정의, 같은 이력을 다시 보내고, RAG는 같은 문서를 다시 임베딩하고 다시 리랭킹한다. 이 글은 LLM "주변"의 캐시를 다룬다 — 멀티턴을 캐시 친화적으로 설계하는 규칙, RAG 파이프라인의 다섯 캐시 층, 게이트웨이 설정 한 줄, 그리고 캐시하면 안 되는 것.

에이전트 비용의 정체: 입력 100 : 출력 1

Manus는 "KV 캐시 히트율이 프로덕션 에이전트의 단일 최우선 지표"라고 썼다. 입력:출력이 100:1이니 캐시 읽기(정가의 10%)와 미스의 차이가 곧 10배다. PwC 연구팀의 실험(OpenAI·Anthropic·Google, DeepResearch 세션 500+건, 시스템 프롬프트 10K, 도구 호출 3~50회)에서 전략적 캐싱은 비용 −41~80%, TTFT −13~31%였다. 그런데 "무조건 전체 캐시"는 역효과였다 — 동적 도구 결과를 캐시 경계 안에 넣으면 매번 쓰기 할증만 낸다.

대화는 append-only로 — 히트율 7%가 74%가 된 한 줄

  • ProjectDiscovery: 4K 시스템 프롬프트를 매번 보내는데 히트율 7%. 프롬프트 중간의 동적 식별자 하나를 끝으로 옮기자 74%, 월 비용 −59%. 이후 시스템 프롬프트 1시간 캐시·정적 도구 알파벳 정렬·마지막 도구 결과에 5분 슬라이딩 브레이크포인트로 84%까지.
  • 규칙: 초 단위 타임스탬프 금지, JSON 직렬화는 결정적으로, 도구는 제거 대신 마스킹(allowed_tools), 이력은 append만. Anthropic은 최상위 cache_control 하나면 브레이크포인트가 자동 전진하고(20블록 룩백), OpenAI는 prompt_cache_key로 세션을 같은 레플리카에 붙인다.
  • 요약(compaction)은 공짜가 아니다: 실측에서 전체 이력+캐시는 턴당 $0.11·회상 92%, 요약은 $0.24·회상 38%였다. 캐시 단가가 ≈$0.55/M 이하면 요약이 더 비싸다. 도구 출력 길이 제한만으로 −38%가 나왔고, Anthropic도 "tool result clearing"을 가장 안전한 경량 압축으로 권한다.

RAG 파이프라인의 다섯 캐시 층 — 돈은 어디에 있나

  • 쿼리 임베딩 캐시 — 지연용이지 절감용이 아니다. 임베딩 단가는 $0.01~0.15/M(BGE-M3 $0.01, text-embedding-3-small $0.02)이라 월 1,000만 쿼리를 전부 캐시해도 ≈$6.
  • 재인덱싱 콘텐츠 해시 — 변경 없는 청크를 다시 임베딩하지 않는 것. 10억 토큰 코퍼스 1회 = $130~150.
  • 리랭커 캐시 — 가장 무거운 단계. Cohere Rerank $1~2.5/1K 검색이니 100만 검색 = $1,000~2,500. (query+chunks)→순서를 캐시.
  • 검색 결과 캐시 — 유사도 0.85 이상 쿼리는 응답은 달라도 청크는 같다.
  • 청크 KV 재사용(자체 서빙) — 프리픽스가 아닌 위치의 문서 KV를 재사용하는 연구가 실제 제품에 들어왔다. CacheBlend(LMCache)는 토큰 10~15%만 재계산해 TTFT 2.2~3.3배·처리량 2.8~5배, TurboRAG는 모델 수정 없이 TTFT 9.4배, Prompt Cache(Yale)는 GPU 8배·CPU 60배. 코퍼스가 고정적이면 인덱싱 시점에 KV까지 만들어 두는 것이 다음 단계다.

게이트웨이는 헤더 한 줄

LiteLLMcache_params: {type: redis, ttl: 600}(시맨틱은 redis-semantic + similarity_threshold), Cloudflare AI Gatewaycf-aig-cache-ttl: 3600과 응답 cf-aig-cache-status: HIT, HeliconeHelicone-Cache-Enabled + 사용자별 Helicone-Cache-Seed, Portkey는 {"cache":{"mode":"simple","max_age":60}}, Kong은 ai-semantic-cache 플러그인. 도구 결과 캐시는 idempotent이고 TTL 안에 노화하지 않고 부작용이 없을 때만 — TVCache는 키에 인자만이 아니라 상태 이력을 넣어 히트율 70%, 도구 실행 시간 6.9배 단축을 얻었다.

캐시하면 안 되는 것, 그리고 계측

개인화·테넌트 의존 응답(키에 tenant·permission·source version이 없으면 데이터 노출), 시간 민감 정보, 상태 의존 도구 결과, 고위험 응답(환각이 캐시되면 유사 질의 전부 오염), 그리고 임베딩 모델 교체 시 전량 무효화. 국내 실무 가이드의 표현을 빌리면 "자주 히트하는 시스템이 아니라 안전하게 미스하는 시스템". 계측은 cache_read_input_tokens/cached_tokens를 토큰 가중 히트율로 — Langfuse의 OTel 경로에서 캐시 토큰이 정가로 계산되는 버그(2026)가 있었으니 대시보드는 청구서와 대조할 것. 다음 글은 출력 비용까지 없애는 유일한 층, 시맨틱 캐시다.

— LLM 서빙 캐싱 시리즈 ⑤ / 다음 글: 시맨틱 캐시 — 현실 히트율과 오탐의 비용

LLM 서빙 캐싱 ④ — API 프롬프트 캐싱: 가격표, TTL, 손익분기

자체 GPU가 없어도 프리픽스 캐시의 이득은 받을 수 있다. API 제공사가 서버 쪽 KV 캐시를 재사용하고 그만큼 할인해 주는 것이 프롬프트 캐싱이다. 2026년 8월 기준으로 과금 모델은 세 갈래로 정리됐고, 손익분기는 계산할 수 있으며, 청구서를 20~30% 좌우하는 실수가 실제로 일어났다. 가격은 전부 공식 페이지에서 확인한 값이다.

세 가지 과금 모델

  • 쓰기 할증형 — Anthropic·OpenAI(GPT-5.6+)·Bedrock. Anthropic은 5분 캐시 쓰기 ×1.25, 1시간 쓰기 ×2, 읽기 ×0.1. Sonnet 5는 입력 $2 / 5분 쓰기 $2.50 / 1시간 쓰기 $4 / 읽기 $0.20 / 출력 $10. 최소 캐시 길이는 모델별 512(Opus 5)·1,024(Sonnet 5)·4,096(Haiku 4.5) 토큰이며 미달이면 에러 없이 조용히 캐시되지 않는다. OpenAI는 2026-07-09 GPT-5.6부터 무료 자동 쓰기를 버리고 같은 ×1.25 / ×0.1 구조 + 명시적 브레이크포인트 + 30분 TTL로 전환했다(이전 모델은 쓰기 무료, 읽기 GPT-5.x ×0.1·4.1/o3 ×0.25, 최소 1,024~2,048).
  • 저장료형 — Gemini. 암묵 캐싱은 2.5 이상 기본 활성이고 무료지만 보장이 없다. 명시 캐싱은 토큰 0.1배에 더해 시간당 저장료(3.7 Flash $0.50, 3.1 Pro $4.50 per M토큰·시간)가 붙는다. 100K 토큰 Pro 캐시를 놀려두면 하루 $10.80이 읽기 한 번 없이 나간다.
  • 무료 디스크형 — DeepSeek. 2024년 8월 세계 최초의 디스크 KV 캐시. 64토큰 단위, 쓰기 무료, 수 시간~수 일 보존. V4-pro 미스 $1.32 / 히트 $0.044 — 히트가 미스의 3.3%다. 오프피크 50%까지 겹치면 정가의 1.7%.

국내 제공사는 Upstage만 캐시 단가를 공개했다(Solar Pro 4 $0.30 / 캐시 $0.06 / $1.20, Pro 3는 −90%). K-EXAONE은 FriendliAI에서 캐시 −80%, HyperCLOVA X는 캐시 항목이 없고 Kanana는 CBT 중이다. 자세한 건 ⑪편.

손익분기 계산기

  • 몇 번 재사용해야 남는가: 5분 캐시는 쓰기 1.25 + 읽기 0.1 = 1.35 vs 정가 2.0 — 두 번째 요청부터 32.5% 절감. 1시간 캐시는 2 + 0.1 + 0.1 = 2.2 vs 3.0 — 세 번째부터. Anthropic 문서는 "5분 캐시는 read 1회, 1시간 캐시는 read 2회면 본전"으로 쓴다.
  • 히트율 기준: 유효 단가 = H × 0.1 + (1 − H) × 1.25. 손익분기 히트율은 5분 약 22%, 1시간 약 53%. AWS의 표현은 "읽기가 토큰 흐름의 ~20%를 넘으면 순절감".
  • 90% 할인 ≠ 90% 절감: 히트율 90%, 5분 캐시면 미스 10%가 ×1.25라 절감은 78.5%다. 1시간이면 71%. 그리고 ①편에서 본 대로 출력이 캐시되지 않으니 청구서 전체로는 다시 절반쯤.
  • 할인 중첩: Anthropic Batch(50%) × 캐시 읽기 = 정가의 5%. Azure PTU는 읽기 100% 할인. Bedrock은 캐시 토큰이 ITPM 한도에 안 들어간다(1st-party OpenAI는 TPM에 산입).

TTL 하나가 청구액 20~30%를 좌우한다

Claude Code 사용자의 119,866건 로그 분석: 2026년 3월 초 클라이언트가 1시간→5분 TTL로 바뀌자 3월 청구가 25.9%, 넉 달간 $5,561 중 $949(17.1%)가 초과 지불됐다. Anthropic의 답은 "1회성 요청이 많으면 5분이 더 싸서 클라이언트가 자동 결정한다"였다. 다른 사례는 라이브러리 업데이트 후 일 $4~5→$13.86, 한 줄 수정으로 $4.52. 규칙: 요청 간격 5분 미만이면 5분, 5~60분이면 1시간, 1시간 이상이면 max_tokens 최소값으로 프리워밍하거나 포기(워밍 경제학은 ⑨편).

조용한 무효화 체크리스트

  • 프리픽스 순서는 tools → system → messages. 도구 정의 한 글자만 바꿔도 전부 무효. Anthropic은 2026년 5월 mid-conversation role: "system", 7월 도구 변경 베타로 탈출구를 열었고, OpenAI는 allowed_tools로 정의는 고정한 채 제한한다.
  • 브레이크포인트 앞의 타임스탬프·UUID, 비정렬 JSON, 이미지 detail 변경, thinking/effort 변경, 모델 스위치, web search·citations 토글.
  • 동시 요청은 전부 쓰기다 — 첫 응답이 시작된 뒤에야 읽기가 가능하니 팬아웃은 첫 요청 완료 후. OpenAI/Azure는 prompt_cache_key당 약 15 RPM을 넘으면 콜드 레플리카로 흘러 미스가 는다.
  • 고유 내용 뒤의 브레이크포인트는 순수 할증(쓰기만 발생). Anthropic 2026-02의 automatic caching은 최상위 cache_control 하나로 마지막 캐시 가능 블록을 자동 추적하고, 5월의 cache_miss_reason 진단 베타가 이유를 알려준다.

측정 필드는 Anthropic cache_read_input_tokens·cache_creation_input_tokens, OpenAI usage.prompt_tokens_details.cached_tokens, Gemini total_cached_tokens. 이 값을 스트림별로 로그에 남기지 않으면 절감은 증명되지 않는다. 다음 글은 에이전트와 RAG에서 이 캐시를 실제로 살리는 배치 규칙이다.

— LLM 서빙 캐싱 시리즈 ④ / 다음 글: 에이전트·멀티턴·RAG — 앱 계층의 캐시 다섯 층

LLM 서빙 캐싱 ③ — 프리픽스 캐싱: 히트율은 엔진이 아니라 프롬프트 배치가 결정한다

같은 시스템 프롬프트를 매 요청마다 다시 계산하고 있다면 GPU는 하루 종일 같은 숙제를 반복하는 셈이다. 프리픽스 캐싱은 앞부분이 같은 요청의 KV를 재사용해 prefill을 건너뛴다. 2026년 현재 vLLM·SGLang·TensorRT-LLM·llama.cpp 네 엔진 모두 기본 활성이라, 질문은 "켜까"가 아니라 "왜 우리 히트율은 낮은가"다. 이 글은 엔진의 메커니즘, 히트율을 결정하는 프롬프트 배치, 그리고 레플리카가 둘 이상일 때 캐시를 깨는 로드밸런서 문제를 다룬다.

네 엔진의 메커니즘 — 히트의 단위가 다르다

  • vLLM Automatic Prefix Caching — 16토큰 블록마다 (부모 블록 해시, 토큰 ID, LoRA ID·멀티모달 해시·cache_salt)로 체인 해시를 만든다. 완전히 찬 블록만 캐시되므로 50토큰 프리픽스는 48토큰만 인정된다. LRU 축출, V1에서 기본 활성(--no-enable-prefix-caching으로 끔). 해시 알고리즘이 프로파일에 보이면 --prefix-caching-hash-algo xxhash.
  • SGLang RadixAttention — 프롬프트와 생성 결과를 radix tree로 들고 페이지 크기 1토큰이라 짧은 프롬프트에서 손해가 없다. 대기열을 "가장 긴 매칭 프리픽스" 순으로 정렬하는 캐시 인지 스케줄링이 핵심이며, LMSYS 벤치에서 히트율 50~99%, 처리량 최대 5배. 축출 정책은 --radix-eviction-policy로 lru/lfu/priority 선택.
  • TensorRT-LLM KV cache reuseenable_block_reuse 기본 활성, 부분 블록 재사용, 0~100 우선순위 LRU(시스템 프롬프트 고정 가능, 히트율 ~20% 상승), host_cache_size로 축출 전 CPU 오프로드.
  • llama.cpp — 슬롯 단위 cache_prompt. 슬롯보다 대화가 많으면 축출되고 --slot-save-path로 디스크 저장. 단일 서버·엣지 계층용.

단일 인스턴스 이득은 크지만 prefill/TTFT에만 걸린다. llm-d의 측정에서 Qwen3-32B 10K 토큰 프롬프트 TTFT는 4.3초→0.6초, 디코드는 그대로다. 국내 SqueezeBits 비교(Llama-3.1-8B, 공유 프리픽스 25%, 출력 1K)에서 처리량은 TRT-LLM +34.7%, vLLM 0.6.3 +13.3%였고, 공유 프리픽스가 전혀 없을 때 당시 vLLM은 −36.7%였다(V1에서 개선). 캐시는 "거의 공짜"지만 워크로드가 맞아야 한다.

히트율은 엔진이 아니라 프롬프트 배치가 결정한다 — 0.3% → 87%

Qwen2.5-32B를 H100 4노드에서 서빙한 사례가 교과서적이다. 1,847토큰 고정 시스템 프롬프트를 쓴 에이전트는 히트율 94%, TTFT 480→110ms, prefill 연산 −38%. 그런데 한 테넌트가 프롬프트 앞 200토큰에 타임스탬프·세션 UUID·도구 출력 해시를 넣자 히트율 0.3%로 떨어졌다 — 47번째 토큰에서 갈라지니 그 뒤 블록 전부가 미스다. 가변 필드를 끝으로 옮기자 87%, TTFT 510→145ms. "Don't Break the Cache"(에이전트 세션 500+건)도 같은 규칙으로 비용 −41~80%를 얻었다. 캐시를 조용히 깨는 것들:

  • 요청마다 바뀌는 헤더 — Claude Code가 llama.cpp에 붙인 귀속 헤더 하나가 매 턴 수만 토큰을 재처리시켰다.
  • JSON 키 순서 비결정성, 사용자별 도구 목록, 앞부분 컨텍스트 재정렬(뒤 전부 무효).
  • 토크나이저·챗 템플릿 버전 변경(캐시의 정체성은 토큰 ID), 마지막 부분 블록, LoRA 전환, 이미지 해시 없는 멀티모달.
  • 멀티테넌트에서 cache_salt 없이 공유하면 히트/미스 타이밍으로 다른 테넌트의 프리픽스를 추측하는 사이드채널(PrefixWall)이 생긴다. 공개 시스템 프롬프트만 공유하고 고객 데이터는 salt — 선택적 격리가 전면 격리보다 재사용을 70% 더 남긴다.

레플리카가 2대 이상이면 로드밸런서가 캐시를 깬다

  • 1단계 세션 스티키: vLLM Router의 consistent hashing. 챗봇이면 이것으로 충분한 경우가 많다.
  • 2단계 프리픽스 해시 라우팅: SGLang 라우터는 워커별 근사 radix tree로 매칭률 기준 라우팅. Llama-3.1-8B 8×A100에서 히트율 20%→75%, 처리량 82.7K→158.6K tok/s.
  • 3단계 KV 이벤트 기반: llm-d의 정밀 스케줄링은 16×H100·150테넌트에서 P90 TTFT 0.54초 vs 랜덤 92.6초(170배), 처리량 2배. Baseten의 Dynamo KV 라우터는 50K 토큰 코딩 트래픽에서 히트율 89%, TTFT −50%, RPS +61%. GKE Inference Gateway는 평균 TTFT 2,625→188ms.

작은 클러스터의 현실적 기대치는 처리량이 아니라 꼬리 지연이다 — 4레플리카 멀티턴에서 히트율 62→90%, P95 TTFT 727→237ms, 처리량은 그대로였다. 프롬프트가 전부 고유하거나 200토큰 미만이면 라우팅 투자는 건너뛴다. 이번 주에 할 일: 프롬프트를 고정→few-shot→도구→사용자 데이터 순으로 정렬하고, vllm:prefix_cache_hits / vllm:prefix_cache_queries를 대시보드에 올리고, 세션 스티키부터 켠다. GPU 캐시 용량이 히트율을 막는 순간(HiCache 40→80%)의 이야기는 ⑦편에서.

— LLM 서빙 캐싱 시리즈 ③ / 다음 글: API 프롬프트 캐싱 — 가격표, TTL, 손익분기

LLM 서빙 캐싱 ② — KV 캐시와 메모리 경제학: GPU 한 장에 몇 명을 태우나

자체 서빙에서 GPU 메모리는 두 덩어리로 쓰인다. 모델 가중치와 KV 캐시. 가중치는 상수다 — 모델을 고르는 순간 정해진다. KV 캐시는 변수다 — 동시에 처리하는 토큰 수에 비례해 늘어나고, 이것이 배치 크기를, 배치 크기가 처리량을, 처리량이 토큰당 비용을 결정한다. 그래서 캐싱 시리즈의 두 번째 글은 캐시를 "재사용"하기 전에 캐시가 왜 비용의 변수인지부터 짚는다.

한 줄 공식과 우리 모델의 숫자

토큰 하나의 KV 캐시 크기는 2 × 레이어 수 × KV 헤드 수 × 헤드 차원 × 바이트다(bf16이면 2바이트). Raschka의 아키텍처 갤러리DeepSeek-V3 ISCA'25 논문의 표를 합치면 토큰당 bf16 기준으로 Llama-3.1-8B 128KiB, Qwen3-8B 144KiB, Qwen3-32B 256KiB, Llama-3-70B·Qwen2.5-72B 320KiB, Llama-3.1-405B 504KiB, 그리고 MLA를 쓰는 DeepSeek-V3는 68.6KiB다. 70B 모델에 128K 컨텍스트 요청 하나가 들어오면 KV만 40GiB — H100 한 장의 절반이다. vLLM 논문의 13B/A100-40GB 예시는 가중치 65%, KV 30%였고, 4비트로 양자화한 70B의 가중치(32.6GiB)가 4K 요청 32개의 KV(40GiB)보다 작다는 국내 계산 사례도 있다. 청구서의 단위는 요청 수가 아니라 동시 토큰 수다 — 500토큰 100건과 10,000토큰 5건은 같은 값이다.

아키텍처가 4~30배를 좌우한다

  • MHA → GQA: GQA 논문대로 64개 Q 헤드에 KV 헤드 8개면 8배 절감. Llama-2-7B 512KiB → Llama-3-8B 128KiB가 이 차이다.
  • GQA → MLA: DeepSeek-V2는 512차원 잠재 벡터만 캐시해 KV −93.3%, 최대 처리량 5.76배. 72B GQA 모델(327KB) 대비 4.7배 작다.
  • 하이브리드·슬라이딩 윈도우: Qwen3-30B-A3B 96KB, Qwen3.5-35B-A3B 20KB, Nemotron-3-Nano 6KB/토큰. LG의 K-EXAONE 리포트는 48개 레이어 중 36개를 슬라이딩 윈도우로 두고 창을 4,096→128 토큰으로 줄인 이유를 "KV 캐시 사용량 최소화"라고 명시했다.

같은 품질 구간이라면 모델 선택 자체가 가장 큰 캐시 최적화다. 토큰당 KV가 4배 작으면 같은 GPU에 4배 많은 요청을 태운다.

PagedAttention — 낭비 60~80%를 0으로, 대신 커널은 느려진다

vLLM 이전 시스템은 요청마다 최대 길이만큼 연속 메모리를 예약해 실제 토큰 상태는 20.4~38.2%만 채� 다. PagedAttention은 16토큰 블록을 필요할 때 할당해 낭비를 없앴고 처리량이 2~4배(FasterTransformer 대비 최대 22배) 올랐다. 공짜는 아니다. vAttention(MS Research)은 페이지드 커널이 연속 메모리 커널보다 20~26% 느리다고 반박했다. SGLang은 페이지 크기 1토큰, TensorRT-LLM은 블록 단위(기본 128)로 서로 다른 지점에 선다. 블록 크기는 다음 편의 프리픽스 캐시 히트 단위이기도 하다.

KV 풀 → 배치 → tok/s → $/1M 토큰

  • 동시성 상한: Llama-3.1-8B를 H100에 gpu-memory-utilization 0.9로 올리면 KV 풀 약 56GB ≈ 458K 토큰 ≈ 8K 요청 56개, 128K 요청은 3.5개. 70B bf16을 H100 2장에 올리면 KV에 4GB(~12K 토큰)밖에 안 남아 FP8 가중치나 4장, 아니면 H200이 필요하다.
  • 배치가 비용 손잡이: 국내 스타트업 SqueezeBits의 벤치에서 Llama-3-8B/A100의 디코드 처리량은 배치 4→512에서 30~40배 늘었다. DeepMind 스케일링 북은 70B가 compute-bound가 되는 지점을 배치 ~240으로 본다.
  • 비용 환산: $/1M 토큰 = ($/시간 ÷ (tok/s × 3,600)) × 10⁶. H100 $2.90/시간이면 100 tok/s는 $8.06/M, 1,000 tok/s는 $0.81/M, 3,000 tok/s는 $0.27/M. TRT-LLM 튜닝 가이드의 4×H100 Llama-3.3-70B는 설정만으로 1,564→2,474 tok/s(+58%), 즉 토큰당 비용 −37%였다.
  • FP8 KV는 조건부 공짜: vLLM의 2026년 재측정에서 --kv-cache-dtype fp8은 바이트를 절반으로 줄이고 정확도 94~100% 회복이지만, 이득은 약 7K 토큰 이상에서만 나고 슬라이딩 윈도우 레이어에서는 0%다. 2024년 vLLM은 FP8 커널이 없어 이득이 ~0%였고 TRT-LLM만 +45%였다는 기록도 기억할 것.

실전 값은 vLLM gpu-memory-utilization 0.90, max-model-len은 실제 필요치로, max-num-batched-tokens는 지연 우선이면 2,048·처리량 우선이면 8,192 이상, 로그에 preemption이 보이면 풀이 모자란 것. 벤더 숫자는 다시 계산하자 — 한 2026년 블로그는 "$2.50/시간에 95 tok/s = $0.73/M"이라 썸지만 맞는 값은 $7.31/M이다. 다음 글은 이 KV를 요청 간에 재사용하는 프리픽스 캐싱이다.

— LLM 서빙 캐싱 시리즈 ② / 다음 글: 프리픽스 캐싱 — 엔진, 프롬프트 배치, 캐시 인지 라우팅

RAG 종류 총정리 ⑬ (완결) — 한국어 조건과 결정 트리

열두 편을 한 장으로 접는다. 먼저 한국어로 서비스할 때만 적용되는 조건을 모으고, 그다음 "우리는 무엇부터 하나"를 결정 트리로 정리한다. 한국어 RAG의 다섯 가지 조건 임베딩 기본값을 의심하되, 갈아타는 이득은 제한적이...