콘텐츠로 이동

상태 머신과 워크플로 그래프 설계

분류: Layer 12 - AI 시스템 & LLM 애플리케이션 | 선수지식: L10-20 (트리·그래프), L9-10 (설계 원칙), L12-60 (Agent)

상태 머신과 워크플로 그래프 설계 — FSM, Statecharts, XState, LangGraph

섹션 제목: “상태 머신과 워크플로 그래프 설계 — FSM, Statecharts, XState, LangGraph”

상태 머신과 워크플로 그래프는 시스템을 **상태(state), 이벤트(event), 전이(transition), side effect(action)**로 분해해 복잡한 흐름을 명시적으로 제어하는 설계 방식이다.

  • agent를 무한 루프에서 꺼낸다: “다음에 무엇을 할지”를 모델에만 맡기지 않고 가능한 경로를 제한한다.
  • 디버깅 가능성: 현재 상태와 직전 이벤트를 보면 실패 위치를 추적할 수 있다.
  • 테스트 가능성: 모든 상태·전이 조합을 표로 만들고 누락 전이를 검증할 수 있다.
  • Human-in-the-loop와 잘 맞음: 승인 대기, 수정 요청, 재시도 같은 block 상태를 모델링하기 쉽다.
  • Durable execution의 기반: 재시작 시 복원할 최소 단위가 “현재 상태 + context”로 정리된다.

2.5 선행 기술의 한계 — if/else Workflow가 무너지는 지점

섹션 제목: “2.5 선행 기술의 한계 — if/else Workflow가 무너지는 지점”

초기 LLM workflow는 보통 다음과 같은 코드로 시작한다.

if (needsSearch) {
const docs = await search(query);
if (docs.length === 0) retry();
}
if (needsTool) {
const result = await callTool(args);
}

처음에는 읽기 쉽지만, 검색 실패, 도구 권한 부족, 사람 승인 대기, 재시도 초과, 부분 성공, 취소가 붙으면 분기 수가 곱셈으로 늘어난다. 상태는 지역 변수와 DB row, queue message, frontend UI에 흩어지고 “지금 이 작업이 정확히 어디에 멈췄는가”가 사라진다.

상태 머신은 이 한계를 불가능한 상태를 표현하지 않는 모델로 푼다. XState는 finite state machine과 statechart를 핵심 추상화로 제공하고, LangGraph는 agent 실행을 graph node와 edge로 표현한다. 출처: XState API, LangGraph durable execution.

3.0 State Machine과 Stateful System의 차이

섹션 제목: “3.0 State Machine과 Stateful System의 차이”

상태 머신은 가능한 상태와 전이를 정의하는 모델이고, stateful system은 그 모델을 실제 운영 환경에서 저장·복원·관측·마이그레이션까지 책임지는 시스템이다.

관점State machineStateful system
관심사어떤 상태에서 어떤 이벤트 허용상태를 어디에 저장하고 어떻게 복구할지
산출물상태도, transition tableDB schema, checkpoint, replay log, migration
실패 처리invalid transition 거부worker crash, 중복 이벤트, 버전 불일치 복구
테스트상태·이벤트 조합 테스트재시작, 재처리, 오래된 run replay 테스트

예를 들어 waiting_for_human -> approved -> acting 전이를 정의하는 것은 state machine 설계다. 승인 대기 중 서버가 재시작되어도 같은 run을 복원하고, 승인 이벤트가 두 번 와도 한 번만 처리하며, workflow 코드 v2 배포 후 v1 run을 깨뜨리지 않는 것은 stateful system 설계다.

State: idle | planning | acting | waiting_for_human | done | failed
Event: START | TOOL_OK | TOOL_ERROR | APPROVE | REJECT | RETRY | CANCEL
Transition: (state, event) -> next_state

FSM의 장점은 “현재 상태에서 받을 수 없는 이벤트”를 명확히 거부할 수 있다는 점이다.

작은 승인 workflow라면 transition table을 먼저 적어보면 누락 전이가 보인다.

현재 상태이벤트다음 상태비고
planningSTARTactingplan이 유효할 때만 허용
actingTOOL_ERRORfailed_transientattempt < max_attempts
waiting_for_humanAPPROVEacting승인 이벤트는 idempotent 처리
waiting_for_humanCANCELfailed사용자 취소
doneAPPROVE거부완료된 run은 다시 진행 금지

