LangGraph 2.0 실전 가이드 — 그래프 기반 AI 에이전트, 체크포인팅, MCP 연동, 프로덕션 배포
LangGraph 2.0(2026년 2월 출시)의 핵심 개념과 프로덕션 배포 전략을 정리한다. State·Node·Edge 구성, PostgreSQL 체크포인팅, Human-in-the-Loop 패턴, MCP 서버 연동, 멀티 에이전트 서브그래프, 가드레일 설정까지 코드 예시 중심으로 다룬다.
LangGraph 2.0은 2026년 2월 정식 릴리즈된 그래프 기반 AI 에이전트 프레임워크로, 체크포인팅·Human-in-the-Loop·MCP 연동을 프로덕션 수준으로 지원한다. 단순 LLM 호출 체인에서 벗어나, 상태를 유지하면서 루프·분기·재시도·인간 개입을 구조적으로 처리해야 하는 에이전트를 만들 때 선택지가 된다. 이 글은 LangGraph 2.0의 핵심 개념과 코드 예시, 프로덕션 배포 전략을 실무 관점에서 정리한다.
이 글이 필요한 사람: AI 에이전트를 프로덕션에 배포해야 하는 백엔드/풀스택 개발자, LangChain에서 더 복잡한 에이전트로 이동하려는 개발자, CrewAI·AutoGen과 비교해 무엇을 선택할지 고민 중인 개발자.
LangGraph 2.0이란 무엇인가
LangGraph는 LangChain 팀이 만든 오픈소스 에이전트 런타임이다. AI 에이전트의 실행 흐름을 방향성 그래프(DAG가 아닌 사이클 허용 그래프)로 정의하는 것이 핵심 아이디어다. 노드는 함수나 LLM 호출이고, 에지는 실행 흐름이다. 상태(State)는 그래프 전체에서 공유되며, 각 노드가 상태를 읽고 업데이트한다.
2026년 2월 출시된 LangGraph 2.0은 이전 버전 대비 세 가지 큰 변화를 가져왔다:
가드레일 노드 내장 — 콘텐츠 필터링, 속도 제한, 감사 로그를 선언적 설정으로 추가 가능
MCP 클라이언트 내장 — 별도 라이브러리 없이 MCP 서버를 툴로 직접 연결
LangGraph Studio 2.0 — 에이전트 실행 시각화, 상태 편집, 중단점 설정 GUI
Klarna, Replit, Elastic, Ally Financial이 프로덕션에서 사용 중이며, GitHub 스타 기준으로 CrewAI와 함께 에이전트 프레임워크 양강 체제를 형성하고 있다.
LangGraph의 상태 기반 그래프 실행 구조. 노드가 상태를 공유하며 사이클 실행이 가능하다. (출처: LangChain 공식 문서)
핵심 구성요소 — State, Node, Edge, Graph
LangGraph의 네 가지 핵심 구성요소를 이해하면 전체 패턴이 보인다.
State는 그래프 전체에서 공유되는 TypedDict 객체다. 각 노드는 상태를 받아 수정된 상태를 반환한다. 상태 설계가 에이전트 설계의 절반이다.
Node는 Python 함수다. 상태를 입력받고 업데이트할 상태 딕셔너리를 반환한다. LLM 호출, 툴 실행, 검증 로직 모두 노드로 표현한다.
Edge에는 세 종류가 있다. 일반 에지는 항상 다음 노드로 이동하고, 조건부 에지는 상태 값에 따라 분기하며, 엔트리/종료 포인트는 그래프의 시작과 끝을 정의한다.
Graph는 StateGraph 인스턴스다. 노드와 에지를 등록하고 compile()로 실행 가능한 Runnable을 생성한다.
LangGraph 2.0 기본 에이전트 구조 (Python)
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage, AIMessage
# 1. State 정의
class AgentState(TypedDict):
messages: list
next_action: str
# 2. Node 정의
llm = ChatAnthropic(model="claude-opus-4-6")
def call_llm(state: AgentState) -> AgentState:
response = llm.invoke(state["messages"])
return {"messages": state["messages"] + [response]}
def route(state: AgentState) -> str:
last_message = state["messages"][-1]
if hasattr(last_message, "tool_calls") and last_message.tool_calls:
return "tool_node"
return END
# 3. Graph 구성
builder = StateGraph(AgentState)
builder.add_node("llm", call_llm)
builder.set_entry_point("llm")
builder.add_conditional_edges("llm", route)
# 4. 컴파일 및 실행
graph = builder.compile()
result = graph.invoke({"messages": [HumanMessage("현재 날씨를 알려줘")]})
체크포인팅으로 에이전트 상태 영속화하기
체크포인팅은 LangGraph를 단순 파이프라인이 아닌 프로덕션 에이전트 런타임으로 만드는 핵심 기능이다. 실행 중간에 상태를 저장해두면, 서버 재시작이나 오류 후에도 이어서 실행할 수 있다. 장시간 실행 작업, 인간 승인이 필요한 단계, 비용이 큰 LLM 호출을 반복하지 않을 수 있다.
LangGraph 2.0은 세 가지 체크포인터를 공식 지원한다:
InMemoryCheckpointer — 개발/테스트용. 프로세스 재시작 시 소멸
PostgresSaver — 프로덕션 권장. asyncpg 기반 연결 풀 지원
RedisSaver — 고속 캐시가 필요한 짧은 세션에 적합
thread_id로 대화 세션을 구분한다. 같은 thread_id로 이어서 호출하면 이전 상태에서 계속 실행된다.
PostgreSQL 체크포인터 설정 (프로덕션)
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
import asyncpg
# 연결 풀 생성 (프로덕션: min 5, max 20 권장)
async def create_graph_with_checkpointer():
pool = await asyncpg.create_pool(
dsn="postgresql://user:pass@localhost:5432/langgraph",
min_size=5,
max_size=20
)
checkpointer = AsyncPostgresSaver(pool)
await checkpointer.setup() # 체크포인트 테이블 자동 생성
graph = builder.compile(checkpointer=checkpointer)
return graph
# 실행: thread_id로 세션 구분
config = {"configurable": {"thread_id": "user-session-abc123"}}
result = await graph.ainvoke(
{"messages": [HumanMessage("이전 작업 이어서 진행해줘")]},
config=config
)
# 이전 상태 조회
state = await graph.aget_state(config)
print(state.values) # 현재 저장된 상태 확인
Human-in-the-Loop — 에이전트 중간에 사람 개입시키기
Human-in-the-Loop(HITL)는 에이전트가 특정 시점에 실행을 일시 중단하고 사람의 확인이나 입력을 기다리는 패턴이다. 비용이 큰 작업 실행 전 승인, 에이전트 판단이 불확실한 케이스, 규정상 사람 검토가 필수인 워크플로우에서 필수다.
LangGraph에서 HITL은 interrupt_before와 interrupt_after 파라미터로 구현한다. 지정된 노드에서 그래프가 일시 중단되고, Command(resume=...)로 재개한다.
Human-in-the-Loop 승인 패턴
from langgraph.types import Command, interrupt
def risky_action(state: AgentState) -> AgentState:
# 실행 전 사람에게 확인 요청
user_approval = interrupt({
"message": f"다음 작업을 실행합니다: {state['next_action']}. 승인하시겠습니까?",
"action_details": state["next_action"]
})
if user_approval["approved"]:
# 승인된 경우 실제 작업 실행
result = execute_action(state["next_action"])
return {"messages": state["messages"] + [{"role": "tool", "content": result}]}
else:
# 거부된 경우 중단
return {"messages": state["messages"] + [{"role": "system", "content": "작업이 취소되었습니다."}]}
# 그래프 컴파일 시 중단점 지정
graph = builder.compile(
checkpointer=checkpointer,
interrupt_before=["risky_action"] # 이 노드 전에 자동 중단
)
# 에이전트 실행 → 중단점에서 일시 정지
result = await graph.ainvoke(inputs, config)
# result["__interrupt__"] 에 중단 정보 포함
# 사람이 승인 후 재개
await graph.aupdate_state(config, {}, as_node="risky_action")
final = await graph.ainvoke(Command(resume={"approved": True}), config)
LangGraph 2.0은 MCP(Model Context Protocol) 클라이언트를 내장한다. 별도 라이브러리 없이 MCP 서버를 에이전트 툴로 직접 연결할 수 있다. MCP의 97M 설치 기반과 LangGraph의 에이전트 런타임이 결합되면, 에이전트가 파일 시스템·DB·외부 API에 구조화된 방식으로 접근할 수 있다.
연결 방식은 두 가지다:
stdio MCP 서버 — 로컬 프로세스로 실행되는 MCP 서버 (Claude Desktop 방식)
HTTP/SSE MCP 서버 — 원격 MCP 서버, 프로덕션 환경에서 권장
MCP 툴을 LangGraph에 연결하면 에이전트가 툴 호출 → 결과 수신 → 다음 판단을 자동으로 처리한다. 체크포인팅과 결합하면 툴 실행 결과도 상태로 저장된다.
LangGraph 2.0 + MCP 서버 연동
from langgraph.mcp import MCPClient
from langgraph.prebuilt import create_react_agent
# HTTP MCP 서버 연결 (프로덕션)
async def build_mcp_agent():
async with MCPClient(
url="https://your-mcp-server.com/mcp",
transport="http"
) as mcp_client:
# MCP 서버에서 툴 목록 자동 로드
tools = await mcp_client.get_tools()
# ReAct 에이전트에 MCP 툴 장착
agent = create_react_agent(
model="claude-opus-4-6",
tools=tools,
checkpointer=checkpointer
)
config = {"configurable": {"thread_id": "mcp-session-001"}}
result = await agent.ainvoke(
{"messages": [HumanMessage("GitHub에서 최근 이슈 10개를 요약해줘")]},
config=config
)
return result
# stdio MCP 서버 연결 (로컬 개발)
from langgraph.mcp import StdioMCPClient
mcp = StdioMCPClient(command=["npx", "-y", "@modelcontextprotocol/server-filesystem", "/workspace"])
tools = await mcp.get_tools()
멀티 에이전트 그래프 — 서브그래프와 에이전트 팀 구성
복잡한 태스크를 처리하려면 단일 에이전트보다 역할별로 특화된 에이전트 팀이 효과적이다. LangGraph는 서브그래프(subgraph)를 통해 에이전트를 노드로 취급하는 멀티 에이전트 아키텍처를 지원한다.
일반적인 패턴:
슈퍼바이저 패턴 — 오케스트레이터 에이전트가 서브 에이전트에게 작업을 위임하고 결과를 취합
병렬 실행 패턴 — 독립적인 태스크를 여러 에이전트가 동시에 처리 후 결과 병합
파이프라인 패턴 — 에이전트 A 결과가 에이전트 B의 입력이 되는 직렬 처리
LangGraph 2.0의 Send API를 사용하면 동적으로 에이전트 인스턴스를 생성하고 병렬 실행할 수 있다. 예를 들어, 문서 N개를 N개 에이전트에 동시에 분배해서 처리하는 팬아웃/팬인 패턴이다.
슈퍼바이저 멀티 에이전트 패턴
from langgraph.graph import StateGraph, END
from typing import TypedDict, Literal
class TeamState(TypedDict):
task: str
research_result: str
code_result: str
final_answer: str
# 서브 에이전트 노드
def research_agent(state: TeamState) -> TeamState:
"""검색·조사 전문 에이전트"""
result = research_llm.invoke([HumanMessage(f"조사 태스크: {state['task']}")])
return {"research_result": result.content}
def code_agent(state: TeamState) -> TeamState:
"""코드 작성 전문 에이전트"""
result = coding_llm.invoke([
HumanMessage(f"코드 작성 태스크: {state['task']}\n참고 자료: {state['research_result']}")
])
return {"code_result": result.content}
def supervisor(state: TeamState) -> TeamState:
"""결과 통합 및 최종 답변 생성"""
result = supervisor_llm.invoke([
HumanMessage(f"조사 결과: {state['research_result']}\n코드: {state['code_result']}\n이 내용을 통합해서 최종 답변을 작성해줘")
])
return {"final_answer": result.content}
# 그래프 구성
builder = StateGraph(TeamState)
builder.add_node("research", research_agent)
builder.add_node("code", code_agent)
builder.add_node("supervisor", supervisor)
builder.set_entry_point("research")
builder.add_edge("research", "code") # 조사 → 코딩
builder.add_edge("code", "supervisor") # 코딩 → 슈퍼바이저
builder.add_edge("supervisor", END)
team_graph = builder.compile(checkpointer=checkpointer)
프로덕션 배포 — LangGraph 2.0 가드레일과 LangGraph Platform
LangGraph 2.0의 프로덕션 배포 방법은 두 가지다.
셀프호스팅: FastAPI + LangGraph 그래프를 직접 서버에 배포한다. PostgreSQL 체크포인터, Redis 세션 캐시, 비동기 실행으로 구성한다. 비용 제어가 가능하지만 인프라 관리가 필요하다.
LangGraph Platform: LangChain이 제공하는 관리형 서비스다. 에이전트 배포, 스케일링, 모니터링을 관리해준다. LangGraph Studio와 통합되어 실시간 에이전트 실행 시각화가 가능하다.
LangGraph 2.0의 가드레일 노드는 프로덕션에서 중요한 기능이다. 코드로 구현하던 콘텐츠 필터링, 속도 제한, 감사 로그를 선언적 설정으로 추가할 수 있다:
LangGraph 2.0 가드레일 설정
from langgraph.guardrails import ContentFilter, RateLimiter, AuditLogger
# 콘텐츠 필터 — 유해 콘텐츠 차단
content_filter = ContentFilter(
blocked_categories=["violence", "hate_speech", "personal_info"],
on_violation="reject" # 또는 "sanitize"
)
# 속도 제한 — 사용자당 요청 수 제한
rate_limiter = RateLimiter(
requests_per_minute=10,
requests_per_day=100,
key_fn=lambda state: state["user_id"]
)
# 감사 로그 — 규정 준수 목적
audit_logger = AuditLogger(
log_level="all", # "tool_calls", "state_changes", "all"
storage="postgresql",
retention_days=90
)
# 가드레일 적용
graph = builder.compile(
checkpointer=checkpointer,
guardrails=[content_filter, rate_limiter, audit_logger]
)
# langgraph.json — LangGraph Platform 배포 설정
# {
# "dependencies": ["."],
# "graphs": {"agent": "./agent.py:graph"},
# "env": ".env"
# }
2026년 주요 AI 에이전트 프레임워크 비교. LangGraph는 제어·상태 관리, CrewAI는 역할 기반 협업, OpenAI Agents SDK는 OpenAI 생태계에 강점이 있다.
LangGraph vs CrewAI vs OpenAI Agents SDK — 2026년 선택 기준
세 프레임워크는 철학이 다르다. 상황에 맞는 선택이 중요하다.
기준
LangGraph 2.0
CrewAI
OpenAI Agents SDK
철학
그래프 기반 제어
역할 기반 팀
함수 우선 단순함
학습 곡선
중상 (그래프 개념)
낮음
낮음
상태 관리
정교한 상태 그래프
제한적
컨텍스트 객체
체크포인팅
내장 (PostgreSQL/Redis)
미지원
미지원
Human-in-Loop
내장
제한적
커스텀 구현 필요
MCP 지원
2.0 내장
플러그인
부분 지원
프로덕션 성숙도
높음
중간
OpenAI 종속
LLM 독립성
완전 독립
완전 독립
OpenAI 중심
LangGraph 선택 기준: 복잡한 상태를 유지해야 하고, Human-in-the-Loop가 필요하며, 여러 LLM 공급사를 혼용할 계획이 있을 때.
CrewAI 선택 기준: 역할이 명확한 에이전트 팀을 빠르게 만들어야 할 때. 프로토타이핑에 빠르다.
OpenAI Agents SDK 선택 기준: OpenAI만 쓸 계획이고 빠른 시작이 우선일 때.
트러블슈팅 — LangGraph 2.0 자주 막히는 케이스
1. 체크포인터 없이 interrupt() 호출 시 오류 interrupt()는 체크포인터가 있어야 상태를 저장할 수 있다. compile(checkpointer=...)를 반드시 설정할 것.
2. 서브그래프 상태 타입 불일치 서브그래프의 State와 부모 그래프의 State 타입이 다르면 데이터 전달 시 KeyError가 발생한다. 공유 키는 타입을 맞출 것.
3. 비동기 노드에서 asyncio 이벤트 루프 충돌 동기 코드 내부에서 asyncio.run()을 중첩 호출하면 RuntimeError. graph.invoke() vs graph.ainvoke()를 환경에 맞게 선택할 것.
4. MCP 연결 타임아웃 원격 MCP 서버는 첫 연결 시 최대 10초가 걸릴 수 있다. timeout=30으로 넉넉하게 설정할 것.