요즘 에이전트 프레임워크를 도입하려고 보면 “기능은 많은데 뭐부터 써야 하지?”가 가장 큰 고민이죠. LangChain과 LangGraph 1.0은 바로 그 지점을 겨냥해 안정화된 API와 역할 분리를 내세웠고, 특히 LangChain의 에이전트는 LangGraph 런타임 위에서 돌아가도록 정리돼 처음은 쉽게, 필요해지면 깊이 있게 내려갈 수 있게 했습니다. 즉, 표준 에이전트 패턴은 LangChain으로 빠르게, 장기 실행·감사·중단/재개 같은 프로덕션 제어는 LangGraph로 맡기는 그림입니다.
LangChain 1.0: 실제로 도움이 되는 기능과 코드 예시

LangChain 1.0의 핵심은 표준 진입점 create_agent와 미들웨어입니다. create_agent로 모델·도구·프롬프트만 지정하면 생산성 높은 에이전트 루프(모델→도구→응답)가 바로 서고, 미들웨어 훅(before/after model, tool call wrapping 등)으로 대화 요약, Human‑in‑the‑Loop(HITL), PII 감지/마스킹 같은 정책을 손쉽게 끼워 넣을 수 있습니다. 또한 구조화 출력(Structured output)은 메인 루프에 통합되어 ToolStrategy/ProviderStrategy로 더 견고해졌고, 메시지의 표준 콘텐츠 블록(.content_blocks)이 도입돼(OpenAI/Anthropic 등) 멀티모달·도구 호출·인용 데이터를 공급자 중립 형식으로 다룰 수 있습니다. (기존 레거시는 langchain‑classic으로 이동, Python 3.10+ 요구)
예시 1) 가장 기본적인 에이전트 + 요약/HITL 미들웨어
# Python 3.10+
from typing import TypedDict
from langchain.tools import tool
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware, HumanInTheLoopMiddleware
from langchain_openai import ChatOpenAI
@tool
def get_weather(city: str) -> str:
"""Get weather information for a city."""
return f"{city}: 22°C, Clear"
agent = create_agent(
model=ChatOpenAI(model="gpt-4o-mini"), # 또는 문자열 "openai:gpt-4o-mini"
tools=[get_weather],
system_prompt="Answer concisely and call tools when helpful.",
middleware=[
SummarizationMiddleware(
model="openai:gpt-4o-mini",
max_tokens_before_summary=1000
),
HumanInTheLoopMiddleware(
# get_weather 도구 호출 시 사람 승인 단계 삽입
interrupt_on={"get_weather": True, "description": "Review weather call before executing"}
),
],
)
result = agent.invoke({"messages": [{"role": "user", "content": "서울 날씨 알려줘"}]})
print(result["messages"][-1].content)
이 패턴은 LangChain의 표준 에이전트 루프와 미들웨어를 활용해, 토큰 한계에 가까워지면 자동 요약을, 민감 도구 호출엔 사용자 승인을 끼워 넣는 구성입니다.
예시 2) 구조화 출력 — 비용/지연 절약(메인 루프 통합)
from pydantic import BaseModel
from langchain.agents import create_agent
from langchain.agents.structured_output import ToolStrategy, ProviderStrategy
class WeatherReport(BaseModel):
temperature: float
condition: str
# (A) 어떤 모델이든 도구 호출로 스키마를 강제: ToolStrategy
agent = create_agent(
model="openai:gpt-4o-mini",
tools=[], # 필요 시 도구 추가
response_format=ToolStrategy(WeatherReport),
)
out = agent.invoke({"messages": [{"role": "user","content": "서울의 기온과 상태를 숫자/문자로만 알려줘"}]})
print(out["structured_response"]) # WeatherReport(temperature=..., condition="...")
# (B) 공급자 네이티브 구조화 출력: ProviderStrategy (예: OpenAI)
agent_native = create_agent(
model="openai:gpt-4o",
response_format=ProviderStrategy(WeatherReport),
)
v1에서는 구조화 출력을 별도 노드가 아니라 메인 루프에서 처리해 비용/지연을 줄였고, 사전에 도구가 바인딩된 모델(pre‑bound)은 구조화 출력과 함께 쓸 수 없으니 에이전트 측에서 도구를 넘기세요.
예시 3) 표준 콘텐츠 블록 접근(멀티모달 포함)
# 마지막 AI 메시지의 표준화된 콘텐츠 블록 순회
ai_msg = result["messages"][-1]
for block in getattr(ai_msg, "content_blocks", []):
print(block["type"], block) # text / image / tool_call 등
.content_blocks는 공급자별 포맷 차이를 흡수해 추론 추적·인용·도구 호출과 같은 복합 내용을 일관되게 다루게 해줍니다. (LangChain Blog)
LangGraph 1.0: 실제로 도움이 되는 기능과 코드 예시