전이 테스트는 최소한 done + APPROVE 같은 invalid transition 거부, TOOL_ERROR 반복 후 fallback 진입, APPROVE 중복 수신 시 상태가 한 번만 바뀌는지를 확인한다.

statechart는 FSM에 계층·병렬·history 개념을 더한다.

  • Hierarchical state: running.searching, running.calling_tool
  • Parallel state: draftingcompliance_check를 동시에 진행
  • History state: 승인 후 중단 전 상태로 복귀
  • Guard: if confidence >= 0.8일 때만 자동 진행

LLM workflow에서는 human review 후 어디로 돌아갈지 history state가 특히 중요하다.

Graph는 node와 edge로 흐름을 표현한다.

START
-> classify
-> retrieve
-> draft
-> judge
-> [pass] final
-> [fail] revise -> judge

FSM이 “상태 중심”이라면 graph는 “실행 step 중심”이다. LangGraph 같은 agent framework는 state를 공유 객체로 두고 node가 state를 갱신한다.

요소역할예시
Guard전이 가능 여부 판단risk < threshold
Action내부 state 갱신attempt += 1
Effect외부 side effect이메일 발송, DB 업데이트

Durable execution에서는 effect를 재실행하면 안 되므로 action/effect 분리가 필수다.

LLM을 graph node로 넣을 때 출력 계약이 필요하다.

{
"decision": "call_tool | ask_human | final",
"confidence": 0.74,
"reason": "...",
"tool_args": {}
}

자유 텍스트 답변을 바로 edge condition에 쓰면 parsing 실패가 workflow 실패로 번진다.

LLM node가 참고할 입력은 L12-100 Context Engineering의 context bundle로 관리하고, graph state에는 “다음 전이를 결정하는 데 필요한 최소 상태”만 남기는 편이 안전하다. 검색 결과 원문이나 긴 tool 로그를 graph state에 계속 누적하면 persistence 비용과 replay 노이즈가 함께 커진다.

재시도는 edge가 아니라 상태로 모델링하는 편이 안전하다.

acting
-> failed_transient
-> retry_wait
-> acting
-> failed_permanent

외부 side effect가 이미 일어났다면 L9 Saga처럼 보상 action을 별도 node로 둔다.

운영 가능한 workflow graph는 “현재 node가 어디인가”만 저장하지 않는다.

항목저장 내용운영 목적
Checkpoint현재 state, context summary, attempts, timerscrash 후 마지막 안전 지점에서 재개
Persistencecheckpoint를 durable store에 기록worker 교체·배포·장기 대기에도 상태 보존
Replayevent log나 history로 같은 결정을 재현사고 분석, regression test, human approval 재개
Versioningstate schema와 transition graph 버전진행 중 run을 새 코드 배포와 분리

checkpoint는 snapshot이고 replay는 history다. snapshot만 있으면 “왜 이 상태가 되었는가”가 약하고, history만 있으면 긴 workflow 재구성이 비싸다. production에서는 보통 event history와 최신 checkpoint를 함께 둔다.

LLM workflow에서는 다음 값을 특히 조심해서 저장한다.

  • LLM 입력 원문: 재현성에는 좋지만 PII·secret·비용 문제가 있으므로 redaction과 reference 저장을 우선한다.
  • Tool side effect 결과: 외부 시스템에 이미 반영된 작업은 idempotency key와 함께 저장한다.
  • Context summary: 다음 step 판단에 필요한 사실만 구조화하고, 원문 근거는 문서 ID·span ID로 참조한다.
  • Graph version: v1 run이 진행 중일 때 v2 transition을 강제로 적용하면 불가능한 상태가 생길 수 있다.

작은 persistence schema는 다음 정도만 있어도 crash 복구와 중복 이벤트 방어를 시작할 수 있다.

{
"run_id": "run_20260522_001",
"graph_version": "support-agent-v1",
"state_schema_version": 2,
"checkpoint_id": "chk_0007",
"current_node": "waiting_for_human",
"state": {
"attempt": 1,
"approval_status": "pending",
"context_summary_ref": "ctxsum_42"
},
"last_event_id": "evt_103",
"idempotency_key": "approve:ticket_77:reviewer_12",
"updated_at": "2026-05-22T09:30:00Z"
}

