
grep이 강력해지는 조건 ― Agent 시대의 검색 설계 (RAG 제3회)
요약
Agent 시대의 검색 설계에서 grep과 같은 전통적인 문자열 검색 도구의 재발견을 다룹니다. 단발성 검색인 RAG와 달리, Agent는 검색 실패 시 재시도할 수 있는 탐색 루프를 가지므로 grep의 신뢰성과 추적 가능성이 강력한 장점이 됩니다.
핵심 포인트
- Agent는 검색-읽기-재시도의 탐색 루프를 통해 검색 실패를 보완할 수 있음
- 정확한 키워드가 존재하는 태스크(로그, 설정값 등)에서는 grep이 벡터 검색보다 유리함
- grep은 검색 실패 원인을 추적하기 용이하여 디버깅에 유리함
- 검색을 단판 승부가 아닌 반복적인 과정으로 설계하는 것이 중요함
지난번에는 BM25와 벡터 검색 (Vector Search)을 비교했습니다.
BM25는 희귀한 문자열에 강합니다.
벡터 검색은 의미적 유사성에 강합니다.
RRF는 이 두 가지를 순위로서 혼합합니다.
여기까지 읽으면 자연스러운 결론은 다음과 같습니다.
'그렇다면 RAG에서는 BM25와 벡터 검색을 둘 다 넣으면 된다.'
'필요하다면 reranker (재순위화 모델)도 추가하면 된다.'
확실히 이는 많은 상황에서 정답입니다.
하지만 Agent가 검색하는 경우에는 또 다른 질문이 생겨납니다.
애초에 정말로 인덱스 (Index)가 필요한가?
더 낮은 레이어 (Low-layer)의 도구로 충분하지 않은가?
여기서 등장하는 것이 grep입니다.
grep은 새로운 기술이 아닙니다.
파일에서 문자열을 찾는 오래된 도구입니다.
하지만 Agent가 스스로 검색어를 생각하고, 실패하면 다른 검색어로 다시 찾을 수 있다면, grep은 단순한 오래된 도구가 아니게 됩니다.
Agent의 탐색 루프 (Exploration Loop)에 통합하면, grep은 상당히 신뢰할 수 있는 검색 인터페이스가 됩니다.
제3회에서는 grep과 벡터 검색을 비교합니다.
결론은 grep이 만능이라는 이야기가 아닙니다.
중요한 것은, 검색기뿐만 아니라 Agent가 어떻게 찾고, 어떻게 읽고, 어떻게 멈추는지까지 포함하여 설계하는 것입니다.
일반적인 RAG를 생각하면 검색은 일회성 처리라고 생각하기 쉽습니다.
사용자가 질문한다.
시스템이 query (쿼리)를 만든다.
검색기가 top-K를 반환한다.
그 결과를 LLM에 전달한다.
이 구조에서는 첫 번째 검색에서 놓치면 매우 힘듭니다.
필요한 문서가 top-K에 들어있지 않으면, 모델은 보지 못한 것에 대해 답변하게 됩니다.
따라서 검색기의 단발성 성능이 크게 작용합니다.
하지만 Agent의 경우는 조금 다릅니다.
Agent는 검색하고, 읽고, 부족하면 다시 검색할 수 있습니다.
첫 번째 query가 틀려도 다른 단어로 바꿀 수 있습니다.
결과가 너무 많으면 좁힐 수 있습니다.
파일명이나 주변 문맥을 보고 다음에 찾을 장소를 바꿀 수 있습니다.
즉, 검색은 단판 승부가 아니게 됩니다.
여기서 비용에 대한 생각이 바뀝니다.
한 번의 검색으로 완벽하게 적중시켜야 하는가?
아니면 저렴한 검색을 여러 번 시도하여 점점 정답에 다가가면 되는가?
Agent 시대의 grep은 후자에서 강력해집니다.
grep이 강력한 경우는 정답이 어딘가에 그대로 적혀 있는 태스크입니다.
로그 속의 에러.
대화 이력 속의 예정.
설정 파일의 키 (Key).
코드 중의 함수명.
사양서에 적힌 수치.
과거 티켓에 남아 있는 결정 사항.
이런 것들은 의미적으로 가까운 문서를 찾는 것보다 문자열을 직접 찾는 것이 더 좋을 때가 있습니다.
예를 들어, 사용자가 이전에 다음과 같이 말했다고 가정해 봅시다.
알림 메일은 매일 아침 8:30에 보내주세요.
나중에 "알림 메일은 몇 시에 보낼 예정이었지?"라고 질문을 받았을 때, 필요한 것은 고도의 의미 검색이 아닙니다.
알림, 메일, 매일 아침, 8:30과 같은 단서를 포착하면 됩니다.
grep은 이러한 종류의 증거를 포착하는 용도에 적합합니다.
게다가 동작을 추적할 수 있습니다.
어떤 단어로 찾았는지.
어느 행에 걸렸는지.
왜 찾지 못했는지.
검색 범위가 틀렸는지.
표기 불일치 (Typo/Variation)를 잡지 못한 것인지.
실패 원인을 추적하기 쉽습니다.
벡터 검색에서는 이 부분이 다소 불투명해집니다.
embedding (임베딩) 공간에서는 가까웠다.
하지만 인간이 보기에는 다르다.
chunk (청크)를 나누는 방식이 잘못되었는지, query가 잘못되었는지, embedding 모델이 맞지 않는지, reranker가 떨어뜨린 것인지.
원인을 구분하는 것만으로도 시간이 걸립니다.
따라서 정답이 원문에 있는 타입의 Agent 검색에서는 우선 grep을 baseline (기준점)으로 삼을 가치가 있습니다.
이 이야기는 단순한 감각만이 아닙니다.
PwC 연구팀이 2026년 5월에 발표한 「Is Grep All You Need? How Agent Harnesses Reshape Agentic Search」라는 실험이 있습니다.
LongMemEval에서 가져온 116문제를 사용하여, grep과 벡터 검색을 여러 Agent harness 위에서 비교한 것입니다.
여기서 말하는 LongMemEval은 긴 대화 이력에서 필요한 정보를 찾아 답변하는 벤치마크입니다.
즉, 과거 대화의 어딘가에 있는 발언이나 시간, 취향, 결정 사항을 찾아내는 태스크입니다.
이 실험에서는 5개의 모델, 4개의 harness, grep과 벡터 검색(vector search), 그리고 검색 결과를 inline으로 반환하는 경우와 file-based로 반환하는 경우를 비교하고 있습니다.
결과를 보는 핵심은 간단합니다.
검색 결과를 inline으로 Agent에게 전달하는 조건에서는, grep이 10개 조합 모두에서 벡터 검색을 상회했습니다.
예를 들어, GPT-5.4를 Codex CLI로 사용한 조건에서는 grep inline이 93.1%, vector inline이 75.9%였습니다.
Claude Opus 4.6을 Chronos harness로 사용한 조건에서는 grep inline이 93.1%, vector inline이 83.6%였습니다.
이는 상당히 명확한 결과입니다.
다만, 여기서 "grep이 벡터 검색보다 우월하다"라고 단정 짓는 것은 위험합니다.
이 실험의 태스크는 장기 대화 기억 QA(Long-term conversation memory QA)입니다. 정답이 원문에 어딘가에 있는 경우가 많습니다. 즉, grep에 적합한 태스크입니다.
논문 자체도 이 점을 한정하고 있습니다.
과학 문헌을 가로지르는 요약, 패러프레이징(paraphrasing)이 많은 조사, 이미지나 표를 포함하는 문서, 코드의 의미 검색(semantic search)에서는 결과가 달라질 가능성이 있습니다.
여기서 얻어야 할 교훈은 grep 만능론이 아닙니다.
정답이 원문에 있다면, 벡터 검색을 도입하기 전에 grep baseline을 측정하라.
이것입니다.
이 실험에서 또 하나 흥미로운 점은 harness의 차이입니다.
동일한 Claude Opus 4.6이라도, Chronos harness의 grep inline은 93.1%입니다.
Claude Code 상의 grep inline은 76.7%입니다.
동일한 모델, 동일한 검색 방식이라도 harness가 바뀌면 결과가 크게 달라집니다.
이는 Agent 검색에서 매우 중요한 포인트입니다.
harness는 단순한 그릇이 아닙니다.
system prompt를 어떻게 작성할 것인가.
검색 도구(tool)를 어떻게 설명할 것인가.
검색 결과를 몇 건 반환할 것인가.
너무 긴 결과는 어떻게 자를(truncate) 것인가.
Agent에게 몇 번까지 탐색하게 할 것인가.
언제 "이제 충분하다"라고 판단하게 할 것인가.
이러한 설계가 검색 결과의 활용 방식을 바꿉니다.
같은 grep이라도 Agent가 검색어를 제대로 생성하지 못하면 놓치게 됩니다.
같은 벡터 검색이라도 결과 제시 방식이 나쁘면 읽을 수 없습니다.
같은 모델이라도 종료 조건(termination condition)이 약하면 근거가 부족한 상태에서 답변하게 됩니다.
따라서 Agent 검색에서는 retriever만 바꾼다고 충분하지 않습니다.
검색기를 교체하기 전에 harness를 살펴봐야 합니다.
특히 살펴봐야 할 것은 다음 4가지입니다.
system prompt
tool description
result truncation
...
system prompt는 탐색의 습관을 결정합니다.
대화 이력 QA라면, "날짜, 시각, 고유명사, 짧은 구절을 우선적으로 찾아라"라고 적는 것이 좋습니다.
문헌 조사라면, "동일한 단어가 나오지 않더라도 유사한 주장이나 반대 의견을 찾아라"라고 적는 것이 좋습니다.
tool description도 효과가 있습니다.
search(query)라고만 적는 것과,
짧은 문자열이나 고유명사에 강한 검색. 표기법 차이(表記ゆれ)가 있을 경우 스스로 다른 query를 시도해야 함이라고 적는 것은 Agent의 사용 방식을 바꿉니다.
result truncation은 반환하는 양입니다.
너무 적으면 근거를 놓칩니다.
너무 많으면 Agent가 읽을 수 없게 됩니다.
termination condition은 멈추는 방식입니다.
1회 검색 후 답변할 것인가.
근거가 약하면 2회까지 다른 단어로 찾아볼 것인가.
수치나 날짜를 답변할 때는 원문을 확인한 뒤 답변할 것인가.
이 부분들은 검색기의 성능은 아닙니다.
하지만 최종 정확도에는 큰 영향을 미칩니다.
또 하나 놓치기 쉬운 것이 검색 결과의 전달 방식입니다.
검색 결과를 inline으로 반환하는 경우, Agent는 그 자리에서 결과를 읽습니다.
대화 컨텍스트(context) 안에 결과가 포함되어 즉시 답변에 사용할 수 있습니다.
file-based의 경우, 검색 결과는 파일에 기록됩니다.
Agent는 그 파일을 열어 필요한 부분을 읽고, 경우에 따라 추가로 검색을 수행합니다.
이 차이는 단순한 구현 상세가 아닙니다.
inline은 단순합니다.
다만, 결과가 크면 컨텍스트를 압박합니다.
file-based는 방대한 결과를 다룰 수 있습니다.
다만, Agent가 파일을 읽고, 돌아오고, 통합하고, 재검색하는 워크플로우를 올바르게 수행해야 합니다.
이 차이만으로도 결과는 달라집니다.
앞선 실험에서 GPT-5.4 + Codex CLI의 grep은 inline 방식에서 93.1%였습니다.
하지만 file-based 방식에서는 55.2%까지 떨어졌습니다.
같은 grep이라도 결과 전달 방식이 바뀌면 이 정도로 차이가 날 수 있습니다.
물론 file-based가 나쁘다는 뜻은 아닙니다.
거대한 코드베이스나 대량의 문서를 다룬다면, 검색 결과를 전부 inline에 넣는 것은 불가능합니다.
파일로 넘기고, Agent가 필요한 부분만 읽도록 하는 설계가 필요합니다.
다만, 그 순간 문제는 성격이 바뀝니다.
검색의 문제가 아니라, Agent의 독해 워크플로우(workflow) 문제로 나타납니다.
결과 파일을 찾아낼 수 있는가.
필요한 부분을 열 수 있는가.
여러 결과를 섞이지 않게 다룰 수 있는가.
근거를 잃지 않고 요약할 수 있는가.
부족할 때 다른 query로 되돌아갈 수 있는가.
이 부분을 평가하지 않은 채 file-based로 전환하면, 검색기가 아무리 좋아도 답은 무너집니다.
흔히 하는 판단 중에 이런 것이 있습니다.
코퍼스(Corpus)가 작으면 grep.
커지면 벡터 검색(Vector Search).
이해하기 쉽지만, 다소 거친 판단입니다.
크기만으로 결정되지 않습니다.
답이 원문에 있는가.
표기 불일치(表記ゆれ, variation in notation)가 어느 정도인가.
Agent가 좋은 검색어를 만들 수 있는가.
검색 결과의 노이즈율은 어느 정도인가.
반환된 결과를 Agent가 다 읽어낼 수 있는가.
file-based 독해 루프가 안정적인가.
이 조건들에 따라 달라집니다.
예를 들어, 거대한 로그라도 찾고자 하는 것이 에러 코드라면 grep이 강력합니다.
작은 문서 집합이라도 찾고자 하는 것이 추상적인 개념이라면 벡터 검색이 필요합니다.
즉, 판단 기준은 사이즈가 아닙니다.
답에 도달하기 위해, Agent가 어떤 탐색을 할 필요가 있는가 입니다.
Agent 검색을 만든다면, 처음에 태스크를 두 가지로 나누는 것이 좋습니다.
원문을 찾는 타입:
답이 원본 데이터 어딘가에 그대로 적혀 있음
개념을 찾는 타입:
...
원문을 찾는 타입이라면, 우선 grep only를 만듭니다.
여기서 복잡한 것을 하지는 않습니다.
검색 대상을 결정한다.
짧은 query를 여러 번 던질 수 있도록 한다.
결과에 파일명, 행 번호, 전후 문맥을 붙인다.
Agent에게 "찾지 못하면 다른 표기법으로 찾으라"고 가르친다.
이를 베이스라인(baseline)으로 삼습니다.
그다음, 벡터 검색과 비교합니다.
중요한 것은 동일한 조건에서 비교하는 것입니다.
prompt, tool description, 반환 건수, 평가 데이터를 통일합니다.
그렇게 하지 않으면 검색기의 차이인지, 하네스(harness)의 차이인지 알 수 없습니다.
다음으로, 하네스를 하나씩 바꿉니다.
prompt만 바꾼다.
tool description만 바꾼다.
반환 건수만 바꾼다.
inline과 file-based만 바꾼다.
종료 조건만 바꾼다.
한 번에 전부 바꾸지 않는다.
사소해 보이지만 매우 중요한 점입니다.
Agent 검색은 부품을 추가할수록 복잡해집니다.
복잡해진 시스템에서 정밀도가 올라가더라도, 왜 올라갔는지 모른다면 다음에 고장 났을 때 고칠 수 없습니다.
지금까지 grep에 대해 이야기했지만, 벡터 검색을 부정하는 것은 아닙니다.
벡터 검색이 필요한 상황은 분명히 있습니다.
표현이 다른 문서를 찾아낸다.
다른 언어로 된 같은 의미의 기술을 찾는다.
여러 문서에서 유사한 주장을 모은다.
아직 이름이 붙지 않은 개념에 가까운 사례를 찾는다.
이런 작업은 grep만으로는 대응하기 어렵습니다.
다만, Agent에게 검색을 맡길 때 처음부터 "벡터 검색을 넣으면 RAG가 된다"고 생각하는 것은 위험합니다.
Agent는 검색어를 바꿀 수 있습니다.
여러 번 시도할 수 있습니다.
파일을 열어 주변을 읽을 수 있습니다.
결과를 보고 다음에 찾을 방향을 바꿀 수 있습니다.
이 능력을 전제로 하면, grep은 단순한 검색기가 아니라 Agent의 탐색용 인터페이스가 됩니다.
반대로, 벡터 검색도 단순한 검색기가 아닙니다.
Agent가 추상적인 질문으로부터 후보를 넓히기 위한 도구입니다.
그러므로 경쟁 관계가 아닙니다.
grep은 원문에 있는 단서를 직접 줍는 도구입니다.
벡터 검색은 단어가 달라도 가까운 의미의 후보를 넓히는 도구입니다.
어느 쪽을 사용할지는 질문의 형태에 따라 결정됩니다.
제2회에서는 BM25, 벡터 검색 (Vector Search), RRF를 살펴보았습니다.
제3회에서는 Agent가 검색을 반복할 수 있다면, grep과 같은 저수준 (Low-level) 도구가 강력해지는 상황을 살펴보았습니다.
여기까지 오면 검색기 (Retriever)에 대한 이야기는 어느 정도 정리될 수 있습니다.
하지만 아직 부족합니다.
진정한 문제는 Agent가 "이제 충분히 조사했다"라고 어떻게 판단하느냐입니다.
첫 번째 검색으로 부족할 때, 무엇을 바꾸어 다시 찾을 것인가.
여러 정보원이 있을 때, 어떤 순서로 볼 것인가.
모순되는 문서가 나왔을 때, 어디서 멈출 것인가.
이는 검색기의 성능뿐만 아니라, 검색의 제어 흐름 (Control Flow) 문제입니다.
다음 회차에서는 Agentic RAG를 다룹니다.
RAG를 단 한 번의 검색이 아니라, 조사하고, 읽고, 부족함을 판단하고, 다시 찾는 하나의 루프 (Loop)로 바라봅니다.
―― AI 미래 편집실 「AI Watch」
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기