이종관
글 목록으로

LangGraph 에이전트 오케스트레이션: StateGraph 기반 멀티에이전트 시스템 설계

LangGraph StateGraph 기반 멀티에이전트 오케스트레이션과 Durable Execution 설계

2026년 2월 21일·21 min read·
agent
langgraph
orchestration
state-management
workflow
durable-execution

왜 오케스트레이션이 필요한가

멀티에이전트 시스템에서 개별 에이전트의 추론 능력만큼 중요한 것이 에이전트 간 통신, 상태 관리, 실행 흐름 제어다. 9개 에이전트가 순차 파이프라인으로 연결된 단순한 for-loop 구조는 다음과 같은 근본적인 한계를 가진다.

한계설명결과
장애 복구 불가7번째 단계에서 오류 시 처음부터 재실행불필요한 API 호출, 비용 낭비
병렬 실행 불가독립적인 분석 단계도 순차 대기총 지연 시간 증가
조건 분기 불가데이터 품질 불량 시에도 전체 실행오염된 데이터로 의사결정
상태 추적 부재"어디까지 진행됐는가" 기록 없음디버깅, 감사 불가
사람 개입 불가고위험 결정에서 승인 절차 없음자동화의 위험 노출

LangGraph는 이 모든 문제를 그래프 기반 상태기계(StateGraph) 로 해결한다.


LangGraph 핵심 개념

StateGraph: 그래프 기반 워크플로우

LangGraph는 에이전트 워크플로우를 상태 기반의 제어된 실행 그래프(Stateful, controlled execution graph) 로 모델링한다. 노드(Node)는 각 에이전트의 실행 단위이고, 엣지(Edge)는 상태 전이를 정의한다.

python
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.postgres import PostgresSaver
 
class PipelineState(TypedDict):
    project_id: str
    market: str
    config: dict
    scan_results: list[ScanResult]
    news_items: list[NewsItem]
    position_alerts: list[PositionAlert]
    signals: list[Signal]
    debate_result: dict | None
    final_decision: dict | None
    errors: list[str]
 
graph = StateGraph(PipelineState)

PipelineState는 전체 워크플로우의 공유 상태다. 각 노드는 이 상태를 읽고 업데이트하며, 체크포인터가 매 단계마다 스냅샷을 저장한다.

핵심 구성 요소

구성 요소역할비유
Node에이전트 실행 단위 (함수)공장의 작업 스테이션
Edge노드 간 상태 전이컨베이어 벨트
Conditional Edge조건에 따른 분기품질 검사 분기점
State공유 상태 (TypedDict)작업 지시서
Checkpointer매 노드 완료 시 상태 저장세이브 포인트
Thread실행 인스턴스 식별자작업 주문번호

StateGraph DAG 설계: 트레이딩 파이프라인

Sense-Think-Act 3계층 매핑

9개 에이전트를 Sense-Think-Act 3계층으로 분리하고, LangGraph의 StateGraph로 DAG를 구성한다.

그래프 정의 코드

python
graph = StateGraph(PipelineState)
 
# --- Sense Layer ---
graph.add_node("data_quality_gate", data_quality_gate)
graph.add_node("volume_scanner", volume_scanner)
graph.add_node("news_collector", news_collector)
graph.add_node("position_sensor", position_sensor)
 
# --- Think Layer (Fan-out / Fan-in) ---
graph.add_node("quant_analyst", quant_analyst)
graph.add_node("llm_analyst", llm_analyst)
graph.add_node("sector_rotation", sector_rotation)
graph.add_node("analysis_merge", merge_analysis_results)
graph.add_node("bull_bear_debate", bull_bear_debate)
graph.add_node("ensemble_voter", ensemble_voter)
 
# --- Act Layer ---
graph.add_node("risk_sentinel", risk_sentinel)
graph.add_node("trade_executor", trade_executor)
 
# 엣지 정의
graph.set_entry_point("data_quality_gate")
 
# Data Quality Gate: 조건부 분기
graph.add_conditional_edges(
    "data_quality_gate",
    lambda s: "continue" if not s["errors"] else "end",
    {"continue": "volume_scanner", "end": END},
)
 
# Sense Layer 순차 실행
graph.add_edge("volume_scanner", "news_collector")
graph.add_edge("news_collector", "position_sensor")
 
# Fan-out: 병렬 분석
graph.add_edge("position_sensor", "quant_analyst")
graph.add_edge("position_sensor", "llm_analyst")
graph.add_edge("position_sensor", "sector_rotation")
 
# Fan-in: 결과 합류
graph.add_edge("quant_analyst", "analysis_merge")
graph.add_edge("llm_analyst", "analysis_merge")
graph.add_edge("sector_rotation", "analysis_merge")
 
