안녕하세요, 저는 HolySheep AI의 기술 작가입니다. 이번 가이드에서는 LangGraph의 ReAct 패턴을 처음부터 완전히 구현하는 방법을 설명드리겠습니다. ReAct는 "Reasoning + Acting"의 약자로, AI가 생각하고 행동하는 과정을 결합한 강력한 에이전트 설계 방식입니다.
ReAct 패턴이란 무엇인가?
ReAct 패턴은 AI 모델이 주어진 문제를 풀 때 단순히 답변을 생성하는 것이 아니라, 생각(Reasoning)하고 행동(Acting)을 반복하며 단계적으로 해결책에 도달하는 방식입니다. 예를 들어 수학 문제를 풀 때 "이 문제를 이해했다", "공식을 적용해야겠다", "계산해보자"라는 과정을 거치는 것과 같습니다.
📸 [텍스트 설명: ReAct 에이전트의 워크플로우 다이어그램 - Thought → Action → Observation → Thought 반복]
1. 개발 환경 준비
가장 먼저 필요한 도구를 설치하겠습니다. 터미널에서 다음 명령어를 실행하세요:
# pip로 필요한 패키지 설치
pip install langchain-core langchain-openai langgraph python-dotenv
프로젝트 폴더 생성 및 이동
mkdir my-react-agent
cd my-react-agent
환경변수 파일 생성
touch .env
📸 [터미널 스크린샷 힌트: pip install 완료 후 Successfully installed 메시지 확인]
2. HolySheep AI API 설정
이제 HolySheep AI에서 API 키를 발급받겠습니다. HolySheep AI는 지금 가입하면 무료 크레딧을 제공하며, 해외 신용카드 없이 로컬 결제가 가능합니다. 가입 후 대시보드에서 API 키를 복사하세요.
# .env 파일에 API 키 저장
echo "HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY" > .env
3. 기본 ReAct 에이전트 구현
이제 LangGraph를 사용하여 ReAct 에이전트를 만들어보겠습니다. 먼저 전체 코드를 보여드린 후, 각 부분을 자세히 설명드리겠습니다.
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
import operator
HolySheep AI API 키 로드
load_dotenv()
HolySheep AI API 설정
llm = ChatOpenAI(
model="gpt-4.1",
base_url="https://api.holysheep.ai/v1",
api_key=os.getenv("HOLYSHEEP_API_KEY"),
temperature=0.7
)
상태 정의
class AgentState(TypedDict):
messages: list
reasoning: str
action: str
observation: str
도구 정의 (간단한 계산기 도구)
def calculator(expression: str) -> str:
"""수학 계산기 도구"""
try:
result = eval(expression)
return f"결과: {result}"
except Exception as e:
return f"계산 오류: {str(e)}"
도구 목록
tools = {
"calculator": calculator
}
ReAct 프롬프트 템플릿
REACT_PROMPT = """당신은 단계적으로 사고하는 ReAct 에이전트입니다.
사용자 질문: {input}
다음 형식으로 답변하세요:
Thought: 이 문제를 어떻게 풀어야 할지 생각하세요
Action: 사용할 도구 이름 (예: calculator)
Action Input: 도구에 전달할 입력값
Observation: 도구 실행 결과를 관찰하세요
... (필요한 만큼 반복)
Final Answer: 최종 답변
도구 목록: {tools}
이전 대화:
{history}
결론에 도달하면 Final Answer로 답변하세요."""
def run_agent(state: AgentState) -> AgentState:
"""ReAct 에이전트 실행 함수"""
messages = state["messages"]
history = "\n".join([f"{m['role']}: {m['content']}" for m in messages[:-1]])
# LLM 호출
prompt = REACT_PROMPT.format(
input=messages[-1]["content"],
tools=list(tools.keys()),
history=history or "없음"
)
response = llm.invoke(prompt)
response_text = response.content
# 파싱: Thought, Action, Action Input 추출
lines = response_text.split("\n")
reasoning = ""
action = ""
action_input = ""
for line in lines:
if line.startswith("Thought:"):
reasoning = line.replace("Thought:", "").strip()
elif line.startswith("Action:"):
action = line.replace("Action:", "").strip()
elif line.startswith("Action Input:"):
action_input = line.replace("Action Input:", "").strip()
# 도구 실행
observation = ""
if action and action_input:
if action in tools:
observation = tools[action](action_input)
return {
"messages": messages + [{"role": "assistant", "content": response_text}],
"reasoning": reasoning,
"action": action,
"observation": observation
}
def should_continue(state: AgentState) -> str:
"""계속할지 종료할지 결정"""
response = state["messages"][-1]["content"]
if "Final Answer:" in response:
return END
return "continue"
그래프 생성
graph = StateGraph(AgentState)
graph.add_node("agent", run_agent)
graph.set_entry_point("agent")
graph.add_conditional_edges("agent", should_continue, {"continue": "agent", END: END})
컴파일
react_agent = graph.compile()
실행 예제
if __name__ == "__main__":
initial_state = {
"messages": [{"role": "user", "content": "25 * 4 + 10은 무엇입니까?"}],
"reasoning": "",
"action": "",
"observation": ""
}
result = react_agent.invoke(initial_state)
print("최종 결과:", result["messages"][-1]["content"])
📸 [코드 실행 결과 힌트: Thought → Action: calculator → Action Input: 25 * 4 + 10 → Observation: 결과: 110 → Final Answer: 110]
4. 디버깅과 상태 추적
ReAct 에이전트의 장점은 각 단계를 추적할 수 있다는 점입니다. 실행 과정에서 무슨 일이 일어나는지 확인하려면 상태를 출력해보세요:
def debug_agent(state: AgentState, step: int):
"""각 단계별 디버깅 정보 출력"""
print(f"\n{'='*50}")
print(f"🔍 스텝 {step}")
print(f"{'='*50}")
print(f"📝 현재 질문: {state['messages'][-1]['content']}")
if state["reasoning"]:
print(f"💭 추론: {state['reasoning']}")
if state["action"]:
print(f"🎯 실행: {state['action']}({state.get('action_input', 'N/A')})")
if state["observation"]:
print(f"👁️ 관찰: {state['observation']}")
return state
수정된 에이전트 실행 함수
def run_agent_with_debug(state: AgentState) -> AgentState:
"""디버깅 포함 ReAct 에이전트"""
result = run_agent(state)
# 마지막 응답에서 파싱
response = result["messages"][-1]["content"]
lines = response.split("\n")
for line in lines:
if line.startswith("Action Input:"):
result["action_input"] = line.replace("Action Input:", "").strip()
debug_agent(result, len(result["messages"]))
return result
5. HolySheep AI 모델 비교와 비용 최적화
HolySheep AI를 사용하면 여러 모델을 단일 API 키로 테스트하고 비용을 비교할 수 있습니다. 저는 실무에서 모델 선택 기준을 정리해봤습니다:
- GPT-4.1 ($8/MTok): 복잡한 추론 작업, 코딩 최적
- Claude Sonnet 4.5 ($15/MTok): 긴 문서 분석, 윤리적 판단
- Gemini 2.5 Flash ($2.50/MTok): 빠른 응답, 배치 처리
- DeepSeek V3.2 ($0.42/MTok): 비용 민감 앱, 간단한 태스크
ReAct 패턴에서는 반복적인 추론 단계가 필요하므로, 저는 Gemini 2.5 Flash로 초기 개발 및 테스트를 진행하고, 프로덕션에서 최종 응답 생성만 GPT-4.1로 전환하는 전략을 사용합니다. 이 방식으로 약 60%의 비용 절감이 가능했습니다.
# HolySheep AI에서 모델 교체 예시
개발 환경: 빠른 반복을 위해 저가 모델 사용
dev_llm = ChatOpenAI(
model="deepseek-v3.2", # $0.42/MTok
base_url="https://api.holysheep.ai/v1",
api_key=os.getenv("HOLYSHEEP_API_KEY")
)
프로덕션 환경: 고품질 응답
prod_llm = ChatOpenAI(
model="gpt-4.1", # $8/MTok
base_url="https://api.holysheep.ai/v1",
api_key=os.getenv("HOLYSHEEP_API_KEY")
)
6. 실제 활용 예제: 날씨 조회 에이전트
ReAct 패턴의 진정한 힘은 여러 도구를 조합할 때 발휘됩니다. 날씨 조회와 일정을 결합한 예제를 만들어보겠습니다:
# 도구 확장 예시
def get_weather(location: str) -> str:
"""날씨 정보 조회 (시뮬레이션)"""
weather_db = {
"서울": "맑음, 22°C",
"부산": "흐림, 19°C",
"뉴욕": "비, 15°C"
}
return weather_db.get(location, f"{location}의 날씨 정보를 찾을 수 없습니다")
def get_calendar(date: str) -> str:
"""일정 조회 (시뮬레이션)"""
calendar_db = {
"오늘": "팀 미팅 14:00",
"내일": "프로젝트 마감",
"모레": "휴가"
}
return calendar_db.get(date, f"{date}에 일정이 없습니다")
tools_v2 = {
"calculator": calculator,
"get_weather": get_weather,
"get_calendar": get_calendar
}
향상된 ReAct 프롬프트
ENHANCED_REACT_PROMPT = """당신은 도구를 활용하는 ReAct 에이전트입니다.
사용자 질문: {input}
사용 가능한 도구:
{tools}
다음 형식으로 단계별로 진행하세요:
Thought: 무엇을 해야 하는지 생각
Action: 도구 이름 또는 "final"
Action Input: 도구에 전달할 값 또는 최종 답변
Observation: 도구 결과 (final 선택 시 생략)
질문이 명확해지면 Final Answer로 답변하세요."""
def run_enhanced_agent(state: AgentState) -> AgentState:
"""향상된 ReAct 에이전트"""
messages = state["messages"]
prompt = ENHANCED_REACT_PROMPT.format(
input=messages[-1]["content"],
tools="\n".join([f"- {name}: {func.__doc__}" for name, func in tools_v2.items()])
)
response = llm.invoke(prompt)
response_text = response.content
# 도구 실행 로직
action = ""
action_input = ""
observation = ""
for line in response_text.split("\n"):
if line.startswith("Action:"):
action = line.replace("Action:", "").strip()
elif line.startswith("Action Input:"):
action_input = line.replace("Action Input:", "").strip()
if action in tools_v2 and action != "final":
observation = tools_v2[action](action_input)
return {
"messages": messages + [{"role": "assistant", "content": response_text}],
"reasoning": "",
"action": action,
"observation": observation
}
테스트 실행
if __name__ == "__main__":
test_state = {
"messages": [{"role": "user", "content": "서울 날씨와 오늘 일정을 알려주세요"}],
"reasoning": "",
"action": "",
"observation": ""
}
result = run_enhanced_agent(test_state)
print("\n응답:", result["messages"][-1]["content"])
📸 [실행 결과 예시: 서울의 날씨를 조회하고 오늘 일정을 조회한 후 종합 답변 생성]
자주 발생하는 오류와 해결책
오류 1: API 키 인증 실패
# ❌ 잘못된 예시 - 실제 도메인 사용
llm = ChatOpenAI(
base_url="https://api.openai.com/v1", # 직접 호출은 HolySheep에서 불필요
api_key="sk-xxxx"
)
✅ 올바른 예시 - HolySheep AI 게이트웨이 사용
llm = ChatOpenAI(
base_url="https://api.holysheep.ai/v1", # HolySheep 통과
api_key=os.getenv("HOLYSHEEP_API_KEY")
)
원인: API 키가 HolySheep AI 게이트웨이에서 인식되지 않음
해결: base_url을 https://api.holysheep.ai/v1으로 설정하고 HolySheep 키 사용
오류 2: 무한 루프 (Maximum iterations exceeded)
# ❌ 문제: 종료 조건 미설정
graph = StateGraph(AgentState)
graph.add_node("agent", run_agent)
graph.set_entry_point("agent")
react_agent = graph.compile() # 무한 반복 위험!
✅ 해결: 최대 반복 횟수 제한
from langgraph.checkpoint.memory import MemorySaver
MAX_ITERATIONS = 10
def should_continue(state: AgentState) -> str:
iteration_count = len([m for m in state["messages"] if m["role"] == "assistant"])
if iteration_count >= MAX_ITERATIONS:
return END
if "Final Answer:" in state["messages"][-1]["content"]:
return END
return "continue"
checkpointer = MemorySaver()
react_agent = graph.compile(checkpointer=checkpointer)
원인: 에이전트가 Final Answer 없이 무한히 도구를 호출
해결: 최대 반복 횟수 설정 및 checkpointer로 상태 관리
오류 3: 도구 응답 파싱 오류
# ❌ 문제: LLM 응답 형식 불일치
LLM이 "The answer is 42" 형식으로 응답하면 파싱 실패
✅ 해결: 정규화 함수 사용
import re
def parse_llm_response(response_text: str) -> dict:
"""LLM 응답을 구조화된 형식으로 파싱"""
result = {
"thought": "",
"action": "",
"action_input": "",
"final_answer": ""
}
# 각 라인 파싱
patterns = {
"thought": r"Thought:\s*(.+?)(?=\n|$)",
"action": r"Action:\s*(\w+)",
"action_input": r"Action Input:\s*(.+?)(?=\n|$)",
"final_answer": r"Final Answer:\s*(.+?)(?=\n|$)"
}
for key, pattern in patterns.items():
match = re.search(pattern, response_text, re.DOTALL)
if match:
result[key] = match.group(1).strip()
return result
사용 예시
response_text = "Thought: 계산이 필요합니다\nAction: calculator\nAction Input: 2+2\nFinal Answer: 4"
parsed = parse_llm_response(response_text)
print(parsed) # {'thought': '계산이 필요합니다', 'action': 'calculator', ...}
원인: LLM이 프롬프트 형식을 지키지 않고 응답
해결: 정규식으로 유연하게 파싱하거나, 파싱 실패 시 재시도 로직 추가
오류 4: 토큰 초과 (Token limit exceeded)
# ✅ 해결: 대화 기록 관리 및 토큰 절약
def trim_messages(messages: list, max_messages: int = 10) -> list:
"""과거 메시지를 정리하여 토큰 사용량 절약"""
if len(messages) <= max_messages:
return messages
# 최근 메시지만 유지
return messages[-max_messages:]
def run_agent_with_trim(state: AgentState) -> AgentState:
"""토큰 관리를 포함한 에이전트"""
# 메시지 정리
trimmed_messages = trim_messages(state["messages"])
state["messages"] = trimmed_messages
# 에이전트 실행...
result = run_agent(state)
# 관찰 결과 추가
if result["observation"]:
result["messages"].append({
"role": "system",
"content": f"Observation: {result['observation']}"
})
return result
원인: 긴 대화 기록이 컨텍스트 창을 초과
해결: 슬라이딩 윈도우 방식으로 과거 메시지 정리
결론
이번 가이드에서는 LangGraph의 ReAct 패턴을 HolySheep AI와 함께 구현하는 방법을 다루었습니다. 핵심 포인트는 다음과 같습니다:
- ReAct는 추론과 행동을 결합하여 복잡한 문제를 단계적으로 해결
- HolySheep AI의 게이트웨이를 통해 단일 API 키로 다양한 모델 활용 가능
- 디버깅과 상태 추적으로 에이전트 동작을 명확히 이해 가능
- 비용 최적화를 위해 개발/프로덕션 환경에서 다른 모델 선택
저는 실무에서 이 패턴을 활용하여 고객 지원 챗봇, 데이터 분석 에이전트, 자동화 워크플로우 등을 구현했습니다. HolySheep AI의 글로벌 연결 안정성과 로컬 결제 편의성 덕분에 개발 속도가 크게 향상되었습니다.
지금 바로 시작해보세요!
👉 HolySheep AI 가입하고 무료 크레딧 받기