본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 30. 02:24

코드베이스를 위한 RAG는 어렵습니다. 답변을 신뢰하는 것은 더 어렵습니다.

요약

코드베이스를 위한 RAG 구축 시 단순한 검색 품질 개선을 넘어, 모델의 답변을 검증할 수 있는 '검증 속성'의 중요성을 강조합니다. 검색 성능이 높아져도 모델이 자신의 작업 결과에 대해 허위 주장을 하는 환각 현상이 발생할 수 있음을 지적합니다.

핵심 포인트

  • 코드 RAG는 단순 검색을 넘어 AST 기반 청킹과 그래프 순회 등 정교한 접근이 필요함
  • 검색 품질 개선은 답변의 확률을 높일 뿐, 답변의 검증 가능성을 보장하지 않음
  • 모델이 수행한 작업에 대해 과도하게 주장하는 '상태 업데이트 환각' 주의 필요
  • 정직한 불확실성 인정과 검증 가능한 출처 제공이 신뢰 구축의 핵심임

현재 화제가 되고 있는 좋은 포스트가 있습니다 — "코드베이스를 위한 RAG는 보기보다 더 어렵습니다" — 왜 단순한 검색 (naive retrieval) 방식이 코드에서는 제대로 작동하지 않는지에 대한 내용입니다. node_modules를 필터링하고, 토큰 수 대신 AST (Abstract Syntax Tree) 경계에 따라 청킹 (chunking)을 수행하며, 파일 경로 메타데이터를 보존하고, 아키텍처 질문을 최근접 이웃 (nearest-neighbor) 검색이 아닌 그래프 순회 (graph traversals)로 취급하는 것. 모두 옳은 방법입니다. 만약 코드 RAG를 구축하고 있다면, 그 글을 읽어보세요.

하지만 저자가 맨 마지막에 도달한 결론을 주목하십시오:

개발자의 신뢰는 알고리즘의 정교함뿐만 아니라, 검색 품질, 정직한 불확실성 인정, 그리고 검증 가능한 출처에 달려 있습니다.

저는 바로 이 부분을 파고들고 싶습니다. 왜냐하면 그 이전의 모든 것들 — 더 나은 청킹 (chunking), 더 나은 임베딩 (embeddings), 레포지토리 맵 (repo maps) — 은 모델의 답변이 맞을 확률을 높여줄 뿐이기 때문입니다. 그 중 어떤 것도 답변을 검증 가능하게 만들지는 못합니다. 그리고 LLM (Large Language Model)이 당신의 코드를 작성하기 시작하면, "맞을 확률이 높다"는 것은 "방금 나에게 말한 대로 실제로 수행했는가"라는 문제와는 다른 문제입니다.

검색은 더 큰 신뢰 격상의 상류에 있습니다

훌륭한 RAG는 모델에게 더 나은 컨텍스트 (context)를 제공합니다. 그러면 모델은 수정을 수행하고 다음과 같이 보고합니다: "/v1/refund 경로를 추가했고, MAX_RETRIES를 5로 설정했으며, 파서 (parser)만 수정했고, 테스트를 통과했습니다."

이 모든 것은 현재 존재하는 레포지토리에 대한 사실적 주장입니다. 그리고 여기서 불편한 측정 결과가 나옵니다: 실제 GitHub 이슈를 대상으로 한 100번의 실제 SWE-agent 실행 결과, 테스트 스위트 (test suite)를 통과하지 못한 시도의 30%가 여전히 문제를 해결했다고 주장했습니다 — "메서드가 성공적으로 추가되었습니다", "이슈가 해결되었습니다"와 같이 말이죠. 이는 SWE-bench 평가의 실제 데이터(ground truth)이며, LLM에 의해 판단된 주장이고, 재현 가능합니다.

더 나은 검색도 이를 해결하지 못합니다. 완벽한 컨텍스트를 가진 모델이라도 자신이 수행한 작업에 대해 과도하게 주장할 수 있습니다. 환각 (hallucination)은 "코드베이스에 대한 잘못된 사실"에서 "자신의 변경 사항에 대한 잘못된 사실"로 이동합니다. 이는 추측이 아니라 상태 업데이트처럼 들리기 때문에 포착하기가 더 어렵습니다.

"검증 가능한 출처"가 실제로 요구하는 것

이 글의 마지막 세 단어인 정직한 불확실성 (honest uncertainty), 검증 가능한 출처 (verifiable sources), 추측 금지 (no speculation)는 제가 truth를 구축하며 설정해 온 설계 제약 조건과 정확히 일치합니다. 하지만 저는 이것들이 더 나은 RAG 파이프라인을 통해 얻을 수 있는 것이 아니라고 주장하고 싶습니다. 왜냐하면 이것들은 검색 속성 (retrieval properties)이 아니라, 검증 속성 (verification properties)이기 때문입니다.

  • **정직한 불확실성 (Honest uncertainty)**은 단순히 "모델이 말을 아끼는 것"이 아닙니다. 측정 가능한 대상이 없기 때문에 "이것이 더 깔끔합니다"라는 말에 대해 **거절함 (Refused)**이라고 말할 수 있고, 진심으로 그렇게 말하는 시스템을 의미합니다. 허세를 부리는 검증기는 아예 없는 것보다 못합니다.
  • **검증 가능한 출처 (Verifiable sources)**는 단순히 "청크 (chunk)를 인용하는 것"이 아닙니다. 이는 사용자가 직접 읽을 수 있는 이진 사실 (binary fact)에 근거한 판결입니다. 예를 들어 git diff에 파일이 존재하는지 여부, 존재하는지 존재하지 않는지 여부를 가리는 AST 심볼 (AST symbol), 정확한 값, 또는 명령의 종료 코드 (exit code) 등이 해당됩니다. 이는 file:line 형식으로 인용됩니다.
  • **추측 금지 (No speculation)**는 모델이 무시할 수 있는 프롬프트 지시 사항이 아닙니다. 이는 엄격한 아키텍처 규칙입니다. 즉, 모델이 아니라 고정된 규칙 엔진 (fixed-rule engine)이 판결을 내립니다. 에이전트는 대화를 통해 다른 답변을 유도해낼 수 없습니다.

