멀티 에이전트 협업 실전: 4가지 아키텍처 패턴 선택 가이드

Anthropic의 연구 데이터에 따르면 멀티 Agent 시스템은 단일 Agent보다 성능이 90.2% 높습니다. 단일 Agent에는 세 가지 치명적인 약점이 있습니다. 컨텍스트 한계(200k token을 넘어서면 엉뚱한 출력을 내기 시작함), 분산된 역량(기능을 너무 많이 넣으면 무엇이든 조금씩만 하는 만능형이 됨), 어려운 디버깅(Agent 하나가 고장 나도 문제의 근원을 찾기 어려움)입니다. 멀티 에이전트 협업 시스템은 AI 세계의 ‘마이크로서비스 아키텍처’와 같습니다. 각 Agent는 한 가지 일만 담당하고 명확한 메시지 전달을 통해 협업합니다.
네 가지 핵심 아키텍처 패턴은 각각 적합한 상황이 다릅니다. Subagents(중앙 오케스트레이션)는 독립된 여러 도메인의 병렬 처리에, Skills(필요할 때 로드)는 단일 스레드의 다단계 처리에, Handoffs(상태 기반)는 다단계 대화에, Router(병렬 분배)는 여러 데이터 소스 조회에 적합합니다. 이 글에서는 선택 기준과 프로덕션 환경의 함정부터 LangGraph 코드 구현까지 살펴보며 ‘Subagents와 Skills 중 무엇을 써야 하는가’, ‘Agent 사이의 상태를 어떻게 관리하는가’라는 질문에 답합니다.
멀티 에이전트 시스템이 필요한 이유
솔직히 말하면 단일 Agent의 가장 큰 문제는 ‘사용할 수 있는가’가 아니라 ‘얼마나 오래 사용할 수 있는가’입니다.
이런 경험이 있지 않나요? 처음에는 코드를 잘 작성하던 Agent가 갑자기 엉뚱한 내용을 출력하기 시작합니다. 분명 A만 물었는데 B와 C를 거쳐 결국 Z까지 끌어오기도 합니다. Agent가 ‘멍청해서’가 아닙니다. 컨텍스트 창이 한계를 넘었기 때문입니다.
단일 Agent에는 세 가지 치명적인 약점이 있습니다.
컨텍스트 한계. 아무리 강력한 Agent라도 200k token의 컨텍스트는 유한합니다. 코드 리뷰, 보안 분석, 성능 최적화를 동시에 맡기면 절반이나 기억해도 다행입니다. 같은 대화에서 20번째 턴까지 Python을 이야기하다가 21번째 턴부터 JavaScript를 출력하는 Agent를 본 적이 있습니다. 자신이 무엇을 해야 하는지 완전히 잊은 것입니다.
분산된 역량. 하나의 Agent에 기능을 많이 넣을수록 무엇이든 조금씩 하지만 어느 하나도 잘하지 못하는 ‘만능형’이 됩니다. 코드 리뷰를 시키면 단위 테스트를 작성하고, 문서를 시키면 코드까지 리팩터링할 수 있습니다. 방향 감각은 기대하기 어렵습니다.
어려운 디버깅. Agent 하나가 고장 나면 어느 단계에서 문제가 생겼는지 알기 어렵습니다. 프롬프트가 너무 길었는지, 도구 호출이 실패했는지, 컨텍스트가 오염됐는지 찾아내는 일은 건초더미에서 바늘 찾기와 같습니다.
멀티 에이전트 시스템은 쉽게 말해 AI 세계의 ‘마이크로서비스 아키텍처’입니다. 각 Agent는 한 가지 일을 맡아 그 일에 집중합니다. 모든 것을 하나의 ‘슈퍼 Agent’에 몰아넣는 대신 명확한 메시지를 주고받으며 협업합니다.
Google, LangChain, Anthropic 모두 이 접근법을 발전시키고 있습니다. O’Reilly 보고서에 따르면 2025년 Agent 관련 논문은 연초 820편에서 2,500편 이상으로 늘어 세 배가 됐습니다. 이유는 간단합니다. 하나의 Agent로 모든 일을 해결하는 시대가 끝났다는 사실을 모두가 깨달았기 때문입니다.
네 가지 핵심 아키텍처 패턴
LangChain과 Google은 몇 가지 대표적인 멀티 에이전트 아키텍처를 정리했습니다. 여러 프로젝트에서 직접 사용해 보니 각 패턴에는 분명히 맞는 상황이 있었습니다. 잘못 선택하면 ‘모기를 잡는 데 대포를 쓰거나 젓가락으로 국을 먹는’ 셈이 됩니다.
Subagents(하위 에이전트) - 중앙 오케스트레이션 패턴
가장 직관적인 패턴입니다. 하나의 ‘메인 Agent’가 지휘관이 되어 여러 ‘하위 Agent’를 거느립니다. 하위 Agent는 메인 Agent의 도구이며, 메인 Agent가 누구를 언제 호출할지 결정합니다.
사용자 요청 → 메인 Agent(코디네이터) → 하위 Agent A/B/C에 분배 → 결과 종합 → 사용자에게 반환
언제 사용하나요? 작업이 서로 독립된 여러 도메인에 걸쳐 있을 때 사용합니다. 고객 지원 시스템을 예로 들면 한 하위 Agent는 주문 조회, 다른 Agent는 환불, 또 다른 Agent는 불만 처리를 담당합니다. 각 도메인은 자체 지식 베이스와 도구를 갖고, 메인 Agent는 ‘분배’만 담당합니다.
코드 예제(LangGraph):
from langgraph.prebuilt import create_react_agent
# 하위 Agent 정의
order_agent = create_react_agent(
model="claude-3-5-sonnet-20241022",
tools=[query_order, update_order],
prompt="주문 전문가입니다. 주문 관련 문제만 처리하세요."
)
refund_agent = create_react_agent(
model="claude-3-5-sonnet-20241022",
tools=[check_refund_policy, process_refund],
prompt="환불 전문가입니다. 환불 관련 문제만 처리하세요."
)
# 메인 Agent가 하위 Agent를 도구로 보유
main_agent = create_react_agent(
model="claude-3-5-sonnet-20241022",
tools=[order_agent, refund_agent], # 하위 Agent가 곧 도구
prompt="고객 지원 총괄입니다. 사용자 질문을 적절한 전문가에게 분배하세요."
)
장점: 컨텍스트가 깔끔하게 격리되어 각 하위 Agent는 자신에게 필요한 내용만 봅니다. 병렬 실행 효율도 높습니다.
단점: 하위 Agent마다 독립적으로 LLM을 호출하므로 token 소비가 큽니다. 하위 Agent끼리 상태를 공유하려면 우회 과정도 필요합니다.
Skills(스킬) - 필요할 때 로드하는 패턴
하나의 Agent가 여러 ‘역할’을 갖는 방식입니다. Skills는 본질적으로 동적으로 로드하는 프롬프트 템플릿입니다. Agent는 작업에 따라 ‘정체성’을 바꾸지만 항상 같은 Agent입니다.
사용자 요청 → 단일 Agent → '코드 리뷰' Skill 로드 → 실행 → '문서 생성' Skill 로드 → 실행
언제 사용하나요? 작업을 ‘단일 스레드’로 처리하되 단계마다 서로 다른 전문 지식이 필요할 때 적합합니다. 프로그래밍 도우미라면 코드를 작성할 때는 ‘개발자’ 패턴을, 문서를 작성할 때는 ‘기술 작가’ 패턴을 사용할 수 있습니다.
코드 예제:
# Skills 디렉터리 구조
skills/
├── code_review.md # 코드 리뷰 프롬프트
├── doc_writer.md # 문서 생성 프롬프트
└── security_audit.md # 보안 감사 프롬프트
# Skill 동적 로드
def load_skill(skill_name: str) -> str:
with open(f"skills/{skill_name}.md") as f:
return f.read()
# 사용 예제
agent = create_react_agent(
model="claude-3-5-sonnet-20241022",
tools=[...],
prompt=load_skill("code_review") # 런타임에 전환
)
장점: 가볍고 추가적인 Agent 조정 비용이 없습니다. Subagents보다 token 소비가 적습니다.
단점: 컨텍스트가 누적됩니다. Skill을 10번 전환해도 앞서 사용한 9개 Skill의 내용이 컨텍스트에 남아 갈수록 복잡해집니다.
Handoffs(인계) - 상태 기반 패턴
Agent끼리 공을 넘기듯 작업을 인계합니다. Agent A가 작업을 마친 뒤 상태를 Agent B에게 ‘넘기면’ Agent B가 이어서 처리합니다. 이어달리기와 비슷합니다.
사용자 요청 → Agent A(정보 수집) → 인계 → Agent B(문제 분석) → 인계 → Agent C(해결책 제시)
언제 사용하나요? 다단계 대화에 적합합니다. 기술 지원 흐름이라면 문제 수집 → 문제 진단 → 해결책 제시 → 해결 확인의 순서로 진행됩니다. 단계마다 서로 다른 전문 지식이 필요할 수 있습니다.
코드 예제:
from langchain_core.tools import tool
# 인계 도구 정의
@tool
def handoff_to_diagnosis(issue_summary: str) -> str:
"""문제를 진단 전문가에게 인계합니다."""
return f"문제를 접수했습니다: {issue_summary}. 진단을 시작합니다..."
@tool
def handoff_to_solution(diagnosis_result: str) -> str:
"""진단 결과를 해결책 전문가에게 인계합니다."""
return f"진단 결과를 바탕으로 해결책을 마련하고 있습니다: {diagnosis_result}"
# Agent 체인
triage_agent = create_react_agent(
tools=[handoff_to_diagnosis],
prompt="문제 분류 담당자입니다. 사용자 문제를 수집해 진단 전문가에게 인계하세요."
)
diagnosis_agent = create_react_agent(
tools=[handoff_to_solution],
prompt="진단 전문가입니다. 문제의 근본 원인을 분석해 해결책 전문가에게 인계하세요."
)
장점: 대화 흐름이 자연스럽고 사람이 협업하는 방식과 잘 맞습니다. 각 Agent는 현재 단계에만 집중합니다.
단점: 상태 관리가 복잡합니다. Agent A가 Agent B에 전달하는 데이터 형식이 정확하지 않으면 전체 체인이 끊어집니다.
Router(라우터) - 병렬 분배 패턴
하나의 ‘라우터 Agent’가 요청을 분석한 뒤 여러 전문 Agent를 병렬로 호출하고 마지막에 결과를 종합합니다.
사용자 요청 → Router(분류) → Agent A/B/C 병렬 호출 → 결과 종합 → 사용자에게 반환
언제 사용하나요? 하나의 요청이 여러 데이터 소스를 조회해야 할 때 사용합니다. 기업 지식 베이스 질의응답을 예로 들면 Router가 질문 유형을 판단하고 내부 문서, 외부 API, 데이터베이스를 병렬로 조회한 뒤 최종 답변을 종합합니다.
코드 예제:
from langgraph.graph import StateGraph
# 병렬 실행 노드 정의
async def query_internal_docs(state):
# 내부 문서 조회
return {"internal_results": [...]}
async def query_external_api(state):
# 외부 API 조회
return {"external_results": [...]}
async def query_database(state):
# 데이터베이스 조회
return {"db_results": [...]}
async def synthesize(state):
# 모든 결과 종합
all_results = state["internal_results"] + state["external_results"] + state["db_results"]
return {"final_answer": summarize(all_results)}
# 병렬 그래프 구축
graph = StateGraph(State)
graph.add_node("internal", query_internal_docs)
graph.add_node("external", query_external_api)
graph.add_node("database", query_database)
graph.add_node("synthesize", synthesize)
# 병렬 실행
graph.add_edge("router", ["internal", "external", "database"])
graph.add_edge(["internal", "external", "database"], "synthesize")
장점: 병렬로 실행하므로 가장 빠릅니다. 상태가 없고 각 조회가 독립적입니다.
단점: 다회차 대화에는 적합하지 않습니다. 요청마다 새로 시작하며 Agent는 이전 대화 내용을 기억하지 못합니다.
아키텍처 선택 의사결정 프레임워크
그렇다면 어떤 패턴을 선택해야 할까요? 간단한 의사결정 흐름을 그려 봤습니다.
필요한 것은 무엇인가요?
│
├─→ 독립된 여러 도메인을 병렬 처리해야 하나요?
│ │
│ └─→ Subagents(중앙 오케스트레이션)
│
├─→ 단일 Agent가 여러 단계에서 스킬을 전환하나요?
│ │
│ └─→ Skills(필요할 때 로드)
│
├─→ 순차 워크플로에서 차례로 넘겨야 하나요?
│ │
│ └─→ Handoffs(상태 기반)
│
└─→ 여러 데이터 소스의 조회 결과를 종합해야 하나요?
│
└─→ Router(병렬 분배)
흐름만 봐서는 충분히 직관적이지 않을 수 있으므로 비교표로 정리했습니다.
| 패턴 | 분산 개발 | 병렬화 | 다중 홉 대화 | 사용자와 직접 상호작용 | Token 소비 |
|---|---|---|---|---|---|
| Subagents | 높음 | 높음 | 높음 | 낮음 | 높음 |
| Skills | 높음 | 중간 | 높음 | 높음 | 낮음 |
| Handoffs | 없음 | 없음 | 높음 | 높음 | 중간 |
| Router | 중간 | 높음 | 없음 | 중간 | 높음 |
이 표는 어떻게 읽어야 할까요?
- 분산 개발: 팀이 서로 다른 모듈을 나눠 개발하나요? 그렇다면 Subagents와 Skills가 모두 적합하며, 구성원마다 하나의 하위 Agent 또는 Skill을 맡을 수 있습니다.
- 병렬화: 속도가 중요한가요? Router와 Subagents는 여러 Agent를 병렬로 실행할 수 있어 가장 효율적입니다.
- 다중 홉 대화: 사용자가 여러 차례 상호작용해야 하나요? Handoffs와 Skills는 자연스럽게 대화 흐름을 지원합니다.
- 사용자와 직접 상호작용: 사용자가 하위 Agent와 직접 대화하나요? Skills와 Handoffs는 지원하지만 Router는 지원하지 않습니다.
- Token 소비: 비용에 민감하다면 Skills가 가장 경제적이고 Router와 Subagents의 비용이 가장 큽니다.
제 경험으로는 단순하게 시작하는 것이 좋습니다. Skills 또는 Handoffs로 먼저 MVP를 완성하고, 병목을 발견한 뒤 Subagents나 Router로 확장하세요. 처음부터 분산 아키텍처를 만들 필요는 없습니다. 과도한 설계가 얼마나 고통스러운지 저도 잘 압니다.
프로덕션급 구현의 핵심
Demo에서 프로덕션까지는 태평양만큼 먼 거리가 있습니다. 아래 문제들은 제가 모두 직접 겪었습니다.
상태 관리
여러 Agent가 상태를 공유할 때 가장 쉽게 생기는 문제는 ‘경쟁 상태’입니다. 두 Agent가 동시에 같은 변수를 쓰면 마지막에 어느 값이 남을까요?
LangGraph는 output_key로 이 문제를 해결합니다. 각 Agent가 자신의 전용 키에만 쓰도록 하는 방식입니다.
from langgraph.graph import StateGraph, MessagesState
class GraphState(MessagesState):
security_result: str = "" # 보안 Agent 전용
style_result: str = "" # 스타일 Agent 전용
perf_result: str = "" # 성능 Agent 전용
# 보안 Agent는 security_result에만 쓰기
async def security_agent(state: GraphState):
result = await analyze_security(state["messages"])
return {"security_result": result} # 이 키 하나에만 쓰기
# 스타일 Agent는 style_result에만 쓰기
async def style_agent(state: GraphState):
result = await analyze_style(state["messages"])
return {"style_result": result}
이렇게 하면 병렬이든 직렬이든 각 Agent가 자신의 영역만 다루므로 서로 간섭하지 않습니다.
또 하나의 흔한 문제는 ‘컨텍스트 오염’입니다. Agent A의 출력을 Agent B가 읽지만 B에게는 그 정보가 전혀 필요하지 않을 수 있습니다. 저는 상태에 relevant_keys 필드를 추가해 각 Agent가 필요한 키만 읽도록 합니다.
성능 최적화
멀티 Agent 시스템의 token 소비는 끝없는 구덩이와 같습니다. token을 아끼는 몇 가지 방법을 소개합니다.
1. 여러 도메인에서는 Subagents가 Skills보다 token을 67% 절약
LangChain의 테스트 결과에 따르면 하나의 작업이 독립된 세 도메인에 걸쳐 있을 때 Subagents의 token 소비는 Skills의 3분의 1입니다. 이유는 Subagents가 컨텍스트를 격리해 각 하위 Agent가 자신의 도메인 내용만 보기 때문입니다. Skills에서는 모든 Skill의 컨텍스트가 함께 누적되어 갈수록 커집니다.
2. 상태 저장 패턴으로 반복 호출 40~50% 절약
같은 질문을 10번 하는 것처럼 반복 조회가 많은 작업에서는 상태를 유지하는 Handoffs 패턴을 사용하면 Agent가 이전 답변을 기억할 수 있습니다. LangChain 데이터에 따르면 상태 저장 방식은 무상태 방식보다 LLM 호출을 거의 절반까지 줄입니다.
3. 성찰 패턴의 반복 횟수 제한
많은 사람이 Agent에 ‘성찰’ 기능을 추가합니다. 스스로 출력을 확인하고 문제를 찾아 다시 생성하게 하는 기능입니다. 유용하지만 무한 루프에 빠지기 쉽습니다. 저는 보통 max_iterations=2 또는 3으로 제한하고, 이를 넘으면 강제로 종료합니다.
from langgraph.checkpoint.memory import MemorySaver
# 최대 반복 횟수 설정
graph = create_react_agent(
model="claude-3-5-sonnet-20241022",
tools=[...],
checkpointer=MemorySaver(),
config={"configurable": {"max_iterations": 3}} # 최대 3회 성찰
)
흔히 겪는 문제
무한 루프: Agent가 자신을 호출하고, 다시 자신을 호출하고, 또 자신을 호출하며 끝없이 반복됩니다. 해결 방법은 max_iterations와 명확한 종료 조건을 설정하는 것입니다.
def should_continue(state):
if state["iteration_count"] >= 3:
return "end"
if "done" in state["messages"][-1].content:
return "end"
return "continue"
컨텍스트 팽창: Agent가 갈수록 ‘둔해지고’ 출력도 점점 짧아집니다. 대부분 컨텍스트에 너무 많은 내용을 넣었기 때문입니다. Blackboard 패턴(공유 칠판)을 사용해 필요한 컨텍스트만 유지하고 주기적으로 정리하면 해결할 수 있습니다.
조정 비용: Agent 수가 늘면 통신 비용은 기하급수적으로 증가합니다. 제가 테스트한 한 시스템은 Agent를 3개에서 10개로 늘리자 응답 시간이 2초에서 15초로 증가했습니다. 역할이 비슷한 Agent를 합치고 전체 Agent 수를 5개 이하로 유지하는 것이 해결책입니다.
전체 구현 예제
이론은 충분히 살펴봤으니 실제 예제를 보겠습니다. Router + ParallelAgent 패턴으로 코드 리뷰 멀티 에이전트 시스템을 만들었습니다.
아키텍처: Router가 코드 언어와 유형을 판단 → 보안 감사, 스타일 검사, 성능 분석 Agent 세 개를 병렬 호출 → 결과를 종합해 보고서 출력.
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langchain_anthropic import ChatAnthropic
# 상태 정의
class CodeReviewState(TypedDict):
code: str
language: str
security_issues: list
style_issues: list
perf_issues: list
final_report: str
# LLM 초기화
llm = ChatAnthropic(model="claude-3-5-sonnet-20241022")
# Router: 언어 판별
async def route_code(state: CodeReviewState) -> dict:
code = state["code"]
# 단순 판별이며 실제로는 LLM 분류를 사용할 수 있음
if "def " in code or "import " in code:
language = "python"
elif "function" in code or "const " in code:
language = "javascript"
else:
language = "unknown"
return {"language": language}
# 보안 감사 Agent
async def security_audit(state: CodeReviewState) -> dict:
code = state["code"]
prompt = f"""보안 감사 전문가입니다. 다음 코드의 보안 문제를 검사하세요:
- SQL 인젝션 위험
- XSS 취약점
- 민감 정보 노출
- 안전하지 않은 의존성
코드:
{code}
문제를 JSON 목록으로 출력하고 각 항목에 line(줄 번호), severity(심각도), description(설명)을 포함하세요.
"""
response = await llm.ainvoke(prompt)
# 결과 파싱...
return {"security_issues": []}
# 스타일 검사 Agent
async def style_check(state: CodeReviewState) -> dict:
code = state["code"]
language = state["language"]
prompt = f"""코드 스타일 전문가입니다. 다음 {language} 코드의 스타일 문제를 검사하세요:
- 명명 규칙
- 코드 형식
- 주석 완성도
코드:
{code}
문제를 JSON 목록으로 출력하세요.
"""
response = await llm.ainvoke(prompt)
return {"style_issues": []}
# 성능 분석 Agent
async def perf_analysis(state: CodeReviewState) -> dict:
code = state["code"]
prompt = f"""성능 분석 전문가입니다. 다음 코드의 성능 문제를 검사하세요:
- 지나치게 높은 시간 복잡도
- 불필요한 반복문
- 메모리 누수 위험
코드:
{code}
문제를 JSON 목록으로 출력하세요.
"""
response = await llm.ainvoke(prompt)
return {"perf_issues": []}
# 종합 보고서
async def generate_report(state: CodeReviewState) -> dict:
security = state.get("security_issues", [])
style = state.get("style_issues", [])
perf = state.get("perf_issues", [])
total_issues = len(security) + len(style) + len(perf)
report = f"""# 코드 리뷰 보고서
## 개요
- 언어: {state['language']}
- 전체 문제 수: {total_issues}
## 보안 문제 ({len(security)}개)
{format_issues(security)}
## 스타일 문제 ({len(style)}개)
{format_issues(style)}
## 성능 문제 ({len(perf)}개)
{format_issues(perf)}
## 제안
위 분석 결과에 따라 보안 문제를 먼저 수정하는 것이 좋습니다...
"""
return {"final_report": report}
# 그래프 구축
graph = StateGraph(CodeReviewState)
graph.add_node("router", route_code)
graph.add_node("security", security_audit)
graph.add_node("style", style_check)
graph.add_node("perf", perf_analysis)
graph.add_node("report", generate_report)
# 흐름: Router → 세 검사 병렬 실행 → 보고서 생성
graph.set_entry_point("router")
graph.add_edge("router", "security")
graph.add_edge("router", "style")
graph.add_edge("router", "perf")
graph.add_edge("security", "report")
graph.add_edge("style", "report")
graph.add_edge("perf", "report")
graph.add_edge("report", END)
# 컴파일
app = graph.compile()
# 사용
async def review_code(code: str):
result = await app.ainvoke({"code": code})
return result["final_report"]
이 예제를 실행하면 100줄 분량의 코드에 대해 세 Agent가 병렬로 동작해 약 3~5초 만에 결과를 냅니다. 직렬로 실행하면 최소 10초가 걸립니다.
물론 이는 기본 버전에 불과합니다. 프로덕션 환경에서는 캐시(같은 코드를 반복해서 검토하지 않음), 증분 리뷰(변경된 부분만 확인), 사람의 피드백(사용자가 오탐을 표시)을 추가해야 합니다. 하지만 이런 확장 기능은 모두 이 아키텍처를 기반으로 구현할 수 있습니다.
결론
지금까지 내용을 세 문장으로 정리할 수 있습니다.
기본 원리: 프레임워크 선택보다 패턴 선택이 중요합니다. LangGraph, AutoGen, CrewAI는 모두 좋은 도구지만 Handoffs가 필요한 문제에 Router 패턴을 사용한다면 아무리 좋은 프레임워크도 해결해 주지 못합니다.
중간 전략: 단순하게 시작해 점진적으로 확장하세요. Skills 또는 Handoffs의 MVP를 먼저 완성하고 병목이 발견되면 Subagents나 Router를 검토합니다. 과도한 설계가 가장 큰 함정입니다. 저도 겪었으니 같은 실수를 반복하지 마세요.
최종 구현: 프로덕션 환경에서는 상태 관리, 성능, 비용에 집중해야 합니다. Token 소비, 무한 루프, 컨텍스트 오염이라는 세 가지 문제를 해결하면 멀티 Agent 시스템을 안정적으로 운영할 수 있습니다.
다음 단계는 LangGraph 문서를 열고 패턴 하나를 선택해 50줄의 코드로 가장 간단한 멀티 에이전트 시스템을 구현하는 것입니다. 너무 고민하지 말고 먼저 실행해 보세요.
멀티 에이전트 협업 시스템 구축
코드 리뷰 멀티 에이전트 시스템을 처음부터 구축합니다.
- 1
Step 1: 아키텍처 패턴 선택
작업 특성에 맞는 아키텍처 패턴을 선택합니다. - 2
Step 2: 상태 구조 정의
TypedDict로 여러 Agent가 공유할 상태를 정의합니다. - 3
Step 3: Agent 노드 생성
각 Agent에 독립적인 노드 함수를 만듭니다. - 4
Step 4: 실행 그래프 구축
LangGraph StateGraph로 실행 흐름을 구성합니다. - 5
Step 5: 상태 관리 추가
output_key로 경쟁 상태를 방지합니다.
FAQ
Subagents와 Skills는 무엇이 다른가요?
Handoffs 패턴은 언제 사용해야 하나요?
멀티 Agent 시스템에서 경쟁 상태를 어떻게 방지하나요?
멀티 Agent 시스템의 token 소비는 어떻게 제어하나요?
Router 패턴은 어떤 상황에 적합한가요?
Agent가 무한 루프에 빠지는 것을 어떻게 막나요?
4분 읽기 · 게시일: 2026년 3월 25일 · 수정일: 2026년 9월 8일
AI Agent 엔지니어링 가이드
검색으로 들어왔다면 같은 시리즈의 이전 글이나 다음 글로 이동하는 것이 가장 빠릅니다.
이전
Computer-Use Agent: AI가 컴퓨터를 직접 조작하는 시대
Claude Computer Use 기술을 원리부터 실전까지 깊이 있게 설명합니다. Docker 배포, 코드 예제, 경쟁 제품 분석, 보안 모범 사례를 통해 AI 데스크톱 자동화의 최신 기술을 익힐 수 있습니다.
14편 중 6편
다음
Agent의 계획 능력은 어떻게 평가할까? 추론 깊이, 작업 분해, 자기 교정 실전 평가
Agent의 계획 능력은 어떻게 평가할까요? 이 글에서는 추론 깊이, 작업 분해, 자기 교정 평가 방법론을 설명하고 AgentBench, ToolBench, ACPBench 등 주요 benchmark를 비교해 실전 평가 가이드를 제공합니다.
14편 중 8편



댓글
GitHub로 로그인하여 댓글을 남기세요