# Think Layer 후반
graph.add_edge("analysis_merge", "bull_bear_debate")
graph.add_edge("bull_bear_debate", "ensemble_voter")
graph.add_edge("ensemble_voter", "risk_sentinel")
 
# Risk Sentinel: 조건부 분기
graph.add_conditional_edges(
    "risk_sentinel",
    lambda s: "execute" if s["final_decision"].get("approved") else "end",
    {"execute": "trade_executor", "end": END},
)
graph.add_edge("trade_executor", END)

Fan-out / Fan-in 병렬 처리

왜 병렬이 중요한가

의사결정 루프에서 Quant Analyst(p95 < 300ms), Sector Rotation(p95 < 300ms), LLM Analyst(p95 < 8s)는 서로 독립적이다. 순차 실행하면 총 8.6초 이상 소요되지만, 병렬 실행하면 가장 느린 LLM Analyst 기준 8초로 수렴한다.

LangGraph의 Fan-out 동작 방식

LangGraph에서 하나의 노드가 여러 노드로 엣지를 가지면 자동으로 Fan-out(병렬 분기) 된다. Fan-in은 여러 노드가 동일한 다음 노드를 가리킬 때 발생하며, 모든 선행 노드가 완료될 때까지 대기한다.

python
# position_sensor -> [quant, llm, sector] : Fan-out
graph.add_edge("position_sensor", "quant_analyst")
graph.add_edge("position_sensor", "llm_analyst")
graph.add_edge("position_sensor", "sector_rotation")
 
# [quant, llm, sector] -> analysis_merge : Fan-in
graph.add_edge("quant_analyst", "analysis_merge")
graph.add_edge("llm_analyst", "analysis_merge")
graph.add_edge("sector_rotation", "analysis_merge")

analysis_merge 노드는 세 에이전트의 출력을 하나의 통합 리포트로 합친다. 상태(State) 내에 각 에이전트의 결과가 축적되므로, 합류 노드에서 모든 결과를 읽을 수 있다.


체크포인팅과 내구 실행(Durable Execution)

체크포인팅이란

LangGraph의 체크포인터는 매 super-step(노드 실행 완료)마다 전체 상태의 스냅샷을 저장한다. 이를 통해 다음이 가능해진다.

기능설명
Fault Tolerance장애 발생 시 마지막 체크포인트부터 재개
Human-in-the-Loop특정 단계에서 실행을 중단하고 사람의 승인을 기다림
Time Travel이전 상태로 되돌아가 "만약 다르게 판단했다면?" 시뮬레이션
Audit Trail각 단계별 상태가 기록되어 의사결정 추적 가능

PostgreSQL 기반 체크포인터

python
from langgraph.checkpoint.postgres import PostgresSaver
 
checkpointer = PostgresSaver.from_conn_string(DATABASE_URL)
app = graph.compile(checkpointer=checkpointer)
 
# 실행
result = await app.ainvoke(
    initial_state,
    config={"configurable": {"thread_id": "pipeline-run-uuid"}}
)

thread_id가 체크포인트 조회의 기본 키다. 동일한 thread_id로 재실행하면 마지막 체크포인트 이후 단계부터 자동으로 재개된다.

재시작 시퀀스

Durable Execution 원칙

Durable Execution은 LangGraph가 제공하는 핵심 패턴으로, 다음 원칙을 따른다.

원칙트레이딩 적용
DeterministicRisk Sentinel까지는 동일 입력에 동일 출력 보장
Idempotent주문 제출은 idempotency_key로 중복 방지
Side Effect 격리주문 제출(외부 API 호출)은 task로 래핑

트레이딩에서 "정확히 한 번 실행(exactly-once)"은 브로커/거래소 경계 때문에 완벽하게 보장하기 어렵다. 따라서 idempotency_key를 주문 단위로 부여하고, 재시작 시 동일 키의 주문이 이미 제출되었는지 확인하는 멱등성 검사가 필수다.


Human-in-the-Loop

왜 사람 개입이 필요한가

자동매매에서 특정 상황은 기계적 판단보다 사람의 확인이 필요하다.

  • 일 손실 한도 근접 시 추가 거래
  • 시장 레짐 급변 (VIX 급등, 블랙 스완 이벤트)
  • 뉴스 신뢰도가 매우 낮은 상태에서의 대규모 매수
  • 새로운 전략/프롬프트 변경 직후 첫 실거래

LangGraph의 Human-in-the-Loop 구현

Risk Sentinel의 출력에 requires_human_approval 플래그를 포함시키고, LangGraph의 interrupt 기능으로 실행을 중단한다.

