Claude Code는 왜 코드 검색에 RAG를 쓰지 않는가

← 전체 목차 · 이전: 지식베이스를 왜 정기 전량 재구축하면 안 되나 · 다음: 고립된 데이터와의 작별 — 지식 그래프란 무엇인가

차원문서 문답코드 검색
목표의미가 관련된 단락을 찾으면 충분매우 정확한 것을 원한다
전형적 질문"이 부분이 무슨 이야기인가"어떤 함수가 어디 있는가, 어떤 변수가 어디서 호출되는가, 어떤 인터페이스를 누가 구현했는가
적합한 수단의미 유사(RAG)가 유용의미 유사가 오히려 전통 검색 도구만 못하다

코드 시나리오에서 RAG의 세 가지 급소

급소 1: 코드 구조가 잘게 부서지기 쉽다

하나의 함수는 흔히 위쪽의 타입 정의 + 아래쪽의 호출 로직 + 파일을 넘나드는 참조에 의존한다. 일단 청킹하면 모델이 보는 것은 반토막 로직일 수 있다.

급소 2: 검색 정밀도 부족

목표 조회 getUserById에 대해 벡터 유사도가 반환한 결과 순서:

순위반환된 함수유사도
1fetchUserData0.92
2queryUser0.88
3getUserById(정말 원하던 것)0.75

정확히 일치하는 것이 오히려 맨 뒤에 온다 — 식별자 검색에서 의미 유사도가 실효하는 지점이다.

급소 3: 인덱스 갱신 지연

코드베이스는 너무 빨리 변한다. 방금 코드를 고쳤는데 벡터 인덱스가 갱신되지 않아 모델이 읽는 것은 옛 코드다. 재구축은 느리고 증분 동기화는 복잡하다.

소결: 코드 Agent 시나리오에서 RAG는 "쓸 수 없는" 것이 아니라 — 충분히 실시간적이지 않고, 충분히 정확하지 않고, 충분히 통제 가능하지 않다.

대체 방안: 프로그래머처럼 코드를 조회한다

사람의 동작대응 도구
먼저 키워드 검색: 함수명, 클래스명, 라우트명, 에러 메시지Grep
파일 디렉터리로 단서를 찾음: Controller / Service / Hooks / ComponentsGlob
구체적 파일을 특정한 뒤 필요한 만큼 열어 읽음Read

이 "소박한" 방식이 코드에 특히 적합한 이유

  • 실시간적이다: 읽는 것이 디스크 위의 최신 코드다.
  • 정확하다: 찾으면 찾은 것이고 못 찾으면 못 찾은 것이다.
  • 설명 가능하다: 모델이 매 단계에서 왜 검색했고 무엇을 찾았는지 사용자가 다 볼 수 있다.

가장 관건적인 전환: 검색 결정권을 모델에게 넘긴다

RAG 모드코드 Agent 모드
형태일회성 검색순환
흐름질문 → 시스템이 조각 한 묶음을 리콜 → 모델이 그 조각들로 답변모델이 무엇을 검색할지 판단 → 도구가 반환 → 모델이 결과에 따라 전략 조정
실패 처리없음(리콜된 것이 전부)못 찾으면 키워드를 바꾸고, 단서를 찾으면 계속 파일을 읽고, 호출 관계를 찾으면 역추적한다
비유한 번에 도달검색하며, 보며, 추론하며, 수정하며

핵심은 "나에게 검색 시스템이 있다"가 아니라 **"모델이 스스로 코드를 조회하는 법을 배우게 한다"**이다.

탐색형 서브 Agent: 읽기 전용 서브 Agent로 컨텍스트 압축

문제: 메인 Agent가 계속 Grep / Read를 하면 중간 결과가 쌓여 컨텍스트가 금세 오염된다.

메인 Agent → 읽기 전용 서브 Agent: 작업 하달(예: "로그인 흐름을 정리하라")
읽기 전용 서브 Agent: 【독립된 컨텍스트】 안에서 반복 검색·독해·추론
읽기 전용 서브 Agent → 메인 Agent: 【압축된 핵심 결론】만 회신
효과: 메인 Agent의 컨텍스트가 순수하게 유지되고 핵심 정보만 획득 → 오염 방지

추가 수익: 여러 서브 Agent가 병렬로 서로 다른 모듈을 탐색해 전체 효율을 높일 수 있다.

왜 주로 RAG에 의존하지 않는가 — 여섯 가지 이유

  1. 코드는 모호한 의미 매칭이 아니라 정확 매칭이 필요하다
  2. 코드는 빠르게 변하고, 전통 도구는 최신 파일을 실시간으로 읽을 수 있다
  3. 인덱스 없이 빠르게 시작 — 미리 라이브러리를 구축할 필요가 없다
  4. Grep / Glob / Read의 검색 링크가 투명해 오류 추적이 쉽다
  5. 모델이 다중 라운드로 이터레이션 검색할 수 있고 일회성 리콜이 아니다
  6. 전통 도구가 프로그래머의 실제 코드 조회 방식에 더 부합한다

RAG의 대체 불가능성

적용 시나리오 4종: 저장소를 넘나드는 코드 / 프로젝트 문서 / Wiki 지식베이스 / API 설명. 여러 저장소를 가로지르거나 초대규모 코드베이스를 검색할 때는 RAG가 여전히 매우 유용하다.

결론

이 문제의 표준 답안은 "Claude Code가 RAG를 안 쓰는 것은 RAG가 안 되기 때문"이 아니라, **"코드 Agent 시나리오에서는 실시간적이고 정확하고 설명 가능한 도구 검색이, 미리 구축해 둔 벡터 검색보다 흔히 더 적합하다"**이다. 진짜 고급스러운 지점은 모델이 엔지니어처럼 다음에 무엇을 검색하고, 무엇을 읽고, 무엇을 검증할지 스스로 결정하게 하는 것이다.

