Spring AI 에이전트 패턴, 초보자도 이해하는 쉬운 해설
·10분 읽기

Spring AI 에이전트 패턴 원문 흐름 번역 + 쉬운 해설 (코드/다이어그램 포함)

좋아, 이번 글은 요약이 아니라 Spring 원문 흐름을 따라가면서,
- 패턴별 핵심 의미
- 원문 맥락의 코드
- 이해를 돕는 다이어그램 을 모두 포함해서 정리했다.
0) 먼저 큰 메시지
Spring 글이 Anthropic 연구를 바탕으로 강조하는 핵심은 아래다.
- 복잡한 프레임워크부터 시작하지 말 것
- 단순한 패턴을 조합할 것
- 운영 가능성(예측 가능성/유지보수성)을 우선할 것
1) Agentic Systems: 워크플로우 vs 에이전트
- 워크플로우: 코드로 경로를 고정
- 에이전트: 모델이 다음 행동/도구를 동적으로 결정
다이어그램
flowchart LR
A[입력] --> B{고정 경로?}
B -->|예| C[Workflow\n(정해진 코드 경로)]
B -->|아니오| D[Agent\n(모델이 동적 결정)]
C --> E[예측 가능성 높음]
D --> F[유연성 높음]
초보자 관점 한 줄:
- 운영 안정성이 중요하면 워크플로우부터,
- 미리 경로를 정할 수 없는 복잡한 문제면 에이전트로 확장.
2) 패턴 1 — Chain Workflow
복잡한 작업을 단계로 나눠 순차 처리하는 패턴.
의미
- 각 단계 책임이 명확해짐
- 한 번에 시키는 것보다 정확도 향상 가능
- 대신 지연시간은 증가
다이어그램
코드 (원문 맥락)
public class ChainWorkflow {
private final ChatClient chatClient;
private final String[] systemPrompts;
// Processes input through a series of prompts, where each step's output
// becomes input for the next step in the chain.
public String chain(String userInput) {
String response = userInput;
for (String prompt : systemPrompts) {
String input = String.format("{%s}\n {%s}", prompt, response);
response = chatClient.prompt(input).call().content();
}
return response;
}
}
3) 패턴 2 — Parallelization Workflow
여러 LLM 호출을 동시에 실행하고 결과를 합치는 패턴.
의미
- 속도 개선(동시 처리)
- 관점 다양화(투표/합의)
다이어그램
코드 (원문 맥락)
List<String> parallelResponse = new ParallelizationWorkflow(chatClient)
.parallel(
"Analyze how market changes will impact this stakeholder group.",
List.of(
"Customers: ...",
"Employees: ...",
"Investors: ...",
"Suppliers: ..."
),
4
);
4) 패턴 3 — Routing Workflow
입력을 분류해서 가장 적합한 전문 프롬프트로 보내는 패턴.
의미
- 하나의 범용 프롬프트보다 품질 개선
- 입력 유형별 전문화 가능
다이어그램
코드 (원문 맥락)
@Autowired
private ChatClient chatClient;
RoutingWorkflow workflow = new RoutingWorkflow(chatClient);
Map<String, String> routes = Map.of(
"billing", "You are a billing specialist. Help resolve billing issues...",
"technical", "You are a technical support engineer. Help solve technical problems...",
"general", "You are a customer service representative. Help with general inquiries..."
);
String input = "My account was charged twice last week";
String response = workflow.route(input, routes);
5) 패턴 4 — Orchestrator-Workers
중앙 LLM(오케스트레이터)이 과업을 분해하고, 워커들이 병렬 처리한 뒤 합성하는 패턴.
의미
- 하위 작업을 미리 고정하기 어려운 문제에 유리
- 복잡 작업을 유연하게 분해 가능
다이어그램
코드 (원문 맥락)
public class OrchestratorWorkersWorkflow {
public WorkerResponse process(String taskDescription) {
// 1. Orchestrator analyzes task and determines subtasks
OrchestratorResponse orchestratorResponse = // ...
// 2. Workers process subtasks in parallel
List<String> workerResponses = // ...
// 3. Results are combined into final response
return new WorkerResponse(/*...*/);
}
}
ChatClient chatClient = // ... initialize chat client
OrchestratorWorkersWorkflow workflow = new OrchestratorWorkersWorkflow(chatClient);
WorkerResponse response = workflow.process(
"Generate both technical and user-friendly documentation for a REST API endpoint"
);
System.out.println("Analysis: " + response.analysis());
System.out.println("Worker Outputs: " + response.workerResponses());
6) 패턴 5 — Evaluator-Optimizer
생성 모델과 평가 모델이 반복 루프를 돌며 결과를 개선하는 패턴.
의미
- 품질 기준이 명확한 작업에서 강력
- 사람의 “작성→리뷰→수정” 흐름을 자동화
다이어그램
코드 (원문 맥락)
public class EvaluatorOptimizerWorkflow {
public RefinedResponse loop(String task) {
// 1. Generate initial solution
Generation generation = generate(task, context);
// 2. Evaluate the solution
EvaluationResponse evaluation = evaluate(generation.response(), task);
// 3. If PASS, return solution
// 4. If NEEDS_IMPROVEMENT, incorporate feedback and generate new solution
// 5. Repeat until satisfactory
return new RefinedResponse(finalSolution, chainOfThought);
}
}
ChatClient chatClient = // ... initialize chat client
EvaluatorOptimizerWorkflow workflow = new EvaluatorOptimizerWorkflow(chatClient);
RefinedResponse response = workflow.loop(
"Create a Java class implementing a thread-safe counter"
);
System.out.println("Final Solution: " + response.solution());
System.out.println("Evolution: " + response.chainOfThought());
7) Spring AI 구현 장점 (원문 포인트)
- 모델 포터빌리티: 모델 교체 유연성
- Structured Output: 타입 안전한 응답 파싱
- 일관된 ChatClient API: 구현 일관성
예시(원문 맥락):
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
EvaluationResponse response = chatClient.prompt(prompt)
.call()
.entity(EvaluationResponse.class);
8) 초보자용 적용 순서 (실무 권장)
- 단일 프롬프트 + RAG부터 시작
- 안 되면 체인/라우팅 하나 추가
- 성능 개선이 확인되면 병렬화 확장
- 복잡 과제에서만 오케스트레이터 도입
- 완성도 필요 시 평가-최적화 루프 추가
즉, 복잡도는 기능이 아니라 비용이므로, 반드시 성능 개선이 확인될 때만 올리는 게 정석이다.
출처
- Spring Blog: Building Effective Agents with Spring AI (Part 1) https://spring.io/blog/2025/01/21/spring-ai-agentic-patterns
- Anthropic Research: Building effective agents https://www.anthropic.com/research/building-effective-agents
원문 패턴 설명 및 코드 예시를 기반으로 한국어 번역/해설했습니다.