에이전트가 “검색→검증→재검색”을 반복하게 만드는 Agentic RAG 구현 패턴 (2026년 7월 업데이트)
들어가며
전통적인 RAG는 대개 1회 검색(top-k) + 1회 생성으로 끝납니다. 문제는 실무에서 질문이 조금만 복잡해져도 “첫 검색이 틀리면 답 전체가 틀리는” 구조가 된다는 겁니다. 예를 들어:
- 사내 위키/티켓/PRD가 여러 곳에 흩어져 있고, 키워드가 애매함
- 최신/정확성 검증이 필요한 규정·정책 질의
- “근거가 부족하면 더 찾아라” 같은 탐색적(Exploratory) 질의
그래서 2025~2026년 흐름은 RAG를 ‘파이프라인’이 아니라 ‘루프(loop) + 의사결정’으로 다루는 Agentic RAG로 이동했습니다. 최근 SoK(2026)에서도 agentic RAG를 planning, retrieval orchestration, memory, tool invocation 모듈로 분해해 설명합니다. (arxiv.org) 또한 엔터프라이즈 환경에서는 “단발 검색 vs 도구 기반 반복 탐색”의 차이가 성능을 크게 가르는 요인으로 보고됩니다. (arxiv.org)
언제 쓰면 좋은가
- 정확성/근거가 최우선이고, “모르겠으면 더 찾아라/확인해라”가 가능한 작업
- 검색 대상이 크고(수천~수백만 문서), 질의가 모호하거나 다단계 추론이 필요한 경우
- 사용자 경험상 “답변 지연(수 초~수십 초)”을 감내할 수 있는 B2B/사내 도구
언제 쓰면 안 되는가
- 초저지연(수백 ms~1초대) Q&A가 제품의 핵심 KPI인 경우 (루프는 비용/지연이 기본적으로 증가)
- 데이터가 작고 정적이며, 벡터 검색 1~2번으로 충분한 경우
- “에이전트가 외부 도구를 자율 실행”하는 것이 정책/보안 상 위험한 경우 (특히 web/browse 계열)
🔧 핵심 개념
Agentic RAG의 본질은 “LLM이 답을 쓰기 전에, 검색을 ‘행동(act)’으로 보고 스스로 제어한다”입니다. 구현 관점에서 중요한 구성 요소는 아래 5개로 정리됩니다.
1) 주요 개념 정의
- Planner(계획기): 질의를 하위 질문으로 분해하고, 어떤 검색 전략(키워드/벡터/하이브리드/문서 내 탐색)을 쓸지 결정
- Retriever Tools(검색 도구): 벡터DB/키워드 검색/사내 검색 API/문서 내 find/open 등
- Critic / Reflector(평가/반성기): “근거가 충분한가?”, “출처가 충돌하는가?”, “질문에 답했는가?”를 판정해 루프를 돌릴지 종료할지 결정
- LangGraph 예시에서도 document grading + retry retrieval 같은 조건 분기/루프를 강조합니다. (langchain.com)
- Context Engineer(컨텍스트 엔지니어링): 무엇을 컨텍스트로 올리고(증거), 무엇을 요약/압축/버릴지(working memory) 관리
- 2026년 논문들에서도 context/memory overflow를 줄이는 설계가 주요 이슈로 다뤄집니다. (arxiv.org)
- Trace/Eval(관측/평가): “왜 저 검색을 했는가”, “툴 호출이 과했는가”를 로그로 남겨 품질/비용을 튜닝
- OpenAI도 Agents SDK/Tracing, Responses API 기반 오케스트레이션을 강조합니다. (openai.com)
2) 내부 작동 방식(구조/흐름)
실무에서 가장 재현성 있는 흐름은 “단일 에이전트 + 반복 검색 + 근거 판정” 패턴입니다.
- Query intake: 사용자 질문 + 정책(예: 내부 문서 우선, 최신성 필수)
- Plan: 하위 질문 생성(예: “정책 버전?”, “예외 조항?”)
- Retrieve: (a) 키워드/벡터/하이브리드 (b) 필요 시 문서 내 navigation(open/find)
- Evidence merge: 증거 문서들을 근거 단위로 정규화(제목/섹션/URL/날짜/스니펫)
- Critique:
- 근거 커버리지(질문에 필요한 슬롯이 채워졌나)
- 충돌(서로 다른 문서가 상반된 주장)
- 신뢰도(공식 문서/최신 버전/권한 범위)
- Loop or Answer:
- 부족하면 추가 검색 쿼리 생성/검색 범위 확장
- 충분하면 근거 인용 기반 최종 답변 생성
여기서 중요한 차이점은, 기존 RAG가 “retriever가 정답 후보를 뽑고 LLM이 서술”이라면, Agentic RAG는 LLM이 retriever를 도구로 다루면서 탐색 전략 자체를 최적화한다는 점입니다. 엔터프라이즈 지식베이스에서도 이 “single-shot → iterative tool use”가 큰 개선 요인으로 보고됩니다. (arxiv.org)
3) 다른 접근과의 차이점
- (기존) RAG 파이프라인: 빠르고 단순하지만, 첫 검색 실패에 취약
- GraphRAG/Knowledge Graph: 멀티홉/관계 기반 질의에 강점. 다만 구축 비용이 큼. 최근에는 “Graph + Agentic loop” 결합까지 논의됩니다. (arxiv.org)
- Agentic RAG: 인덱스/검색 품질만 올리는 게 아니라, 질의 전략을 런타임에 바꾸는 쪽으로 무게중심 이동
- “복잡한 검색 백엔드 vs LLM-driven logical retrieval” 같은 재정의도 나옵니다. (arxiv.org)
💻 실전 코드
아래 예제는 “사내 정책 문서(파일) + 외부 변경사항(웹)”을 함께 다루는 자율적 정보 검색 에이전트 시나리오입니다.
- 목표: 사용자가 “7월 이후 변경된 보안 정책을 반영해서 답해줘”라고 물으면, 1) 내부 문서를 먼저 찾고(File Search) 2) 최신 변경이 의심되면 Web Search로 보강 3) 근거가 부족하면 재검색 4) 최종 답변은 근거 목록 + 결론으로 출력
참고: OpenAI 쪽은 2026년 기준 Responses API + 내장 도구(web search/file search)를 “에이전트 오케스트레이션”의 핵심으로 밀고 있습니다. (openai.com) (또한 Assistants API는 2026년 8월 제거 예정으로 안내되어 있어, 신규 구현은 Responses 중심이 안전합니다. (help.openai.com))
0) 사전 준비
1
2
pip install openai pydantic python-dotenv
export OPENAI_API_KEY="..."
1) 에이전트 루프 구현 (Python, Responses API + 도구 호출)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from openai import OpenAI
from pydantic import BaseModel, Field
from typing import List, Literal, Optional
import os
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
# ---- 모델이 "다음 액션"을 결정하도록 강제하는 스키마 ----
class NextAction(BaseModel):
action: Literal["retrieve_internal", "retrieve_web", "answer"] = Field(...)
query: Optional[str] = Field(default=None, description="검색 쿼리(필요 시)")
reason: str
missing_slots: List[str] = Field(default_factory=list, description="근거가 부족한 항목")
SYSTEM = """너는 Agentic RAG 자율 에이전트다.
목표: 답변을 하기 전에 근거를 수집/검증하고, 부족하면 재검색한다.
규칙:
- 내부 문서(File Search) 우선.
- 최신성 이슈가 있거나 내부 문서가 불충분하면 Web Search로 보강.
- 근거가 2개 이상이고 서로 모순이 없을 때만 answer.
- 매 루프마다 missing_slots를 갱신하라.
출력은 NextAction JSON만.
"""
def decide_next(user_question: str, evidence: str) -> NextAction:
resp = client.responses.create(
model="gpt-4o-mini",
input=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": f"질문:\n{user_question}\n\n현재 근거:\n{evidence}\n"}
],
response_format={
"type": "json_schema",
"json_schema": {
"name": "NextAction",
"schema": NextAction.model_json_schema()
}
}
)
data = resp.output_text # JSON string
return NextAction.model_validate_json(data)
def tool_retrieve_internal(query: str) -> str:
# 예시: OpenAI 내장 file_search를 쓸 때는 tool 구성/벡터스토어 연결이 필요.
# 여기서는 "내부 검색 결과 문자열"이 반환된다고 가정(실서비스에선 사내 검색 API로 대체 가능).
# 실제 OpenAI file_search 사용은 Responses API tool로 연결. (도구 스펙은 공식 문서 참고)
return f"[INTERNAL] query={query}\n- Policy v3.2(2026-06-10): ...\n- Exception memo(2026-07-02): ...\n"
def tool_retrieve_web(query: str) -> str:
# 마찬가지로 실제로는 web_search tool을 Responses API에 붙여 사용.
return f"[WEB] query={query}\n- Vendor advisory(2026-07-15): ...\n- Community report(2026-07-20): ...\n"
def synthesize_answer(user_question: str, evidence: str) -> str:
resp = client.responses.create(
model="gpt-4o",
input=[
{"role": "system", "content": "근거 기반으로만 답하라. 답변 끝에 근거 목록을 bullet로 붙여라."},
{"role": "user", "content": f"질문:\n{user_question}\n\n근거:\n{evidence}\n"}
]
)
return resp.output_text
def run_agent(user_question: str, max_iters: int = 4) -> str:
evidence = ""
for i in range(max_iters):
na = decide_next(user_question, evidence)
if na.action == "retrieve_internal":
q = na.query or user_question
evidence += "\n" + tool_retrieve_internal(q)
elif na.action == "retrieve_web":
q = na.query or user_question
evidence += "\n" + tool_retrieve_web(q)
else:
return synthesize_answer(user_question, evidence)
# 반복 제한 도달: 실패를 "명시적으로" 반환(실무에서 중요)
return "근거를 충분히 수집하지 못했습니다. 질문을 더 구체화하거나 검색 범위를 확장하세요."
if __name__ == "__main__":
question = "2026년 7월 기준으로 우리 보안 정책에서 '외부 SaaS로 로그 반출' 관련 변경사항을 반영해 요약해줘."
print(run_agent(question))
예상 출력(예시)
- 결론 요약(변경된 조항/예외/승인 프로세스)
- 근거 bullet 2~4개(내부 정책 문서 버전, 7월 예외 메모, 벤더 advisory 등)
2) 확장: “문서 내 navigation”을 넣는 이유
AgenticRAG 계열 연구/사례에서 자주 강조되는 게 search → open → find → summarize 같은 “문서 내 이동”입니다. 단순 top-k chunk로는 “정의/예외/각주”를 놓치기 쉬워서, 에이전트가 문서 구조를 탐색하게 하면 효율이 좋아집니다. (arxiv.org)
실무 팁은 “retriever가 뽑은 chunk”를 끝내지 말고, 에이전트에게:
- 문서 ID를 주고
- 특정 섹션/키워드를
find - 필요하면 해당 섹션만
open하게 만드는 것입니다(컨텍스트 낭비 감소).
⚡ 실전 팁 & 함정
Best Practice (2~3개)
1) 종료 조건을 ‘정량화’하라
- “근거 2개 이상” 같은 규칙만으로는 부족합니다.
- 권장:
coverage_score(0~1),conflict_detected(bool),freshness_required(bool)를 만들어 답변 가능 상태를 명시- SoK(2026)에서도 모듈화/평가 관점이 중요하게 정리됩니다. (arxiv.org)
2) 루프 비용을 예산으로 통제하라
max_iters,tool_call_budget,token_budget를 두고 초과 시 “부분 답 + 다음 액션 제안”으로 degrade.- OpenAI도 장시간 에이전트에서 컨텍스트/출력 폭증, 오케스트레이션 필요성을 직접 언급합니다. (openai.com)
3) Retrieval을 1종류로 고집하지 말고 ‘라우팅’하라
- 구조화된 데이터(정책/테이블/코드)는 키워드/FTS가 더 잘 맞는 경우가 많고,
- 자연어 지식은 벡터가 유리합니다.
- 에이전트가 “이번 질의는 키워드가 낫다/벡터가 낫다”를 선택하게 해야 합니다(= Router). (최근 실무 가이드들도 이 패턴을 전면에 둡니다.) (scalacode.com)
흔한 함정/안티패턴
- “무조건 web search”: 내부 문서 우선 원칙이 무너지면 보안/정합성/라이선스 문제가 생깁니다.
- 근거를 컨텍스트에 통째로 던지기: 토큰만 늘고, 모델이 중요한 문장을 놓칩니다. “증거 단위 정규화(제목/날짜/핵심 문장/링크)”가 필수.
- 에이전트가 ‘확신’하는 것처럼 말하게 방치: 부족하면 “모른다 + 추가로 필요한 정보/검색 범위”를 출력하도록 강제해야 운영이 됩니다.
비용/성능/안정성 트레이드오프
- 품질을 올리려면 루프를 돌려야 하지만, 루프는 지연 + 비용 + 실패 모드(무한 재검색)를 동반합니다.
- 따라서 “정확성 우선(법무/보안/의료)”과 “응답성 우선(고객 챗봇)”을 같은 아키텍처로 풀려고 하면 망합니다. 제품 요구사항에 따라 agentic loop의 깊이를 다르게 설계해야 합니다.
- 관측/트레이싱이 없으면 튜닝이 불가능합니다(“왜 6번이나 검색했지?”를 알아야 줄일 수 있음). (openai.github.io)
🚀 마무리
Agentic RAG는 “RAG를 더 복잡하게” 만드는 게 아니라, 실패를 전제로 한 정보탐색을 제품에 올리는 방법입니다. 핵심은:
- 검색을 한 번에 끝내지 말고 판정(critic) + 재검색(loop)을 설계할 것
- retrieval/memory/context를 모듈로 분리하고 종료 조건을 정량화할 것 (arxiv.org)
- 엔터프라이즈에서는 특히 “single-shot retrieval → tool 기반 반복 탐색” 전환이 효과의 큰 부분을 차지할 수 있음 (arxiv.org)
도입 판단 기준(현실적인 체크리스트)
- (필수) 답변 실패 시 “추가 탐색”이 사용자 가치로 이어지는가?
- (필수) 지연 5~20초를 허용할 수 있는 UX인가?
- (권장) 근거/출처/최신성 정책을 코드로 강제할 수 있는가?
- (권장) 트레이싱/평가 파이프라인을 운영할 준비가 됐는가?
다음 학습 추천
- LangGraph 기반 self-reflective/loop 설계(조건 분기 + 재시도 그래프) (langchain.com)
- Agentic RAG 아키텍처/평가 분해(SoK 2026) (arxiv.org)
- 엔터프라이즈 검색 인프라 위에 에이전트 harness를 얹는 접근(AgenticRAG 2026) (arxiv.org)
원하면, 당신의 데이터 형태(문서 종류/권한 모델/검색 인프라)와 SLA(지연/비용 상한)를 기준으로 “루프 깊이/툴 구성/평가 지표”까지 포함한 구체 아키텍처를 같이 설계해드릴게요.