LangGraph 1.0은 내구성 있는 실행(Durable execution)과 지속성(Persistence)을 기본기처럼 제공합니다. 그래프를 체크포인터(예: MemorySaver/SQLite/Postgres)와 함께 컴파일하면 각 단계의 상태가 체크포인트로 저장되고, 스레드(Thread) 단위로 중단/재개, 타임 트래블 디버깅, 단기/장기 메모리가 가능해집니다. 특히 interrupt()로 노드 중간에 실행을 멈추고 사람 입력을 받아 Command(resume=...)로 이어갈 수 있어, 결재·승인·수정 같은 Human‑in‑the‑Loop 패턴이 간결해집니다.
👉 이전 글: [AI][Agent] LangGraph: 차세대 AI 에이전트 프레임워크의 부상
예시 1) 체크포인터 + 스레드 + 중단/재개(HITL)
# Python 3.10+
from typing import TypedDict
from langgraph.graph import START, END, StateGraph
from langgraph.checkpoint.memory import MemorySaver # 데모용 체크포인터
from langgraph.types import interrupt, Command
class State(TypedDict):
draft: str
approved: bool
def write_draft(state: State) -> dict:
proposal = f"[DRAFT] {state.get('draft','') or '안녕하세요!'}"
# 사람에게 승인/수정 요청: UI에 proposal을 보여주고 입력을 기다리게 된다
decision = interrupt({"action": "approve_draft", "proposal": proposal})
# 사용자가 {"approve": True} 또는 {"approve": False, "edit": "..."}로 응답한다고 가정
if decision.get("edit"):
proposal = decision["edit"]
return {"draft": proposal, "approved": bool(decision.get("approve", False))}
def send_or_cancel(state: State) -> dict:
return {"draft": f"SENT: {state['draft']}" if state["approved"] else "CANCELLED"}
builder = StateGraph(State)
builder.add_node("write_draft", write_draft)
builder.add_node("send_or_cancel", send_or_cancel)
builder.add_edge(START, "write_draft")
builder.add_edge("write_draft", "send_or_cancel")
graph = builder.compile(checkpointer=MemorySaver())
# 1) 최초 호출: interrupt 발생 → "__interrupt__" 정보가 반환됨
cfg = {"configurable": {"thread_id": "user-123"}}
out = graph.invoke({"draft": "안부 메일 초안"}, cfg)
if "__interrupt__" in out:
payload = out["__interrupt__"]["value"] # {"action": "approve_draft", "proposal": "..."}
# 2) 사람 응답을 받아 재개
human_answer = {"approve": True} # or {"approve": False, "edit": "[DRAFT] 수정본 ..."}
out = graph.invoke(Command(resume=human_answer), cfg)
print(out["draft"]) # SENT: ... 또는 CANCELLED
- compile(checkpointer=...)로 내구성 활성화, {"configurable": {"thread_id": ...}}로 스레드를 지정합니다.
- interrupt()가 불리면 실행이 저장·중단되고, Command(resume=...)로 같은 스레드에서 정확히 그 지점부터 이어집니다.
예시 2) 파일 기반 지속성(데모용 SQLite 체크포인터)
# pip install langgraph-checkpoint-sqlite
from sqlite3 import connect
from langgraph.checkpoint.sqlite import SqliteSaver # 동기용(데모/소규모), 실서비스는 별도 백엔드 권장
conn = connect("state.db")
sqlite_cp = SqliteSaver(conn=conn)
# 위의 builder.compile(checkpointer=sqlite_cp)로 교체하면,
# 프로세스 재시작 후에도 같은 thread_id로 상태를 이어갑니다.
SQLite 체크포인터 패키지가 별도로 제공되며, 프로덕션에서는 동시성/확장성을 고려한 백엔드를 선택하세요(예: Postgres 버전, LangGraph 플랫폼).
주의사항과 바로 적용 포인트(요약)
처음엔 표준 패턴으로 빨리 결과 내야 하니 LangChain 1.0의 create_agent + 미들웨어(요약/HITL/PII)를 기본으로 삼고, 구조화 출력은 ToolStrategy/ProviderStrategy로 메인 루프에서 처리해 비용·지연을 줄이세요. 워크플로가 길어지고 승인·감사·재시작/재실행이 중요해지면 LangGraph 1.0으로 내려가 체크포인터·스레드·interrupt/Command 조합으로 내구성을 확보하면 됩니다. 마이그레이션 관점에서는 v1에서 레거시 일부가 langchain‑classic으로 분리되고 Python 3.9 지원이 중단되었으니 환경을 3.10+로 정리해 두세요. 지금 바로 LangChain과 LangGraph 1.0을 기준으로 설계하면, 알파/베타 시절의 깨지는 변경보다 훨씬 예측 가능한 개발 경험을 얻을 수 있습니다.
참고 출처
- LangChain Agents: create_agent, 미들웨어, 구조화 출력 전략(메인 루프 통합) 및 사용 예시. (LangChain Docs)
- LangChain v1 마이그레이션(레거시 분리, Python 3.10+, pre‑bound 모델 제한, 구조화 출력 변경점). (LangChain Docs)
- 표준 콘텐츠 블록(.content_blocks) 소개(공급자 중립 멀티모달/도구 호출 표현). (LangChain Blog)
- LangChain Guardrails/PII 감지 미들웨어(개요). (LangChain Docs)
- LangGraph 내구성/지속성(체크포인터·스레드), 메모리 개념, Interrupt/Command 기반 HITL. (LangChain Docs)
👉 다음 글: [AI][Agent] CrewAI vs LangGraph: 협업인가, 상태인가? 당신의 멀티에이전트 프로젝트에 맞는 프레임워크 선택 가이드
[AI][Agent] CrewAI vs LangGraph: 협업인가, 상태인가? 당신의 멀티에이전트 프로젝트에 맞는 프레임워크
AI 에이전트 기술은 이제 단순한 업무 자동화를 넘어, 복잡한 비즈니스 문제를 해결하는 핵심 동력으로 자리 잡고 있습니다. 이 기술적 진화의 중심에서 개발자들은 중요한 아키텍처 선택의 기
wide-shallow.tistory.com
'개발 > LLM' 카테고리의 다른 글
| [AI][RAG] LightRAG 완벽 분석: GraphRAG 대안 (0) | 2025.11.01 |
|---|---|
| [논문 리뷰] DeepSeek-OCR: Contexts Optical Compression: 10배 더 작게 (0) | 2025.10.29 |
| [논문 리뷰] Building Guardrails for Large Language Models (2) | 2025.05.01 |
| [AI][Agent] CrewAI: 협업하는 AI 에이전트의 세계 (1) | 2025.04.29 |
| [AI][Agent] LangGraph와 BeeAI 멀티 에이전트 프레임워크 비교 분석 (0) | 2025.04.22 |