RAG가 더 이상 항상 정답은 아닙니다: 2026년 AI 에이전트가 코드를 검색하는 방법
요약
기존의 벡터 기반 RAG 방식이 코드베이스 검색에는 한계가 있음을 지적하며, 에이전트가 개발자처럼 파일 탐색, grep, 심볼 검색 등을 수행하는 '에이전트 방식의 검색(agentic retrieval)'으로의 패러다임 변화를 설명합니다.
핵심 포인트
- 코드 검색은 단순한 의미론적 유사성보다 구조적 맥락이 중요함
- 전형적인 RAG는 비정형 데이터에는 강하나 코드의 구조를 놓칠 수 있음
- 현대적 에이전트는 정적 청크 대신 동적인 도구(grep, glob 등)를 활용함
- 에이전트 방식의 검색은 모델이 스스로 더 나은 증거를 요청하는 루프를 가짐
RAG가 더 이상 항상 정답은 아닙니다: 2026년 AI 에이전트가 코드를 검색하는 방법
지난 몇 년 동안 "RAG를 추가하라"는 말은 거의 모든 AI 제품 질문에 대한 기본 답변이 되었습니다.
모델이 문서를 이해해야 하나요? RAG를 추가하세요.
레포지토리(repo)에 대한 질문에 답해야 하나요? RAG를 추가하세요.
환각 (hallucination) 현상을 멈추고 싶나요? RAG를 추가하고 약간의 기도를 더하세요.
RAG는 여전히 유용합니다. 저는 RAG를 매장하러 온 것이 아닙니다. 하지만 코드베이스 (codebases)의 경우, 기본 설정이 바뀌고 있습니다. 현대적인 AI 코딩 에이전트 (AI coding agents)는 적절한 컨텍스트 (context)를 찾기 위해 항상 벡터 데이터베이스 (vector database)를 필요로 하지는 않습니다. 많은 경우, 그들은 숙련된 개발자가 매일 사용하는 것과 동일한 것들을 필요로 합니다: 파일 이름, grep, 심볼 (symbols), 임포트 (imports), 테스트 (tests), 그리고 정확한 소스 읽기 (exact source reads).
이러한 변화는 중요합니다. 왜냐하면 코드는 단순한 텍스트가 아니기 때문입니다. 코드는 이름, 경로, 참조 (references), 호출 그래프 (call graphs), 패키지 경계 (package boundaries), 테스트, 설정 파일 (config files), 그리고 에러 문자열 (error strings)을 가지고 있습니다. 코드를 의미론적으로 유사한 문단들의 더미처럼 취급하는 것도 작동할 수 있지만, 코드를 이해 가능하게 만드는 구조를 잃을 수도 있습니다.
오래된 RAG 반사 작용
전형적인 RAG는 보통 다음과 같은 형태를 띱니다:
Repository
-> 파일을 청크 (chunks)로 분할
-> 각 청크에 대한 임베딩 (embeddings) 생성
...
이러한 흐름은 지원 문서, PDF, 내부 위키 페이지, 연구 노트, 정책, 전사 데이터 (transcripts)와 같은 많은 종류의 비정형 지식에 대해 견고합니다. 사용자가 개념적인 질문을 하고 그 답이 많은 산문 속에 숨겨져 있을 수 있다면, 의미론적 검색 (semantic search)이 도움이 됩니다.
하지만 코드 검색 (code retrieval)은 다른 압박 지점들을 가지고 있습니다.
만약 제가 에이전트에게 "쿠폰이 만료되었을 때 왜 결제 (checkout)가 실패하나요?"라고 묻는다면, 저는 단순히 "checkout" 및 "coupon"과 의미론적으로 가까운 것만을 필요로 하는 것이 아닙니다. 저는 다음과 같은 것들이 필요할 수 있습니다:
- 결제를 처리하는 라우트 (route)
- UI에서 발생하는 정확한 에러 문자열 (error string)
- 쿠폰 검증 함수 (coupon validation function)
- 만료된 쿠폰을 설명하는 테스트 (test)
- 프로덕션 환경에서 동작을 변경하는 피처 플래그 (feature flag)
- Nullable 컬럼을 추가한 마이그레이션 (migration)
벡터 검색 (vector search)은 그중 일부를 찾아낼 수도 있습니다. 하지만 훌륭한 코딩 에이전트는 보통 개발자처럼 검색할 것입니다.
에이전트가 현재 실제로 코드를 검색하는 방법
실제적인 코드 검색 루프(code-search loop)는 대개 다음과 같은 모습에 더 가깝습니다:
사용자가 버그에 대해 질문함
-> 유력한 파일들을 glob으로 탐색
-> 정확한 이름, 문자열, 라우트(routes), 에러, 플래그 등을 grep으로 검색
...
이것은 RAG에 반대되는 개념이 아닙니다. 이것은 에이전트 방식의 검색 (agentic retrieval)입니다. 모델은 시작할 때 하나의 정적인 청크(chunk) 묶음을 받는 것이 아닙니다. 모델은 더 많은 것을 학습함에 따라 더 나은 증거를 계속해서 요청합니다.
예시:
rg "expired coupon|coupon expired|CouponExpired" .
rg "validateCoupon|applyCoupon|coupon" src tests
rg "checkout" src/routes src/app tests
그다음 에이전트는 코드 조각(snippets)을 보고 추측하는 대신 실제 파일을 읽습니다:
src/services/coupons.ts 읽기
src/routes/checkout.ts 읽기
tests/checkout/coupon-expiry.test.ts 읽기
이것은 지루합니다. 하지만 그것이 핵심입니다. 정답이 정확한 심볼(symbols)에 달려 있을 때, 지루한 검색이 영리한 검색보다 더 나은 경우가 많습니다.
왜 grep이 코드에서 임베딩 (embeddings)을 이길 수 있는가
단어가 모호할 때는 임베딩 (embeddings)이 훌륭합니다. 하지만 코드는 종종 모호하지 않습니다.
만약 버그가 STRIPE_WEBHOOK_SECRET을 언급한다면, 에이전트는 해당 정확한 문자열을 검색해야 합니다. 스택 트레이스 (stack trace)에 calculateFinalPrice가 나타난다면, 에이전트는 해당 함수로 바로 이동해야 합니다. 실패하는 테스트가 should_reject_expired_coupon이라면, 에이전트는 그 테스트를 읽어야 합니다.
의미론적 유사성 (Semantic similarity)은 다음과 같은 더 부드러운 질문에 답하려고 하기 때문에 이러한 것들을 놓칠 수 있습니다: "어떤 청크 (chunk)가 이 쿼리와 개념적으로 가까운가?"
코드 검색은 종종 더 어렵고 문자 그대로의 질문을 던집니다: "이 심볼 (symbol)이 어디에서 정의되고, 사용되고, 변경되고, 모킹 (mocked)되거나 테스트되는가?"
이것이 grep, glob, 파일 읽기, 그리고 언어 서버 (language-server) 탐색과 같은 도구들이 매우 유용한 이유입니다. 이 도구들은 증거를 보존합니다. 경로와 줄 번호를 제공합니다. 에이전트가 자신이 찾은 것을 검증할 수 있게 해줍니다.
청킹 (chunking) 문제
청킹 (chunking)은 코드용 RAG에서 가장 이상한 부분 중 하나입니다.
하나의 함수가 한 청크에서 시작하여 다른 청크에서 끝날 수 있습니다. 클래스가 잘려 나간 임포트 (imports)에 의존할 수도 있습니다. 라우트 핸들러 (route handler)는 그 위의 미들웨어 (middleware)를 읽기 전까지는 무해해 보일 수 있습니다. 테스트는 80줄 전에 정의된 피스처 (fixture)가 있어야만 의미가 있을 수도 있습니다.
청크 (chunk)가 구조를 깨뜨릴 때, 검색 (retrieval)은 기술적으로는 관련이 있지만 실질적으로는 불완전한 컨텍스트 (context)를 반환할 수 있습니다.
이것이 바로 저장소 수준의 코드 검색 (repository-level code retrieval) 연구가 더 구조 인식적인 (structure-aware) 방법론으로 이동하고 있는 이유입니다. 어떤 접근 방식은 어휘 검색 (lexical search)과 후처리 (post-processing)를 결합합니다. 다른 방식은 의존성 인식 검색 (dependency-aware retrieval)이나 저장소 그래프 (repository graphs)를 사용합니다. 공통된 주제는 간단합니다: 코드는 단순한 유사성 (similarity)이 아니라 구조 (structure)가 필요하다는 것입니다.
긴 컨텍스트 (Long context)가 트레이드오프 (tradeoff)도 변화시켰습니다
RAG 본능이 약해지고 있는 또 다른 이유는 컨텍스트 창 (context window)이 커졌기 때문입니다.
만약 저장소의 유용한 부분이 컨텍스트 안에 들어갈 수 있다면, 가장 좋은 검색 시스템은 '검색 시스템이 없는 것'일 수도 있습니다. 그냥 파일을 읽으면 됩니다. 에이전트 (agent)가 관련 소스 코드를 직접 검사할 수 있다면, 벡터 데이터베이스 (vector database)는 가치보다 더 많은 가동 부품 (moving parts)을 추가할 뿐일 수 있습니다.
이것이 "저장소 전체를 프롬프트 (prompt)에 집어넣으라"는 뜻은 아닙니다. 그것은 게으르고 비용이 많이 드는 방식입니다. 하지만 이는 에이전트가 다른 전략을 사용할 수 있음을 의미합니다:
좁게 검색하기 -> 완전한 파일 읽기 -> 중요한 것만 유지하기 -> 계속하기
이것은 개발자들이 일하는 방식에 더 가깝습니다. 우리는 디버깅 (debugging)을 하기 전에 저장소를 우리 뇌에 임베딩 (embed)하지 않습니다. 우리는 검색하고, 파일을 열고, 단서를 따라가며, 진행하면서 정신적 모델 (mental model)을 구축합니다.
RAG가 여전히 유효한 경우
RAG는 죽지 않았습니다. 단지 모든 코드 문제에 대해 자동으로 선택되는 첫 번째 수단이 아닐 뿐입니다.
다음과 같은 경우에는 벡터 RAG (vector RAG)를 사용하십시오:
- 코퍼스 (corpus)가 대부분 비정형 산문 (unstructured prose)인 경우
- 사용자가 다양한 표현 방식으로 개념적인 질문을 던지는 경우
- 문서, 티켓 (ticket), 댓글 또는 설계 노트 전반에 걸쳐 의미론적 회상 (semantic recall)이 필요한 경우
- 소스 콘텐츠가 인덱싱 (indexing)을 관리할 수 있을 정도로 충분히 천천히 변경되는 경우
- 정확한 이름을 모르거나 신뢰할 수 없는 경우
코드 에이전트 (code agents)의 경우, RAG는 여전히 다음 사항에 도움이 될 수 있습니다:
- 아키텍처 결정 기록 (architecture decision records)
- 긴 제품 사양서 (product specs)
- 오래된 이슈 (issue) 논의
- 설계 문서 (design docs)
- 버그와 연결된 지원 티켓 (support tickets)
- 코드 주변의 자연어 설명 (natural-language explanations)
더 나은 패턴은 대개 하이브리드 (hybrid) 방식입니다. 소스 코드 (source code) 처리는 어휘 검색 (lexical search)과 심볼 탐색 (symbol navigation)에 맡기세요. 지저분한 인간의 텍스트는 의미론적 검색 (semantic retrieval)이 처리하게 하세요. 그리고 에이전트 (agent)가 질문에 어떤 도구가 적합할지 결정하게 하세요.
더 나은 사고 모델 (mental model)
"RAG를 사용해야 할까?"라고 묻는 대신, 다음과 같이 질문하세요:
에이전트가 어떤 종류의 증거 (evidence)를 필요로 하는가?
만약 정답이 정확한 증거라면, 정확한 도구들을 사용하세요:
파일 경로 (file paths)
심볼 (symbols)
임포트 (imports)
...
만약 정답이 의미론적 증거라면, 의미론적 도구들을 사용하세요:
docs
notes
tickets
...
만약 두 가지 모두가 필요하다면, 이들을 결합하세요.
프로덕션 환경에 적합한 코드 에이전트 (code agent)는 벡터 데이터베이스 (vector database)가 부착된 챗봇 (chatbot)이어서는 안 됩니다. 그보다는 터미널 (terminal), 에디터 (editor), 검색 도구 (search tools), 테스트 러너 (test runner), 그리고 증거가 부족할 때를 판단할 수 있는 충분한 판단력을 갖춘 주니어 개발자 (junior developer)에 더 가까워야 합니다.
이것이 개발자에게 의미하는 바
만약 여러분이 2026년에 AI 코딩 도구를 구축하고 있다면, 임베딩 (embeddings)을 연결하는 것부터 시작하지 마세요. 지루한 도구들부터 시작하세요:
- 가능성 있는 파일을 찾기 위한
glob - 정확한 검색을 위한
grep또는ripgrep - 라인 범위를 지정한 파일 읽기 (file reads)
- 언어 서버 (language-server) 심볼 조회 (symbol lookup)
- 테스트 발견 및 실행 (test discovery and execution)
- 시간에 따라 동작이 변했을 때의 git 히스토리 (git history)
그런 다음, 의미론적 검색 (semantic search)이 제 역할을 할 수 있는 곳에 추가하세요.
마지막 부분이 중요합니다. RAG는 인프라 (infrastructure)입니다. 모든 인덱스 (index)에는 청킹 (chunking), 동기화 (syncing), 무효화 (invalidation), 권한 (permissions), 랭킹 (ranking), 평가 (evaluation), 그리고 디버깅 (debugging)이 필요합니다. 만약 grep과 파일 읽기만으로 문제가 해결된다면, 그것은 원시적인 것이 아닙니다. 그것은 훌륭한 엔지니어링 (engineering)입니다.
마지막 생각
RAG는 과거에 LLM을 비공개 데이터 (private data) 상에서 유용하게 만들어 주는 마법 같은 계층 (magic layer)처럼 느껴졌습니다. 많은 유스케이스 (use cases)에서 여전히 그러합니다.
하지만 코드베이스 (codebases)는 단순한 비공개 데이터가 아닙니다. 그것들은 구조를 가진 실행 가능한 시스템 (executable systems)입니다. 최고의 AI 에이전트들은 코드베이스를 그런 방식으로 다루기 시작하고 있습니다.
따라서 아니요, RAG가 항상 정답인 시대는 지났습니다.
때때로 정답은 다음과 같습니다:
rg "the thing that broke"
그리고 솔직히 말해서, 이것이 매우 개발자스러운 (developer-coded) 방식이라고 느껴집니다.
참고 문헌 (References)
참고 문헌 (References)
- Anthropic, "Building agents with the Claude Agent SDK" — https://www.anthropic.com/engineering/building-agents-with-the-claude-agent-sdk
- Anthropic, "How we built our multi-agent research system" — https://www.anthropic.com/engineering/multi-agent-research-system
- LlamaIndex documentation, "Welcome to LlamaIndex" — https://developers.llamaindex.ai/python/framework/
- LlamaIndex documentation, "Multi-agent patterns in LlamaIndex" — https://developers.llamaindex.ai/python/framework/understanding/agent/multi_agent/
- arXiv, "GrepRAG" paper on lightweight lexical retrieval for repository-level code completion — https://arxiv.org/pdf/2601.23254
- arXiv, "Do Not Treat Code as Natural Language" / Hydra repository-level code generation — https://arxiv.org/pdf/2602.11671
- arXiv, "LARGER: Lexically Anchored Repository Graph Exploration and Retrieval" — https://arxiv.org/html/2605.16352
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기