![LangGraph 완전 가이드 [2026년 에디션] 대표 이미지](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0gabyuzc7egnltaw45gz.png)
LangGraph 완전 가이드 [2026년 에디션]
요약
LangGraph를 활용하여 상태 유지(stateful)가 가능하고 제어 가능한 프로덕션급 AI 에이전트 시스템을 구축하는 방법을 다룹니다. 선형적인 LangChain의 한계를 넘어 루프, 분기, 상태 관리가 가능한 복잡한 워크플로우 설계법을 설명합니다.
핵심 포인트
- LangGraph를 통한 상태 유지형 다단계 AI 워크플로우 구축
- 노드, 엣지, 상태를 이용한 유향 그래프 모델링
- 조건부 엣지와 사이클을 활용한 동적 에이전트 제어
- Human-in-the-Loop 및 멀티 에이전트 아키텍처 패턴
- 실패 시 재시도 및 지속성(Persistence) 관리 전략
LangGraph 완전 가이드 [2026년 에디션]
상태 유지(stateful)가 가능하고 제어 가능한 워크플로우로 프로덕션급 에이전트 AI 시스템 구축하기
- 2026년 7월 · 읽기 시간 15분*
만약 LangChain의 선형 파이프라인(linear pipelines)을 넘어 AI 에이전트가 생각하고, 분기(branch)하고, 루프(loop)를 돌며, 복구(recover)하는 방식을 실제로 제어해야 한다면 — LangGraph는 당신이 기다려온 프레임워크입니다. 이 가이드는 핵심 개념부터 프로덕션 패턴까지, 작동하는 코드를 포함하여 모든 것을 다룹니다.
목차
- LangGraph란 무엇이며 왜 존재하는가?
- 핵심 개념: 노드(Nodes), 엣지(Edges), 상태(State)
- 첫 번째 LangGraph 앱 만들기
- 조건부 엣지(Conditional Edges) 및 분기(Branching)
- 사이클(Cycles) 및 루프(Loops) — 진정한 힘
- 상태 관리(State Management) 심층 분석
- Human-in-the-Loop 패턴
- 멀티 에이전트 아키텍처(Multi-Agent Architectures)
- 지속성(Persistence) 및 체크포인팅(Checkpointing)
- 스트리밍(Streaming) 및 실시간 출력
- 프로덕션 환경에서의 LangGraph
- LangGraph vs 대안들
파트 1 — LangGraph란 무엇이며 왜 존재하는가? {#part-1}
LangGraph는 LangChain을 기반으로 구축된 프레임워크로, 유향 그래프(directed graphs)로 모델링된 상태 유지형(stateful), 다단계 AI 워크플로우를 생성하기 위해 만들어졌습니다. 이는 겉보기에는 단순해 보이지만 실제로는 복잡한 문제, 즉 현실 세계의 AI 작업은 직선으로 실행되지 않는다는 문제에서 탄생했습니다.
LangChain의 체인(chains)은 선형적입니다 — A → B → C 순서로 실행되고 종료됩니다. 이 모델은 데모용으로는 적합합니다. 하지만 에이전트가 실패한 도구 호출(tool calls)을 재시도하고, LLM의 결정에 따라 분기하며, 인간의 검토를 위해 일시 중지하고, 몇 시간 또는 며칠에 걸친 세션 전반에 걸쳐 컨텍스트(context)를 유지해야 하는 프로덕션 환경에서는 무너집니다.
핵심 통찰: 에이전트는 단지 루프(loop)일 뿐입니다 — 세상을 인지하고, 결정하고, 행동하고, 결과를 관찰하고, 이를 반복합니다. LangGraph는 그 루프를 명시적이고, 관찰 가능하며, 제어 가능하게 만듭니다.
LangGraph가 해결하는 다섯 가지 문제
실패 시 재시도 (Retry on failure): 도구 호출 (tool call)이 에러를 반환할 때, 에이전트는 전체 체인 (chain)을 중단시키는 대신 루프를 돌아 다른 접근 방식을 시도할 수 있습니다.
동적 분기 (Dynamic branching): LLM 분류기 노드 (classifier node)가 청구 전문가, 기술 지원 흐름, 또는 일반 처리기로 라우팅할 수 있습니다. 이는 설계 시점에 하드코딩되는 것이 아니라 런타임 (runtime)에 결정됩니다.
인간 참여 (Human-in-the-loop): 실행이 정의된 체크포인트 (checkpoint)에서 일시 중지되며, 사람이 검토하고 승인한 후에만 재개됩니다. 이는 규제 산업 및 중대한 결정이 필요한 상황에서 매우 중요합니다.
장기 실행 세션 (Long-running sessions): 상태 (State)가 데이터베이스에 체크포인트로 저장되므로, 에이전트는 충돌, 재시작 또는 며칠간의 중단 이후에도 정확히 멈췄던 지점부터 다시 시작할 수 있습니다.
멀티 에이전트 협업 (Multi-agent collaboration): 특화된 서브 에이전트 (sub-agents)들을 하나의 오케스트레이션된 시스템 (orchestrated system)으로 구성할 수 있으며, 에이전트 간에는 깔끔한 상태 경계 (state boundary)가 유지됩니다.
파트 2 — 핵심 개념: 노드, 엣지, 상태 {#part-2}
LangGraph에는 세 가지 기본 요소 (primitives)가 있습니다. 이것들을 마스터하면 이 가이드의 모든 패턴을 한눈에 이해할 수 있습니다.
상태 (The State)
상태 (State)는 그래프의 모든 노드에서 공유되는 타입이 지정된 Python 딕셔너리 (dictionary)입니다. 각 노드는 상태를 읽고, 작업을 수행한 뒤, 부분적인 업데이트를 반환합니다. Annotated 타입 힌트 (type hint)는 업데이트가 병합되는 방식을 제어합니다. 가장 중요한 패턴은 add_messages로, 이는 메시지 리스트를 교체하는 대신 메시지를 추가 (append) 합니다.
from typing import TypedDict, Annotated
from langgraph.graph import add_messages
...
add_messages가 중요한 이유: 이것이 없다면{"messages": [new_msg]}를 반환하는 각 노드가 전체 기록을 교체해 버릴 것입니다.add_messages를 사용하면 새 메시지가 추가되므로, 별도의 장부 관리 없이도 대화 기록이 자연스럽게 축적됩니다.
노드 (Nodes)
노드 (Nodes)는 일반적인 Python 함수입니다. 노드는 현재 상태 (state)를 전달받아 작업(LLM 호출, 도구 실행, 검증 로직 실행 등)을 수행하고, 변경된 키값만 포함하는 부분적인 (partial) 상태 업데이트를 반환합니다.
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(model="claude-opus-4-6")
...
엣지 (Edges)
엣지 (Edges)는 제어 흐름 (control flow)을 정의합니다. _일반 엣지 (normal edge)_는 항상 A → B로 경로를 지정합니다. _조건부 엣지 (conditional edge)_는 문자열 키를 반환하는 라우팅 함수 (routing function)를 호출하여, 실행을 여러 가능한 다음 노드 중 하나로 안내합니다.
from langgraph.graph import StateGraph, END
workflow = StateGraph(AgentState)
...
파트 3 — 첫 번째 LangGraph 앱 {#part-3}
이론은 무언가를 직접 만들 때 비로소 가치를 발휘합니다. 여기 완전한 **SQL 쿼리 생성 에이전트 (SQL query generation agent)**가 있습니다. 이 에이전트는 자연어 질문을 SQL로 변환하고, 쿼리의 정확성과 안전성을 검증하며, 품질 기준을 충족하거나 최대 3번의 시도가 완료될 때까지 반복합니다.

그림: 생성자-검증자-수정 루프 (generator-validator-revise loop) — SQL 품질 점수가 8점 이상이 될 때까지, 또는 최대 3회 시도 제한까지 반복.
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END, add_messages
from langchain_anthropic import ChatAnthropic
...
핵심 패턴: 빠르고 저렴한 모델 (Haiku)을 DBA 검증자로 사용하고, 성능이 뛰어난 모델 (Opus)을 생성자로 사용하세요. 검증자의 역할은 구조화된 점수 매기기 (structured scoring)입니다. 최첨단 추론 (frontier reasoning) 능력이 필요하지 않으므로, 여러 번의 피드백 반복을 거치더라도 비용을 낮게 유지할 수 있습니다.
파트 4 — 조건부 엣지 및 분기 {#part-4}
조건부 엣지 (Conditional edges)는 LangGraph가 의사결정을 구현하는 지점입니다. 라우팅 함수는 LLM 출력, 상태 값, 비즈니스 로직 또는 이들의 조합에 의해 구동될 수 있습니다. 다음은 의도를 분류하고 적절한 핸들러로 배정하는 고객 지원 라우터입니다.
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, END
...
흔한 실수 (Common mistake): 라우팅 함수는 edge map 딕셔너리의 키 중 하나와 정확히 일치하는 값을 반환해야 합니다. 만약 LLM이
"billing"을 반환했는데 맵에"Billing"이라고 되어 있다면, 그래프는GraphValueError를 발생시킵니다. 라우팅을 하기 전에 항상 LLM 출력값에.strip().lower()를 적용하세요.
파트 5 — 사이클(Cycles) & 루프(Loops) — 진정한 강력함 {#part-5}
루프(Loops)는 LangGraph를 모든 선형적인 대안들과 근본적으로 다르게 만드는 요소입니다. 에이전트(Agent)는 목표를 달성할 때까지 계속해서 작업을 수행할 수 있습니다. 즉, 충분한 정보를 얻을 때까지 검색하고, 품질이 충족될 때까지 생성하며, 도구(Tool) 사용이 성공할 때까지 재시도할 수 있습니다.
패턴은 항상 동일합니다. 라우팅 함수가 이미 실행되었던 노드를 반환할 수 있는 조건부 엣지(conditional edge)를 추가하는 것입니다. 그래프의 사이클 탐지기(cycle detector)는 설계 단계부터 이를 허용합니다.
from typing import TypedDict
class ResearchState(TypedDict):
...
항상 강제 종료 조건(hard exit condition)을 추가하세요. 모든 루프는 LLM의 판단과 관계없이 종료되는 최대 반복 횟수(maximum iteration count)를 가져야 합니다. 검색 결과가 지속적으로 무관할 경우, LLM은
INSUFFICIENT루프에 빠질 수 있습니다. 위에서 언급한 5회 검색 제한과 같은 하드 캡(hard cap)이 여러분의 회로 차단기(circuit breaker) 역할을 합니다.
파트 6 — 상태 관리 심층 분석 (State Management Deep Dive) {#part-6}
모든 상태 키(state key)에는 _리듀서(reducer)_가 있습니다. 리듀서는 노드로부터 오는 업데이트가 기존 상태에 어떻게 병합되는지를 제어하는 함수입니다. 기본 리듀서는 마지막에 작성된 값이 승리하는 방식(last-write-wins)입니다. 리듀서를 이해하면 정교한 병렬(parallel) 및 협업(collaborative) 노드 패턴을 구현할 수 있습니다.
from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages
import operator
...
리듀서 = 무료로 제공되는 스레드 안전성(thread safety).
SendAPI를 사용하여 병렬 노드로 팬아웃(fan out)하고 모든 노드가 동일한 키에 값을 쓸 때, LangGraph의 리듀서는 결과를 원자적(atomically)으로 병합합니다. 리스트에는operator.add를, 채팅 기록에는add_messages를 사용하거나, 커스텀 로직을 위해 직접 만든 함수를 사용하세요.
파트 7 — Human-in-the-Loop 패턴 {#part-7}
이것은 LangGraph를 정의하는 핵심 기능 중 하나입니다. 실행은 정의된 체크포인트(checkpoint)에서 중단되며, 사람이 입력을 제공한 후에만 재개됩니다. 이는 폴링 루프(polling loop)가 아닙니다. 체크포인터(checkpointer)에 의해 지원되는 일급 인터럽트(first-class interrupt) 메커니즘입니다.
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph, END
from langgraph.types import interrupt, Command
from typing import TypedDict
class ApprovalState(TypedDict):
task: str
plan: str
human_approved: bool
final_result: str
def planner_node(state: ApprovalState) -> dict:
plan = llm.invoke(f"Create a detailed execution plan for: {state['task']}").content
return {"plan": plan}
def human_review_node(state: ApprovalState) -> dict:
# interrupt()는 여기서 그래프를 일시 중단합니다.
# 호출자는 페이로드(payload)를 확인하며, Command(resume=...)가 전송될 때 실행이 재개됩니다.
human_input = interrupt({
"question": "Approve this plan?",
"plan": state["plan"]
})
return {"human_approved": human_input.get("approved", False)}
def executor_node(state: ApprovalState) -> dict:
if not state["human_approved"]:
return {"final_result": "Task cancelled."}
result = llm.invoke(f"Execute this plan:\n{state['plan']}").content
return {"final_result": result}
# 체크포인터(Checkpointer)는 필수입니다 — 인터럽트와 재개 사이의 상태를 저장합니다.
memory = Memor
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
