본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 23. 16:06

LangGraph를 더 긴 체인으로 취급하지 마세요: 상태, 중단(Interrupts), 그리고 복구(Recovery)를 먼저 정의하세요

요약

LangGraph를 단순한 체인의 연장이 아닌 상태(State) 중심의 워크플로우로 이해해야 함을 강조합니다. 상태 스키마 정의, 리듀서 활용, 그리고 compile()을 통한 런타임 제어의 중요성을 다룹니다.

핵심 포인트

  • LangGraph의 핵심은 프롬프트가 아닌 상태(State) 관리임
  • 리듀서를 통해 병렬 작업 시 컨텍스트 보존 및 데이터 병합 제어 필요
  • compile() 단계는 그래프 정의(Description)가 런타임(Runtime)으로 전환되는 경계임
  • 복잡한 에이전트 구축 전 상태 스키마와 리듀서를 먼저 검증할 것

LangGraph를 오해하는 가장 쉬운 방법은 이를 "단계가 더 많은 LangChain"으로 보는 것입니다.

그것은 핵심을 놓치는 것입니다.

LangGraph는 에이전트(Agent)가 더 이상 단일 프롬프트(Prompt)나 단순한 체인(Chain)이 아닐 때 유용해집니다. 워크플로우에 상태(State), 분기(Branches), 도구 호출(Tool calls), 인간의 승인(Human approval), 체크포인팅(Checkpointing), 그리고 실제 AI 호스트(AI host) 내에서 에이전트를 신뢰하기 전에 반드시 검사해야 하는 복구 동작(Recovery behavior)이 포함될 때 비로소 유용해집니다.

저는 이 노트를 위한 근거 기반 읽기 레이어로 Doramagic LangGraph 매뉴얼을 사용했습니다:
https://doramagic.ai/en/projects/langgraph/manual/

이것은 독립적인 프로젝트 가이드이며, 공식 LangGraph 문서가 아닙니다. 저는 이를 도입 전 체크리스트로 사용합니다: 프로젝트를 Claude, ChatGPT, Cursor, Codex 또는 다른 AI 호스트에 연결하기 전에 무엇을 이해해야 하는지에 대한 체크리스트입니다.

핵심은 또 다른 프롬프트 라이브러리를 만드는 것이 아닙니다. 유용한 결과물은 역량 리소스 팩(Capability resource pack)입니다: 즉, 개발자가 도입 전에 무엇을 검증할지 결정하는 데 도움이 되는 매뉴얼, 소스 맵(Source map), 경계 노트(Boundary notes), 함정 로그(Pitfall log), 스모크 체크(Smoke check), 경량 평가 기준(Lightweight eval criteria), 피드백 노트, 그리고 호스트 준비 완료 컨텍스트(Host-ready context)입니다.

1. 진짜 경계는 프롬프트가 아니라 상태(State)입니다

단발성(One-shot) 모델 호출의 경우, 프롬프트가 종종 주요 경계가 됩니다.

LangGraph의 경우, 첫 번째 경계는 상태 스키마(State schema)입니다:

  • 어떤 필드가 노드(Node) 사이를 이동하는가;
  • 어떤 필드를 노드가 업데이트할 수 있는가;
  • 병렬 분기(Concurrent branches)가 값을 어떻게 병합하는가;
  • 어떤 값이 체크포인트(Checkpoint)에 들어가는가;
  • 어떤 값이 절대 영구 저장(Persisted)되어서는 안 되는가.

이것이 리듀서(Reducers)가 중요한 이유입니다. 메시지 리스트(Message list)는 보통 단순히 덮어쓰여지지 않습니다. add_messages 또는 이에 상응하는 TypeScript 방식과 같은 추가(Append) 또는 병합(Merge) 규칙이 필요합니다. 이 작은 구현 세부 사항이 병렬 작업이 컨텍스트(Context)를 보존할지, 아니면 조용히 누락시킬지를 결정합니다.

제가 선호하는 첫 실행은 "범용 에이전트(Universal agent)"가 아닙니다. 하나의 상태 스키마, 하나의 노드, 하나의 부분 업데이트(Partial update), 그리고 하나의 명시적인 리듀서를 가진 아주 작은 그래프입니다. 만약 이것이 명확하지 않다면, 도구(Tools)를 추가하는 것은 문제를 숨길 뿐입니다.

2. compile()은 기술(description)과 런타임(runtime) 사이의 경계입니다

compile() 이전의 LangGraph 그래프는 기술(description)입니다: 노드(nodes), 엣지(edges), 조건부 경로(conditional routes), 상태 필드(state fields), 리듀서(reducers)로 구성됩니다.

compile() 이후에는 Pregel 스타일의 런타임(runtime)이 제어권을 가져갑니다. 노드들은 슈퍼스텝(supersteps) 단위로 실행됩니다. 부분적인 상태 업데이트(partial state updates)는 채널(channels)과 리듀서(reducers)를 통해 전달됩니다. 조건부 엣지(conditional edges)는 다음 노드를 선택합니다.

이는 디버깅(debugging) 방식이 바뀌어야 함을 의미합니다. 그래프가 실패했을 때, 단순히 노드 함수만 조사하지 마세요. 다음 네 가지 계약(contracts)을 동시에 조사해야 합니다:

  • State 스키마(schema)가 이 노드가 반환된 키(key)를 작성하도록 허용하는가?
  • 노드가 최소 하나 이상의 유효한 State 필드(field)를 반환하는가?
  • 리듀서(reducer)가 의도된 병합(merge) 동작과 일치하는가?
  • 조건부 엣지(conditional edge)에 실제 종료 경로(exit path)가 있는가?