핵심 통찰

  1. 검색 방식은 "조회의 정밀도 요구"가 결정해야지 기술의 유행도가 결정해서는 안 된다 — 문서 문답은 모호함을 용인하고 코드 위치 특정은 용인하지 않는다. 선택의 첫 질문은 **"내가 필요한 것이 관련성인가 정확성인가?"**여야 한다.
  2. 청킹의 대가는 구조성이 강한 코퍼스에서 증폭된다 — 코드에는 행을 넘고 파일을 넘는 강한 의존이 있어 어떤 고정 윈도우 청킹도 의미 단위를 절단한다. "위아래 의존이 강한" 모든 코퍼스(코드, 법조문, 재무제표의 대사 관계)는 RAG의 적합성을 다시 평가해야 한다.
  3. 벡터 유사도는 식별자 검색에서 체계적 편향을 갖는다fetchUserData(0.92)가 getUserById(0.75)보다 앞선다는 것은, Embedding이 잡는 것이 "의미가 닮음"인 반면 정확 식별자 매칭은 본질적으로 문자열 문제임을 보여준다. 도구의 층위를 잘못 쓴 것이다.
  4. 인덱스는 상태이고, 상태에는 일관성 비용이 있다 — 쓰기가 빈번한 코퍼스에서는 어떤 사전 구축 인덱스든 "재구축이 느리고 증분 동기화가 복잡한" 대가를 치러야 한다. 반면 Grep은 디스크를 직접 읽으므로 애초에 일관성 문제가 없다.
  5. 가장 큰 아키텍처 승급은 "도구 교체"가 아니라 "결정권 이전"이다 — RAG는 "시스템이 모델에게 무엇을 보여줄지 결정"하고, Agent는 "모델이 자기가 무엇을 볼지 결정"한다. 전자는 단일 라운드 파이프라인이고 후자는 폐루프 제어이며, 능력 상한이 완전히 다르다.
  6. 컨텍스트 오염이 긴 작업의 제1의 적이며, 격리가 압축보다 철저하다 — 메인 컨텍스트에 검색 중간 결과를 가득 채워 놓고 압축하느니, 서브 Agent가 독립된 컨텍스트에서 그 중간 과정을 태워 버리고 결론만 회신하게 하는 편이 낫다.
  7. 읽기 전용 권한이 서브 Agent 보안 경계의 자연스러운 설계다 — 조사형 서브 Agent에는 Grep/Glob/Read만 필요하며, 쓰기 권한을 주지 않으면 오수정을 피하면서 병렬 실행에도 충돌 리스크가 없다.
  8. 결론을 절대화하지 말 것 — RAG가 쓸모없다는 것이 아니라, RAG가 여전히 대체 불가능한 경계(저장소를 넘나드는 검색, 초대규모, 멀티모달 혼합 검색)를 명확히 그은 것이다. "경계"를 제시하는 편이 "입장"을 제시하는 것보다 점수가 높다.

엔지니어링 실전 Tips

  • 코드베이스에 기본적으로 벡터 라이브러리를 만들지 말 것: 중소 규모 저장소에서는 Grep + Glob의 리콜 품질과 지연이 대개 RAG보다 우수하며, Embedding 호출 비용과 벡터 DB 운영도 절약된다.
  • RAG를 쓸 것이라면 "혼합 검색"에 쓸 것: 저장소를 넘나드는 코드 + 프로젝트 문서 + Wiki + API 설명 같은 다중 출처·멀티모달 시나리오가 RAG의 가치 구간이다.
  • 꼭 코드에 RAG를 해야 한다면 문법 단위로 자를 것(함수/클래스를 최소 단위로 하고 파일 헤더의 import와 타입 정의를 함께), 고정 token 수로 자르지 말 것.
  • 정확 식별자 조회는 exact match 채널로 가야 하며 벡터 리콜은 보완만 담당해야 한다. 순수 벡터 방안은 getUserByIdfetchUserData 뒤로 보낸다.
  • 인덱스 신선도를 관측 가능 지표로: 벡터 인덱스를 고수한다면 **"인덱스가 HEAD보다 몇 커밋 뒤처져 있는지"**를 반드시 모니터링해야 하며, 그렇지 않으면 모델이 옛 코드를 근거로 방안을 낸다.
  • 메인 Agent의 컨텍스트 예산은 의사결정에 남기고 중간 검색 결과에 쓰지 말 것: "궂은일"을 서브 Agent에 외주 주는 것이 가장 직접적인 Token 절약 수단이다.
  • 서브 Agent의 반환 형식을 제약할 것(결론 + 핵심 파일 경로 + 행 번호만): 그렇지 않으면 서브 Agent가 중간 과정을 그대로 토해내 압축이 무의미해진다.
  • 검색 링크의 투명성 자체가 유지보수성이다: 오류 시 "어떤 단어를 검색했고 어떤 파일에 적중했는지"를 볼 수 있는 편이, "왜 이 chunk가 리콜되었는지"를 파헤치는 것보다 한 자릿수 쉽다.
  • 더 파고들 방향: 혼합 검색(정확 매칭 + 벡터 리콜 + 재정렬)으로 초대규모 코드베이스에서 정밀도와 커버리지를 양립시키기, AST / LSP 기반 코드 인덱스(token 청킹보다 코드 구조에 부합해 "반토막 로직" 문제를 해결), 서브 Agent의 동시 스케줄링과 결론 병합 전략(중복 제거, 결론 충돌 해소), 서브 Agent 결론의 신뢰도 표기.