예를 들어 support-agent-v1waiting_for_human run이 남아 있는 상태에서 v2needs_legal_review node를 추가한다면, 진행 중 run은 그대로 v1 graph로 재개하거나 migration job에서 state_schema_version: 2 -> 3 변환과 새 checkpoint 생성을 명시적으로 수행한다. 이때 기존 approval signal은 같은 idempotency_key로 dedupe해야 승인 메일 발송 같은 effect가 두 번 실행되지 않는다.

L12-120 Temporal Durable Execution은 이 운영 관점을 workflow history, activity result, signal, replay 규칙으로 더 엄격하게 구현한 사례다.

안티패턴문제대안
everything node한 node가 분류·검색·도구·응답을 모두 수행node를 결정 단위로 분리
hidden state상태가 prompt 문자열 안에만 존재typed state schema
unbounded loopjudge 실패 시 무한 revisemax_attempts guard
side effect in guard조건 판단 중 외부 API 호출guard는 순수 함수 유지
UI state와 실행 state 혼합화면 표시 변경이 workflow 의미를 바꿈UI projection 분리
unversioned transition배포 후 진행 중 run이 새 graph와 충돌graph/schema version 고정
  • 상담 봇의 draft → review → send 승인 플로우
  • 코드 agent의 plan → edit → test → fix → summarize 루프
  • RAG pipeline의 retrieve → rerank → answer → judge → fallback
  • 결제/주문처럼 보상이 필요한 AI-assisted workflow
  • batch 평가 시스템의 queue 상태 관리

프론트엔드에서 복잡한 모달·폼 상태를 boolean 여러 개로 관리하면 isOpen && isSubmitting && hasError 같은 불가능한 조합이 생긴다. FSM은 이런 상태를 editing | submitting | failed | submitted로 제한한다. AI workflow도 동일하다. LLM이 더 똑똑해져도 실행 상태는 명시적으로 모델링해야 운영이 된다.

개념 A개념 B차이점
FSMStatechartFSM은 평면 상태, statechart는 계층·병렬·history 지원
DAGState machineDAG는 보통 일회성 비순환 작업, state machine은 loop와 이벤트 처리 가능
WorkflowAgentworkflow는 경로가 코드에 명시, agent는 일부 결정을 LLM이 수행
GuardJudgeguard는 deterministic 조건, judge는 모델 기반 품질 판단
StateContextstate는 실행 위치, context는 결정을 위한 데이터
CheckpointReplaycheckpoint는 현재 snapshot, replay는 이벤트 history로 결정 재현
  • workflow를 state/event/transition으로 표현할 수 있다.
  • state machine 모델과 stateful system 운영 책임을 구분할 수 있다.
  • LLM decision node의 structured output schema를 설계할 수 있다.
  • retry, timeout, cancel, human approval을 상태로 모델링할 수 있다.
  • guard와 side effect를 분리해야 하는 이유를 설명할 수 있다.
  • checkpoint, persistence, replay, versioning을 workflow 설계에 반영할 수 있다.
  • unbounded loop를 max attempt와 fallback state로 제어할 수 있다.

finite state machine, statechart, stateful system, XState, LangGraph StateGraph, workflow graph, checkpoint, persistence, replay, workflow versioning, guard condition, actor model, Saga compensation, deterministic workflow

  • 간단한 고객 문의 agent를 상태도 6개 이하로 그려보기
  • judge → revise 루프에 max attempt guard를 넣고 실패 시 fallback 설계
  • 진행 중인 workflow에 graph_version과 checkpoint schema를 추가해 migration 시나리오 써보기
  • XState로 idle/editing/submitting/success/failure 폼 머신 구현
  • LangGraph에서 node별 state update와 trace를 확인
  1. 상태 머신은 복잡한 workflow를 상태·이벤트·전이로 제한해 불가능한 상태를 줄인다.
  2. state machine은 모델이고 stateful system은 저장·복원·replay·versioning까지 포함한 운영 책임이다.
  3. LLM agent도 실행 경로는 명시적 graph로 두는 편이 디버깅과 운영에 유리하다.
  4. guard, action, effect를 분리해야 재시도와 durable execution이 안전해진다.
  5. graph 설계의 핵심은 모델의 자율성을 없애는 것이 아니라 위험한 경로를 좁히는 것이다.

최종 수정: 2026-05-21