python
def risk_sentinel(state: PipelineState) -> PipelineState:
    intent = state["final_decision"]
    portfolio = get_portfolio_snapshot(state["project_id"])
 
    decision = evaluate_risk(intent, portfolio)
 
    if decision.requires_human_approval:
        # LangGraph interrupt: 실행 중단, 사람 승인 대기
        raise NodeInterrupt(
            f"고위험 거래 감지: {decision.reasons}"
        )
 
    state["final_decision"]["approved"] = decision.approved
    return state

사용자가 승인하면 동일 thread_id로 재실행하여 중단된 지점부터 계속 진행한다. 체크포인트 덕분에 이전 단계를 다시 실행할 필요가 없다.


조건부 엣지(Conditional Edge)를 활용한 분기

Data Quality Gate

파이프라인 진입점에서 데이터 품질을 검증하고, 기준 미달 시 전체 실행을 중단한다.

python
graph.add_conditional_edges(
    "data_quality_gate",
    lambda s: "continue" if not s["errors"] else "end",
    {"continue": "volume_scanner", "end": END},
)

Data Quality Gate 체크리스트:

체크 항목기준실패 시
API 응답 시간p95 < 3초재시도 3회 후 중단
시세 데이터 최신성현재 시각 - 데이터 시각 < 5분경고, 10분 초과 시 중단
가격 이상치전일 종가 대비 30% 이내스플릿/권리락 확인
필수 종목 누락유니버스 90% 이상 조회 성공미달 시 중단
뉴스 API 가용성최소 1개 소스 응답전체 불응답 시 뉴스 없이 진행

Risk Sentinel 분기

리스크 판정 결과에 따라 실행(execute) 또는 종료(end)로 분기한다.

python
graph.add_conditional_edges(
    "risk_sentinel",
    lambda s: "execute" if s["final_decision"].get("approved") else "end",
    {"execute": "trade_executor", "end": END},
)

Risk Sentinel의 판정은 5가지 결과를 가진다.

판정의미후속 동작
APPROVE원안 승인Trade Executor로 전달
RESIZE사이즈 조정 후 승인조정된 Intent로 실행
HOLD조건부 보류조건 충족 시 재평가
REJECT거부로그 기록 후 종료
KILL긴급 중단모든 미체결 취소

이벤트 소스 기반 상태 지속성

3중 저장 구조

트레이딩 시스템의 상태 지속성은 3중 구조로 설계한다.

저장소성격역할
Kafka불변(append-only)모든 이벤트 기록, 재생(replay) 가능, 감사 추적
Redis가변(TTL 기반)실시간 캐시, Pub/Sub, Rate Limit, 에이전트 가중치
PostgreSQL영구 저장LangGraph 체크포인트, 거래 이력, Reflection 메모

이벤트 Envelope 스키마

모든 에이전트 간 메시지는 공통 Envelope로 표준화한다.

json
{
  "event_id": "uuid-v7",
  "ts": "2026-02-21T09:15:00.123+09:00",
  "event_type": "QUANT_DONE",
  "correlation_id": "pipeline-run-uuid",
  "project_id": "project-uuid",
  "agent": "quant_analyst",
  "payload": {
    "symbol": "005930",
    "signal": 0.72,
    "confidence": 0.68,
    "feature_vector": { "rsi_14": 32.5, "macd_signal": 0.003 }
  },
  "schema_version": "v2",
  "idempotency_key": "uuid-for-dedup"
}

idempotency_keycorrelation_id가 핵심이다. 전자는 중복 처리 방지, 후자는 하나의 파이프라인 실행에 속한 모든 이벤트를 추적하는 데 사용된다.


LangGraph vs AutoGen 비교

프레임워크 특성 비교

비교 항목LangGraphAutoGen
모델링 방식그래프/상태기계이벤트 기반 대화
실행 흐름DAG로 명시적 정의에이전트 간 메시징
상태 관리TypedDict 공유 상태대화 히스토리
체크포인팅내장 (PostgreSQL, SQLite)외부 구현 필요
Durable Execution네이티브 지원미지원
Human-in-the-Loopinterrupt 내장UserProxyAgent
병렬 실행Fan-out/Fan-in 내장Teams/GroupChat
디버깅Time Travel (상태 되감기)대화 로그

TradingAgents 프레임워크

TradingAgents는 실제 트레이딩 조직을 모사한 멀티에이전트 구조를 제안한다. 7가지 역할 (Fundamental Analyst, Sentiment Analyst, News Analyst, Technical Analyst, Bull/Bear Researcher, Trader, Risk Manager)이 5단계 파이프라인으로 협업한다.

