ReAct (Reasoning and Acting)
ReAct는 언어 모델이 추론(Reasoning)과 행동(Acting)을 어떻게 결합해야 복잡한 문제를 풀면서 할루시네이션을 줄일 수 있는가라는 질문에 답하는 논문이다. 상위 개념은 Agent Architecture와 Prompt Engineering이고, 하위 개념은 Thought-Action-Observation Loop이며, 이웃 개념은 Chain-of-Thought(CoT)와 Reflexion이다.
추론과 행동의 교차 생성
ReAct는 에이전트가 외부 환경과 상호작용하기 위해 사용하는 추론과 행동의 교차 생성(Interleaved Generation) 패러다임이다.
- 추론(Reasoning Trace, Thought): 행동의 방향을 설정, 진행 상태 추적, 예외 상황 처리(내부 상태 업데이트).
- 행동(Action): 외부 지식 베이스(Wikipedia)나 환경(웹 환경, 가상 환경)에서 정보를 수집하거나 조작(외부 상태 업데이트).
- 관찰(Observation): 행동의 결과로 환경이 반환하는 피드백.
논문은 사람에게서 "acting"과 "reasoning"의 타이트한 결합이 새 작업을 빨리 배우고, 처음 보는 상황이나 불확실한 정보 아래에서도 견고한 의사결정이나 추론을 하게 한다는 점을 동기로 든다.[1] 모델 쪽 결과로는 ReAct가 한 개에서 여섯 개의 in-context 예시만으로 새 task instance에 강한 일반화를 보인다고 보고한다.[1:1]
논문이 제시하는 근거
- 단순 Chain-of-Thought(CoT) 방식은 모델의 내부 파라미터 지식에만 의존해 "사고의 과정"을 생성하므로 팩트 할루시네이션(Fact Hallucination)이나 에러 전파(Error Propagation)에 취약하다.[1:2]
- 행동만 수행하는 모델(Act-only)은 고수준의 목표를 추론하거나 작업 메모리를 유지하지 못해 올바른 최종 행동에 도달하기 어렵다.[1:3]
- ALFWorld(34% 향상)와 WebShop(10% 향상) 등 복잡한 의사결정 벤치마크에서 모방 학습(Imitation Learning) 및 강화 학습(RL) 기반의 기존 베이스라인을 압도했다.[1:4]
- 사람의 의사결정 과정과 유사한 Thought-Action 구조 덕분에 모델의 판단 근거를 사람이 쉽게 해석하고, 도중에 Thought를 수정해 행동을 교정(human-in-the-loop)할 수도 있다.[1:5]
백엔드 시스템에서 ReAct가 갖는 의미
ReAct는 단순한 텍스트 생성기가 아니라, 외부 API와 연동되는 분산 워크플로 시스템(Distributed Workflow System)의 코어 엔진 역할을 한다고 해석할 수 있다. ReAct 루프는 상태 머신(State Machine)처럼 작동하며, 각 단계의 Observation이 다음 Thought의 입력으로 주입되면서 동적인 계획 수정(Dynamic Replanning)을 가능하게 한다.
동시에 성능과 유연성은 상충한다. ReAct는 외부 검색에 크게 의존하기 때문에 검색된 정보가 유용하지 않을 경우(non-informative search) 오히려 추론 흐름이 꼬여버릴 수 있다. 이를 방지하기 위해 내부 지식이 확고한 경우 CoT로, 그렇지 않은 경우 ReAct로 전환하는 혼합 방식(ReAct + CoT-SC)이 실무적으로 권장된다.
아래 API 추상화 설계와 실패 모드 대응은 ReAct 논문이 직접 제시한 architecture가 아니라, 논문의 Thought-Action-Observation loop를 backend system에 적용할 때의 설계 해석이다.
에이전트 친화적 API 추상화
사람이 사용하는 GUI나 복잡한 웹 네비게이션을 그대로 모델에게 노출하는 것은 비효율적이다. ReAct 논문이 Wikipedia 탐색을 오직 Search, Lookup, Finish 3가지의 명확한 시맨틱으로 제한한 것처럼,[1:6] 백엔드 개발자는 LLM이 오해 없이 파싱하고 예측할 수 있는 수준으로 도구(API)의 추상화 계층을 설계해야 한다.
실패 패턴과 운영 대응
논문에서 분석된 ReAct의 주요 에러 패턴은 백엔드 시스템의 모니터링·복구(retry) 전략과 직결된다.[1:7]
- Reasoning Error (47%): 가장 흔한 실패 유형으로, 잘못된 reasoning trace 전체를 가리킨다. 그 안에서 ReAct에 특유한 흔한 패턴은 모델이 이전의 Thought와 Action을 반복 생성해 루프를 빠져나오지 못하는 것이다.[1:8] 백엔드에서는 단순 타임아웃뿐 아니라, 동일 상태 전이가 N회 반복될 경우 강제로 루프를 끊는 서킷 브레이커 또는 강제 사람 승인 개입이 필요하다.
- Search Error (23%): 도구가 빈 결과를 반환하거나 쓸모없는 정보를 줄 때 발생하며, 모델의 추론 흐름을 완전히 탈선시킨다.[1:9] 도구가 단순 에러 코드를 던지는 대신, 모델이 스스로 복구할 수 있도록 "검색어의 스펠링을 확인하거나 다른 키워드를 시도해보세요" 같은 가이드형 에러 메시지를 반환하도록 API를 설계해야 한다.
ReAct 루프가 도는 순서
- 사용자 요청 입력: 예) "X가 Y보다 큰가?"
- Thought 생성: "X의 크기를 찾은 후 Y의 크기를 찾아야 한다. 먼저 X를 검색하자."
- Action 실행:
Search[X] - Observation 획득: 외부 API가 반환한 X의 크기 정보.
- Thought 갱신: "X의 크기는 알았다. 이제 Y를 검색하자."
- Action 실행:
Search[Y] - Observation 획득: 외부 API가 반환한 Y의 크기 정보.
- Thought 결론: "X와 Y의 크기를 비교해보면..."
- Action 종료:
Finish[결과 반환]
sequenceDiagram
participant LLM
participant Env as External Environment (API)
rect rgb(30, 40, 50)
note right of LLM: ReAct Loop
LLM->>LLM: 1. Thought (추론: 현재 상태 분석 및 계획)
LLM->>Env: 2. Action (행동: 도구 호출)
Env-->>LLM: 3. Observation (관찰: 도구 실행 결과)
end
LLM->>LLM: 4. Thought (결론 도출)
LLM->>Env: 5. Action (Finish: 결과 반환)루프 종료: LLM의 신호와 코드의 상한
ReAct 루프에는 종료 주체가 둘 있다. 평소에는 LLM이 끝낼 때를 정하고, LLM이 끝내지 못할 때는 코드가 상한으로 끊는다.
- 논문은 Wikipedia 행동을
Search,Lookup,Finish로 한정하고, few-shot 예시로 이 형식을 가르친다.[1:10]Finish를 내는 것은 LLM의 판단이며, 이 형식은 그 판단을 코드가 읽을 수 있게 담는 약속이라고 볼 수 있다. - 도구 호출 API를 쓰는 프레임워크는 별도의
Finish행동 대신 "도구 호출이 없는 응답"을 종료 신호로 쓴다. LangChaincreate_agent의 루프는 마지막 AI 메시지에 도구 호출이 없으면 루프를 빠져나가고, 코드 주석은 이를 에이전트 루프의 고전적인 종료 조건이라고 부른다.[2] 신호의 형식이 바뀌었을 뿐 판단 주체가 LLM이라는 점은 같다. - Deep Agents는 같은 도구 호출 루프 위에 파일시스템, 서브에이전트, 사람 승인 같은 harness 기능을 얹은 것이다.
create_deep_agent()는 내부에서create_agent()를 호출한다.[2:1] Harness 일반론은 Agent Harness가 다룬다. - LLM이 종료 신호를 끝내 내지 않을 수 있으므로 코드가 상한을 둬야 한다. 위 실패 패턴 절의 Reasoning Error에는 같은 Thought와 Action을 반복하는 루프가 흔한 패턴으로 들어 있다.[1:11] 논문도 ReAct가 정해진 단계(HotpotQA 7단계, FEVER 5단계) 안에 답을 내지 못하면 CoT-SC로 넘기는 상한을 둔다.[1:12]
- Deep Agents 문서는 상한이 없으면 혼란에 빠진 에이전트가 같은 도구 호출을 반복하거나 모델을 수백 번 호출해 몇 분 만에 API 예산을 소진할 수 있다고 경고한다. 그래서
ModelCallLimitMiddleware와ToolCallLimitMiddleware로 모델 호출과 도구 실행 수에 각각 상한을 걸도록 안내한다.run_limit은 한 번의 실행 안에서 세고,thread_limit은 checkpointer를 둔 대화 전체에서 센다.[2:2] create_deep_agent()는 LangGraph 실행 설정의recursion_limit을 9,999로 지정한다(캡처한 커밋 기준).[2:3] 기본 안전망은 크게 잡혀 있으므로, 비용을 통제하려면 위 호출 수 상한을 따로 거는 편이 직접적이다.
HotpotQA 예시로 보는 재검색
- Thought:
Colorado orogeny가 어느 지역에 있는지 찾아야 한다. - Action:
Search[Colorado orogeny] - Observation: 산맥 형성 과정이라는 문서 내용 반환.
- Thought: 문서에 eastern sector 언급이 없다.
eastern sector를 다시 검색해야겠다.[1:13]
다른 개념과의 관계
- In-context learning(few-shot prompting)에 기반한다.
- LLM이 어떻게 외부 지식에 추론을 접지(ground)시킬 수 있는지를 보여준다.
- Chain-of-Thought(내부 지식에만 의존)와 Act-only(추론 과정 없이 행동만 예측)와 대비된다.
- LangChain, AutoGPT 등 대다수 agent framework의 기본 라우팅 메커니즘으로 쓰인다.
관련
- Backend Agent Developer Roadmap: ReAct가 전체 분산 에이전트 시스템에서 어떻게 통합되고 학습되는지 거시적 관점을 제공하는 맵.
- AI Agents Overview: 대규모 언어 모델을 활용하는 에이전트 아키텍처의 전반적인 구조. ReAct는 그 중의 핵심 루프.
출처
테스트 질문
- ReAct가 순수한 Chain-of-Thought보다 할루시네이션(Hallucination)에 강한 이유는 무엇인가?
- ReAct 루프에서 Thought와 Action이 각각 담당하는 역할은 어떻게 다른가?
- 실무 환경에서 ReAct가 외부 API 검색 결과의 품질에 크게 좌우되는 문제를 극복하기 위한 보완 전략은 무엇인가?
- ReAct 에이전트가 반복 루프(Reasoning Error의 흔한 패턴)에 빠지는 것을 방지하기 위해 백엔드 관점에서 어떤 방어 로직을 구현해야 하는가?
- 사람에게 편리한 API 설계와 에이전트(LLM)에게 편리한 API 설계는 어떻게 다른가?
- ReAct 루프의 종료는 누가 판단하고, 코드는 그 판단을 무엇으로 알아채며, LLM이 멈추지 않으면 누가 끊는가?
ReAct_2210.03629.pdf (Introduction, 실험 결과, 에러 분석) — 이 PDF는 이번 변환 세션에서 poppler 부재로 재추출하지 못했고, 2026-07-11 conformance 기록 시점에 검증된 기존 claim(Introduction의 CoT/Act-only 한계 서술, ALFWorld/WebShop 벤치마크 수치, Wikipedia action space
Search/Lookup/Finish, Reasoning Error 47%·Search Error 23% 에러 분류, HotpotQA 예시)을 그대로 유지한다. 2026-10-06 텍스트 추출본 대조 인용: "This tight synergy between “acting” and “reasoning” allows humans to learn new tasks quickly and perform robust decision making or reasoning, even under previously unseen circumstances or facing information uncertainties." (p.1 Introduction), "ReAct shows strong generalization to new task instances while learning solely from one to six in-context examples" (p.4), "when ReAct fails to return an answer within given steps, back off to CoT-SC. We set 7 and 5 steps for HotpotQA and FEVER respectively" (p.5), Table 2 "Reasoning error Wrong reasoning trace (including failing to recover from repetitive steps)" (p.6), "one frequent error pattern specific to ReAct, in which the model repetitively generates the previous thoughts and actions, and we categorize it as part of “reasoning error”" (p.6) ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎deepagents-agent-loop-termination.md — LangChain Agents 도입부: "An agent is a model calling tools in a loop until a given task is complete.", "Deep Agents builds on
create_agent"; Deep Agents overview: "It is the same core tool calling loop as other agent frameworks"; Fault tolerance: "Without limits, a confused agent can burn through your LLM API budget in minutes by looping on the same tool call or making hundreds of model calls. Set caps on both model calls and tool executions per run", "Userun_limitto cap calls within a single invocation (resets each turn). Usethread_limitto cap calls across an entire conversation (requires a checkpointer).";factory.py: "# 3. If the model hasn't called any tools, exit the loop / # this is the classic exit condition for an agent loop";graph.py:return create_agent(..."recursion_limit": 9_999. ↩︎ ↩︎ ↩︎ ↩︎