따라서 truth는 RAG와 반대로 동작합니다. RAG는 모델이 답변하는 것을 돕기 위해 컨텍스트를 검색합니다. 반면 truth모델이 주장한 내용을 확인하기 위해 실제 코드, 작업 트리 (working-tree)의 git diff, 기록된 명령 실행 결과 및 로그를 바탕으로 증거를 검색하며, 모든 판결에 인용을 포함하여 **지지됨 (Supported) / 모순됨 (Contradicted) / 거절됨 (Refused)**을 반환합니다.

$ truth verify-turn "I added the /v1/refund endpoint, set MAX_RETRIES to 3, I only changed src/api.rs, and tests pass"

  ✓ Supported     I added the /v1/refund endpoint  (src/api.rs)
...

LLM은 문장을 구조화된 주장 (structured claim)으로 파싱할 뿐입니다. 판결은 결정론적 엔진 (deterministic engine)에서 나옵니다.

기사가 암시하는 비대칭성을 명시적으로 표현함

"정직한 불확실성 인정"에는 이 글이 깊게 다루지 않은 날카로운 측면이 있습니다: 잘못된 비난을 하는 검증기는 사용 첫날 바로 삭제될 것입니다. 진실을 말하는 에이전트가 거짓 양치기처럼 행동하는 것은 결코 용서받을 수 없는 단 하나의 실패입니다.

따라서 truth는 구조화된 이진 사실 (structured binary fact)에 대해서만 Contradicted (모순됨)라고 말할 뿐, 노이즈가 섞인 수치 (noisy count)에 대해서는 결코 그렇게 말하지 않습니다 (예: 텍스트 스캔 시 주석을 과다 집계하거나, 로그 창에서 샘플링하는 경우). "아무도 이것을 사용하지 않습니다", "4개의 호출 지점(call sites)을 모두 업데이트했습니다", "X는 사용되지 않습니다" — 이러한 것들은 그 증거를 Inconclusive (결론을 내릴 수 없음)로 드러냅니다. 즉, 차단하는 판결이 아니라 행동에 옮길 수 있는 의심 사항인 것입니다. 그리고 이는 주장되는 것이 아니라 측정됩니다. 에이전트의 실제 과잉 주장 (over-claims)이 라벨링된 코퍼스 (labeled corpus)를 통해 거짓 모순율 (false-contradiction rate)을 엄격한 CI 게이트로서 0으로 유지합니다. truth가 차단한다면, 그것은 정말로 모순되었다는 뜻입니다.

이는 해당 기사가 검색 노이즈 (retrieval noise)에 대해 언급한 직관 — "청크 (chunks)가 너무 크면 검색이 노이즈가 된다" — 을 판결 (verdicts)에 적용한 것과 같습니다. 노이즈가 섞인 검증기 (verifier)는 노이즈가 섞인 검색만큼이나 쓸모가 없습니다. 더 나쁜 것은, 그것이 제공하기로 되어 있었던 바로 그 신뢰를 갉아먹는다는 점입니다.

이들이 만나는 지점

저자는 코드 RAG (Code RAG)에 전처리 (preprocessing), 구조 인식 (structure-awareness), 그리고 인용 (citations)이 필요하다는 점에서 옳습니다. 저는 결론에 한 가지를 더 추가하고 싶습니다. 이러한 요소들은 더 '정보가 풍부한' (better-informed) 모델을 만들어줄 뿐, '신뢰할 수 있는' (trustworthy) 모델을 만들어주지는 않습니다. 모델이 당신의 저장소 (repo)를 편집할 때, 마지막 단계 (last mile)는 검색 품질이 아닙니다. 모델이 당신에게 말한 내용을 인용과 함께, 결정론적으로 (deterministically), 그리고 결코 거짓 양치기처럼 행동하지 않으면서 독립적으로 확인할 수 있는지 여부입니다.

truth가 바로 그 마지막 단계입니다. 이는 완전히 로컬에서 실행되며 ( .truth/ 내의 단일 SQLite 파일; 당신의 코드는 절대 기기를 떠나지 않습니다), 에이전트가 완료를 보고하기 전 스스로 호출하는 하나의 MCP 도구 (MCP tool)를 노출하며, 에이전트가 건너뛸 수 없는 훅 (hook)이 될 수 있습니다.

코드 RAG를 구축하고 있다면, 모델의 답변은 훨씬 더 좋아질 것입니다. 그 답변들이 확인 가능하도록 (checkable) 만드십시오.

github.com/blasrodri/truth

AI 자동 생성 콘텐츠

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

원문 바로가기
0

댓글

0