Doramagic 매뉴얼은 InvalidUpdateError: Must write to at least one of [...]와 같은 오류를 강조합니다. 이는 단순한 무작위 런타임 불편 사항이 아닙니다. 이는 종종 노드의 반환 형태(return shape)와 State 스키마(schema)가 일치하지 않음을 의미합니다.

3. Human-in-the-loop는 실행 계약(execution contract)입니다

LangGraph의 중단(interrupt) 및 Human-in-the-loop 지원은 인터페이스 장식(interface decoration)으로 취급되어서는 안 됩니다.

만약 에이전트(agent)가 이메일을 보내거나, 파일을 수정하거나, 외부 API를 호출하거나, 운영 시스템(production systems)을 건드릴 수 있다면, 승인 단계는 화면을 지켜보며 실수를 잡아내길 바라는 사람의 역할이 아니라 그래프 계약(graph contract)의 일부가 되어야 합니다.

실용적인 패턴은 다음과 같습니다:

  • 모델이 도구 호출(tool call)을 제안합니다.
  • 그래프 노드가 중단(interrupt)을 발생시킵니다.
  • 사람이 하나의 구체적인 동작을 승인, 무시 또는 편집합니다.
  • 구조화된 응답(structured response)이 그래프로 반환됩니다.
  • 전체 워크플로(workflow)를 재시작하는 대신 중단 지점(interrupt point)부터 실행이 재개됩니다.

이것이 LangGraph가 단순한 채팅 데모보다 복구 가능한 워크플로 에이전트(recoverable workflow agents)에 더 적합한 이유입니다.

4. 체크포인팅(Checkpointing)은 로깅(logging)이 아닙니다

체크포인팅(Checkpointing)은

  • 체크포인터(checkpointer)는 스레드(thread) 범위로 지정되며 내구성이 있는 실행(durable execution), 재생(replay), 그리고 재개(resume)를 지원합니다.
  • 스토어(store)는 스레드를 가로지르는 장기 기억(long-term memory)입니다.
  • 직렬화(serialization)는 Python 객체가 어떻게 저장되고 재구성되는 데이터를 정의하는지를 결정합니다.

도입하기 전에 주의해야 할 보안 세부 사항이 하나 있습니다. 체크포인트 직렬화기(checkpoint serializer)는 체크포인트 데이터로부터 Python 객체를 처리할 수 있습니다. 새로운 애플리케이션은 LANGGRAPH_STRICT_MSGPACK=true를 고려하거나, JsonPlusSerializer를 위해 명시적인 allowed_msgpack_modules 목록을 사용하는 것을 고려해야 합니다.

이는 고급 엣지 케이스(edge case)가 아닙니다. 만약 체크포인트 데이터가 신뢰 경계(trust boundary)를 넘나들 가능성이 있다면, 역직렬화(deserialization) 정책은 시스템 경계의 일부입니다.

5. 더 나은 첫 실행 체크리스트

LangGraph를 처음 테스트할 때는 의도적으로 경로를 작게 유지하는 것이 좋습니다:

  1. 임시 디렉터리를 사용하세요. 운영(production) 데이터를 연결하지 마세요.
  2. messages와 하나의 비즈니스 필드를 포함하는 최소한의 상태(State)를 정의하세요.
  3. 유효한 상태(State) 필드만 반환하는 노드 하나를 작성하세요.
  4. 추가(append)와 유사한 동작을 하는 모든 필드에 리듀서(reducer)를 부착하세요.
  5. 구체적인 도구(tool)와 유사한 동작 주변에 인터럽트(interrupt)를 하나 추가하세요.
  6. 체크포인터(checkpointer)를 추가하세요.
  7. 노드 하나를 강제로 실패하게 만든 다음, 재개(resume) 동작을 확인하세요.

이 경로가 실패한다면, 아직 실제 도구로 넘어가지 마세요. 문제는 에이전트(agent)가 약해서가 아닙니다. 런타임 경계(runtime boundary)가 검증되지 않은 것입니다.

스모크 테스트(smoke check)는 모호한 "작동하는 것 같다"는 결과가 아니라, 합격/불합격(pass/fail) 기준을 가져야 합니다. 유용한 최소 기준은 다음과 같습니다: 노드가 선언된 상태(State) 필드만 작성하는지, 인터럽트가 실제 부수 효과(side effect)가 발생하기 전에 발생하는지, 재개(resume) 동작이 이미 성공한 형제 노드의 쓰기(write)를 반복하지 않는지, 그리고 직렬화기(serializer) 제한이 명시적인지 확인하는 것입니다. 이 중 어느 하나라도 불분명하다면, 결정은 "운영 환경에서 시도해 보자"가 아니라 "보류(HOLD)\

만약 당신의 작업이 일회성 모델 호출(one-off model call)이라면, LangGraph는 필요 이상의 복잡한 장치(machinery)가 될 수 있습니다.

만약 당신의 AI 호스트가 각 단계가 검사 가능(inspectable)하고, 일시 중단 가능(pausable)하며, 복구 가능(recoverable)하고, 검토 가능(reviewable)해야 하는 다단계 작업(multi-step work)을 수행해야 한다면, LangGraph는 훨씬 더 흥미로운 도구가 됩니다.

더 나은 질문은 "LangGraph로 에이전트(agent)를 구축할 수 있는가?"가 아닙니다.

더 나은 질문은 다음과 같습니다: "내 에이전트의 상태(state), 도구 경계(tool boundary), 그리고 복구 경로(recovery path)를 그래프(graph)로 작성할 수 있는가?"

그 질문에 먼저 답하십시오. 그런 다음 LangGraph가 기술 스택(stack)에 포함되어야 하는지 결정하십시오.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0