Solon 4.0 ReActAgent: 생각하고 행동하는 AI 에이전트 구축을 위한 실무 가이드
요약
Solon 4.0의 ReActAgent를 활용하여 추론과 행동이 결합된 AI 에이전트를 구축하는 실무 가이드입니다. Thought-Action-Observation 루프를 통해 외부 도구와 상호작용하며 복잡한 문제를 해결하는 방법을 다룹니다.
핵심 포인트
- ReAct(Reason + Act) 프레임워크의 인지 루프 개념 이해
- Solon 4.0을 이용한 ChatModel 및 ReActAgent 구현 방법
- 외부 API 및 도구 호출을 통한 에이전트의 실행 능력 확장
- 프로덕션 환경 적용을 위한 의존성 설정 및 구성 방법
Solon 4.0 ReActAgent: 생각하고 행동하는 AI 에이전트 구축을 위한 실무 가이드
단순히 대화만 하는 것이 아니라 데이터베이스를 쿼리하고, API를 호출하며, 결정을 내리고, 결과로부터 학습하는 등 실제로 무언가를 수행하는 AI를 원한 적이 있다면, 제대로 찾아오셨습니다.
이 튜토리얼에서는 Solon 4.0의 ReActAgent를 사용하여 프로덕션 환경에 바로 적용 가능한 AI 에이전트를 구축하는 방법을 보여드리겠습니다. 이 과정이 끝나면, 복잡한 문제를 추론하고 외부 도구를 사용하며 실제 피드백을 바탕으로 행동을 조정할 수 있는 에이전트를 구축하게 될 것입니다.
ReActAgent는 무엇이 다른가?
전통적인 LLM (Large Language Models)은 텍스트 생성에는 뛰어나지만, 데이터베이스 확인, 실시간 데이터 가져오기, 계산 수행 등 현실 세계와 상호작용해야 할 때는 한계에 부딪힙니다.
ReActAgent (Reason + Act, 추론 + 행동)는 그 장벽을 허뭅니다. 이는 다음과 같은 인지 루프 (cognitive loop)를 구현합니다:
Thought (생각) → Action (행동) → Observation (관찰) → (반복 또는 종료)
에이전트는 다음에 무엇을 할지 **생각(thinks)**하고, 도구를 호출하여 **행동(acts)**하며, 그 결과를 **관찰(observes)**한 뒤, 계속 진행할지 아니면 최종 답변을 제공할지를 결정합니다.
이것은 단순한 이론이 아닙니다. Solon의 ReActAgent는 자동화된 고객 지원, 지능형 데이터 분석, 다단계 워크플로 자동화 등 프로덕션 환경에서 사용되어 왔습니다.
1. 의존성(Dependency) 추가하기
먼저, 프로젝트에 solon-ai-agent 모듈을 추가하세요:
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-ai-agent</artifactId>
...
참고: Solon의 parent POM을 사용 중이라면 버전이 자동으로 관리됩니다. 그렇지 않다면 최신 Solon 버전을 사용하세요.
2. ChatModel 구축하기 (에이전트의 두뇌)
모든 에이전트에는 추론을 가능하게 하는 "두뇌"인 ChatModel이 필요합니다. Fluent API를 사용하여 구축해 보겠습니다:
import org.noear.solon.ai.chat.ChatModel;
ChatModel chatModel = ChatModel.of("https://api.moark.com/v1/chat/completions")
...
YAML을 통해 구성하고 주입(inject)할 수도 있습니다:
solon.ai.chat:
demo:
apiUrl: "http://127.0.0.1:11434/api/chat"
...
@Inject("${solon.ai.chat.demo}")
ChatConfig chatConfig;
...
3. Hello World: 첫 번째 ReActAgent 만들기
간단한 것부터 시작해 봅시다. 도구(Tool)와 기본적인 에이전트(Agent)를 생성합니다:
import org.noear.solon.ai.agent.react.ReActAgent;
import org.noear.solon.ai.annotation.ToolMapping;
import org.noear.solon.ai.annotation.Param;
...
이를 실행하면 에이전트는 다음과 같이 동작합니다:
- 생각 (Think): "사용자가 현재 시간을 알고 싶어 합니다. 나에게는
getCurrentTime도구가 있습니다." - 행동 (Act):
getCurrentTime()을 호출합니다. - 관찰 (Observe): 타임스탬프를 가져옵니다.
- 응답 (Respond): "현재 시간은 2026-07-04T14:30:22... 입니다."
4. 실무 사례: 고객 지원 에이전트 (Customer Support Agent)
조금 더 실용적인 것을 만들어 보겠습니다. 주문 데이터베이스를 조회하고 재고를 확인할 수 있는 지원 에이전트입니다.
1단계: 도구 (Tools) 정의하기
import org.noear.solon.ai.chat.tool.AbsToolProvider;
import org.noear.solon.ai.annotation.ToolMapping;
import org.noear.solon.ai.annotation.Param;
...
2단계: 설정을 통한 에이전트 구축
ReActAgent supportAgent = ReActAgent.of(chatModel)
.name("customer_support")
.role("Customer Support Agent — 당신은 주문 문의와 재고 확인을 처리합니다.")
...
에이전트는 다음과 같이 동작합니다:
ORD-1002를 확인해야 함을 인지합니다.getOrderStatus("ORD-1002")를 호출합니다.- 결과인 "PENDING, 결제 미확인"을 읽습니다.
- 고객에게 결제가 아직 확인되지 않았음을 설명합니다.
5. 관찰 가능성 (Observability)을 위한 인터셉터 (Interceptors) 추가
운영 환경에서는 에이전트가 무엇을 생각하고 있는지에 대한 가시성이 필요합니다. ReActInterceptor는 생명주기 훅(Lifecycle hooks)을 제공합니다:
import org.noear.solon.ai.agent.react.ReActInterceptor;
import org.noear.solon.ai.agent.react.ReActTrace;
import org.noear.solon.ai.agent.react.task.ToolExchanger;
...
이를 통해 에이전트가 내리는 모든 결정에 대한 전체 감사 추적(Audit trail)을 확보할 수 있습니다.
6. 스트리밍 응답 (Streaming Responses)
오래 걸리는 작업의 경우, stream()을 사용하여 실시간 출력을 얻으세요:
agent.prompt("우리 상위 10개 제품을 분석하고 판매 요약본을 제공해 주세요.")
.stream()
.doOnNext(resp -> {
...
7. 고급: 호출별 옵션 (Per-Call Options)
.options()를 사용하여 개별 호출에 대한 동작을 미세 조정(fine-tune)할 수 있습니다:
agent.prompt("이 복잡한 데이터셋을 분석하고 JSON 보고서를 생성하세요.")
.session(mySession) // 기존 세션 재사용
.options(o -> o
...
사용 가능한 옵션 요약
| 카테고리 | 메서드 | 설명 | 기본값 |
|---|---|---|---|
| 제어 (Control) | maxTurns(int) | 최대 추론 단계 (Max reasoning steps) | 8 |
| ... |
8. 세션 및 트레이스(Traces) 작업하기
ReActAgent 세션을 사용하면 메모리(memory)를 활용한 장기 대화가 가능합니다:
import org.noear.solon.ai.agent.session.InMemoryAgentSession;
import org.noear.solon.ai.agent.AgentSession;
...
트레이스(trace) 객체는 다음 정보를 제공합니다:
- 전체 사고/행동/관찰 이력 (
getFormattedHistory()) - 단계 수 및 지표 (
getStepCount(),getMetrics()) - 도구 호출(tool call) 인자 및 결과
- 원본 프롬프트 및 세션 (
getOriginalPrompt(),getSession())
9. 경량 모델을 위한 텍스트 모드 (Text Mode)
모든 모델이 네이티브 도구 호출(native tool calls)을 지원하는 것은 아닙니다. ReActAgent는 텍스트 ReAct (Text ReAct) 모드를 지원합니다. 이 모드는 정규 표현식(regex)을 사용하여 모델의 텍스트 출력에서 Action: {json} 태그를 추출합니다. 이를 통해 네이티브 도구 호출 지원 기능이 없는 더 작고 가벼운 모델들과도 호환됩니다. 이는 에지 배포(edge deployments) 및 비용에 민감한 시나리오에 완벽합니다.
실행 스타일(ReActStyle)은 빌드 시점에 ReActAgentConfig를 통해 설정하며, ReActStyle.NATIVE (OpenAI 스타일의 tool_calls, 기본값)와 경량 방식인 ReActStyle.TEXT 중에서 선택할 수 있습니다. 텍스트 모드를 사용할 때, 에이전트는 모델의 출력에서 Action: {json} 태그를 파싱하여 해당하는 도구를 실행합니다.
전체 예제: 이커머스 지원 에이전트
다음은 바로 복사해서 사용할 수 있는 전체 예제입니다:
import org.noear.solon.ai.agent.react.ReActAgent;
import org.noear.solon.ai.agent.react.ReActInterceptor;
import org.noear.solon.ai.agent.react.ReActTrace;
...
핵심 요약 (Key Takeaways)
- ReActAgent는 사고(Thought) → 행동(Action) → 관찰(Observation) 루프를 따릅니다. 즉, 추론하고, 행동하며, 학습합니다.
- **도구 (Tools)**는
@ToolMapping및@Param어노테이션을 사용하여 정의하며, 단순한 POJO (Plain Old Java Object) 형태입니다. - **인터셉터 (Interceptors)**를 통해 에이전트의 의사 결정 과정에 대한 완전한 관찰 가능성 (Observability)을 확보할 수 있습니다.
- **호출별 옵션 (Per-call options)**을 사용하면 에이전트를 다시 구축하지 않고도 동작을 미세 조정할 수 있습니다.
- **텍스트 ReAct 모드 (Text ReAct mode)**는 네이티브 도구 호출 (Native tool calls)을 지원하지 않는 경량 모델에서도 작동합니다.
- **세션 (Sessions) 및 트레이스 (Traces)**를 통해 전체 감사 추적 (Audit trails)이 가능한 지속적인 대화가 가능합니다.
Solon의 ReActAgent는 최소한의 상용구 코드 (Boilerplate)로 Java 생태계에 프로덕션급 AI 에이전트 기능을 제공합니다. Solon의 동일한 프레임워크 설계 철학인 절제, 효율성, 개방성이 여기에도 적용되어, 프레임워크 종속성 (Lock-in) 없이 강력한 에이전트 기능을 사용할 수 있습니다.
더 자세히 알고 싶으신가요? 공식 Solon AI Agent 문서를 확인하거나 solon-ai GitHub 저장소를 탐색해 보세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기