plaintext
Analyst Team  ->  Researcher Team  ->  Trader  ->  Risk Team  ->  Fund Manager
(4명 병렬)        (Bull/Bear 토론)     (종합)      (3관점 토론)    (최종 승인)

Q1 2024 백테스트에서 AAPL 누적수익률 26.62%(Sharpe 8.21), GOOGL 24.36%(Sharpe 6.39), AMZN 23.21%(Sharpe 5.60)을 기록했다. 다만 3종목/3개월이라는 제한된 범위에 주의가 필요하다.

어떤 프레임워크를 선택할 것인가

트레이딩 시스템에서는 LangGraph가 더 적합하다. 이유는 (1) 체크포인팅으로 장애 복구가 가능하고, (2) Conditional Edge로 리스크 게이트를 자연스럽게 모델링할 수 있으며, (3) Human-in-the-Loop가 내장되어 있고, (4) Time Travel로 "다른 판단을 했다면?"을 시뮬레이션할 수 있기 때문이다.

AutoGen의 강점은 에이전트 간 자유로운 대화와 동적 팀 구성에 있어, Bull/Bear Debate 같은 토론 구조에는 AutoGen의 GroupChat 패턴이 유리할 수 있다. 두 프레임워크를 혼용하는 것도 가능하다.


에이전트별 SLO와 실패 모드

지연/처리량 목표

에이전트권장 지연 SLO동시성주요 실패 모드완화책
Volume Scannerp99 < 200ms수백 심볼/회데이터 지연/누락워터마크, 쿨다운
News Collectorp95 < 3s수십 기사/회중복, 루머디듀프, 소스 신뢰도
Position Sensorp99 < 200ms프로젝트당 전종목시세 지연Redis 캐시, DB 정합
Quant Analystp95 < 300ms티켓당 1회피처 오류피처 버전 고정
LLM Analystp95 < 8s동시 10건환각, 과잉확신근거 인용, Critic 루프
Sector Rotationp95 < 300ms주기적레짐 오판히스테리시스
Bull/Bear Debatep95 < 10s동시 수건수렴 실패라운드 제한(2)
Ensemble Voterp95 < 200ms티켓당 1회과적합캘리브레이션
Risk Sentinelp99 < 50ms주문 전 필수한도 미적용하드룰 우선
Trade Executorp99 < 100ms주문/초주문거부, 미체결재호가, 타임아웃

에이전트별 I/O 흐름


운영: 테스트, 카나리 배포, 킬 스위치

3단 테스트 체계

단계설명규제 근거
회귀 테스트코드 변경 시 기존 기능 검증MiFID II RTS 6: 적합성 테스트
시뮬레이션백테스트 + 페이퍼 트레이딩SEC Rule 15c3-5
카나리 배포자본 1-5%로 시작 후 확대Google SRE 카나리 릴리스

카나리 배포 원칙

트레이딩에서 "트래픽" 대신 "자본/노출(Exposure)"을 카나리 단위로 삼는다.

  • 신규 전략/모델 변경: 총 자본의 1-5%로 시작 후 성과/리스크/슬리피지 모니터링
  • LLM 프롬프트/토론 규약 변경: 제한된 섹터/소수 심볼로 먼저 적용 후 드리프트 확인
  • 문제 발생 시 즉시 이전 버전으로 롤백 가능하도록 "버전 고정 + 이벤트 로그 기반 재현" 준비

Kill Switch

Kill Switch는 모든 미체결 주문을 즉시 취소하고 파이프라인을 중단하는 비상 장치다.

모든 LangGraph 노드는 실행 전에 Redis의 Kill Switch 플래그를 확인한다. 플래그가 설정되어 있으면 즉시 종료한다.


전체 인프라 스택 요약

기술역할핵심 사용처
LangGraph오케스트레이션StateGraph DAG, 체크포인트, 조건부 분기, Human-in-the-Loop
Kafka이벤트 스트림파이프라인/거래/포지션 이벤트 토픽, 감사 로그
Redis실시간 캐시시세 캐시, Pub/Sub, Rate Limiter, Kill Switch, 에이전트 가중치
Celery스케줄링/비동기Beat(정기 트리거), PositionSensor 폴링, Reflection, 보고서
PostgreSQL영구 저장체크포인트, 거래 이력, Reflection Memo, 가중치 스냅샷

LangGraph는 "에이전트를 어떻게 연결하고 실행할 것인가"에 대한 답이다. 단순한 순차 파이프라인에서 벗어나, 그래프 기반 DAG + 체크포인팅 + 조건 분기 + 병렬 실행 + Human-in-the-Loop를 하나의 프레임워크로 제공함으로써, 운영 가능한(production-grade) 멀티에이전트 시스템을 구축할 수 있게 한다.


참고 자료