← → 키 또는 Space 로 이동
🕸️

LangChain
LangGraph
패스트트랙

LangChain 빌딩 블록부터 LangGraph 상태 그래프, Agent까지 한 번에

#LangChain #LangGraph #State #Node #Graph #Interrupt #Checkpoint

LangChain vs LangGraph

두 라이브러리의 역할과 차이점

🔗 LangChain
  • LLM 애플리케이션의 기본 빌딩 블록 제공
  • Prompt, Model, Parser, Tool, Retriever 등 컴포넌트 모음
  • 체인(Chain) — 단방향 파이프라인
  • 간단한 RAG, 요약, 번역 등에 적합
  • 분기/반복/상태 관리는 제한적
# 전형적인 단방향 체인
chain = prompt | model | parser
chain.invoke(input={"messages": [("user", "hi")]})
🕸️ LangGraph
  • LangChain 위에 얹힌 상태 기반 그래프 프레임워크
  • 순환(loop), 분기(branch), 병렬 실행 가능
  • Agent 간 협업·툴 호출 루프를 자연스럽게 표현
  • 상태(State) + 체크포인트로 지속성·재개 지원
  • Human-in-the-loop (Interrupt) 내장
# 상태 기반 그래프
graph = StateGraph(State)
graph.add_node("agent", agent_fn)
graph.add_edge("agent", "tool")
🔗

LangChain 기초

Prompt · Model · Output Parser — LLM 앱의 3대 빌딩 블록

📝 Prompt

변수 치환·역할별 메시지로 재사용 가능한 프롬프트 구성

🤖 Model

OpenAI·Gemini 등 Chat Model을 동일한 인터페이스로 호출

📦 Output Parser

문자열 응답을 구조화된 데이터(dict, Pydantic)로 변환

이어지는 슬라이드에서 영화 리뷰 → JSON 예제를 세 단계로 완성해봅니다.

Prompt Template 예제

재사용 가능한 프롬프트 — 변수 치환 + 메시지 구조화

📝 ChatPromptTemplate

  • System / User / Assistant 역할별 메시지를 구성
  • {변수} 플레이스홀더를 invoke 시 채움
  • MessagesPlaceholder로 대화 이력 주입 가능
  • 모델과 파이프(|)로 바로 체인 구성

🧭 언제 쓰나?

  • 같은 지시문을 여러 입력에 반복 적용할 때
  • 시스템 프롬프트를 고정하고 사용자 입력만 바꿀 때
  • few-shot 예시·히스토리를 구조적으로 끼워넣을 때

🎬 예제 시나리오 — 영화 리뷰를 분석해 {sentiment, summary, keywords} JSON으로 추출하는 체인을 3단계(프롬프트 → 모델 → 파서)에 걸쳐 완성해봅니다. 이번 슬라이드는 1단계: 프롬프트.


        
1 / 3

LangChain 모델 선언 예제

Provider별 Chat Model 초기화 — OpenAI · Gemini · init_chat_model

🎬 2단계: 모델 — 프롬프트 + LLM 체인이 완성됩니다. 다음 슬라이드에서 JSON 파서까지 연결합니다.

JsonOutputParser 예제

LLM의 문자열 응답을 dict로 파싱 — 체인 최종 단계

🧪 무엇을 해주나?

  • 모델 출력에서 JSON 블록을 추출 후 dict로 파싱
  • 마크다운 코드펜스(```json ... ```)도 허용
  • Pydantic 모델을 주면 스키마 검증까지 수행
  • 스트리밍 시 부분 JSON도 점진적으로 파싱

🔗 전체 체인 조립

  • prompt | model | parser — 3단계 파이프라인
  • 입력({review}) → 메시지 → 응답 → dict
  • 파서의 get_format_instructions()를 프롬프트에 주입하면 더 안정적

        
1 / 4

with_structured_output 으로 바꿔보기

파서 없이 모델이 직접 Pydantic 객체를 반환하도록

✨ 무엇이 달라지나?

  • 모델이 내부적으로 tool/function calling 또는 JSON 모드를 사용
  • 출력이 Pydantic 인스턴스(또는 dict)로 바로 반환
  • 프롬프트에 포맷 지침을 적지 않아도 스키마가 강제됨
  • JsonOutputParser 불필요 → 체인이 더 단순

⚖️ Parser vs Structured Output

  • Parser 어떤 모델에서도 동작 (문자열 기반)
  • Structured 스키마 준수율↑, 코드 간결
  • 구조화 스펙이 단단하면 Structured 권장

        
1 / 4

Runnable 인터페이스

한 번 Runnable이 되면 LangChain · LangGraph 전체로 동일한 동작이 전파

🧩 핵심 아이디어

  • Prompt · Model · Parser · Tool 은 모두 Runnable
  • 공통 메서드: invoke / stream / batch (+ async 버전)
  • 파이프(|)로 합성해도 결과 역시 Runnable
  • LangGraph는 노드 함수를 내부적으로 RunnableLambda로 감쌈
    → 그래서 그래프 자체에도 invoke/stream/batch가 그대로 열림

🌊 무엇이 전파되나?

  • 스트리밍 체인·그래프 어디서든 토큰 단위 .stream()
  • 배치 여러 입력을 .batch()로 병렬 처리
  • 비동기 .ainvoke() / .astream() 자동 지원
  • 트레이싱 LangSmith 추적·콜백·재시도가 일관 적용

        
1 / 3
🕸️

LangGraph 기초

상태(State) 기반 그래프로 순환·분기·사람 개입이 있는 워크플로우 설계

🗂️ State · Node · Graph

공유 상태 위에서 노드들이 실행되고, 엣지가 다음 단계를 결정

🔀 Conditional Edge

노드 반환값·State 값에 따라 다음 노드를 동적으로 분기

⏸ Interrupt

민감 동작 전 사람 승인·편집을 받아 재개하는 Human-in-the-loop

💾 Checkpoint

스텝마다 상태 스냅샷을 저장해 지속성·재개·시간여행

LangChain 컴포넌트를 그래프로 엮어 상태 있는 워크플로우를 만듭니다.

핵심 구성: State · Node · Graph

LangGraph를 이루는 세 가지 뼈대

🗂️ State

그래프 실행 전체에서 공유되는 데이터 컨테이너. TypedDict / Pydantic으로 스키마 정의.

  • 각 노드는 State를 입력으로 받아 일부를 업데이트해 반환
  • 필드마다 병합 방식을 지정 — 덮어쓰기(기본) / 이어붙이기 등
    ※ 이 "병합 규칙"을 LangGraph에서는 reducer라 부름 (예: 메시지 이력을 누적하는 add_messages)

🧩 Node

State를 받아 업데이트된 State를 반환하는 함수 단위.

  • LLM 호출, 툴 실행, 후처리 등 임의 로직
  • 파이썬 함수 / Runnable 무엇이든 가능
  • add_node("name", fn) 로 등록

🔀 Graph (Edge)

노드 간 흐름을 정의. 정적 엣지와 조건부 엣지를 지원.

  • add_edge(a, b) — 무조건 이동
  • add_conditional_edges — 함수 반환값으로 분기
  • START / END 상수로 시작·종료 지정

        
1 / 5
State·Node·Graph: START → agent → END

Conditional Edge (조건부 분기)

노드 반환값에 따라 다음 노드를 동적으로 결정

START
agent
route?
reply_positive
reply_negative
END

        
1 / 3
Conditional edge graph: START → agent → (reply_positive | reply_negative) → END

Interrupt (사람이 끼어드는 지점)

그래프 실행을 일시 정지하고, 외부 입력을 기다렸다가 재개

START
agent
⏸ human_review
END

⏸ 언제 쓰나?

  • Human-in-the-loop — 툴 호출 전 사람 승인
  • 민감한 동작(결제·삭제) 확인
  • 중간 결과 편집·검토
  • 외부 이벤트(알림·폼 제출) 대기

🧪 두 가지 방식

  • 정적 compile(interrupt_before=["tool"]) — 특정 노드 앞에서 무조건 멈춤
  • 동적 interrupt(payload) — 노드 내부에서 조건적으로 중단
  • 재개는 Command(resume=...) 로 값을 주입

        
1 / 4
Interrupt graph: START → agent → human_review → END

Checkpoint (상태 저장과 재개)

매 단계마다 State 스냅샷을 저장 → 중단·복구·시간여행이 가능

💾 무엇을 저장하나?

  • 각 super-step 직후의 State 스냅샷
  • 다음에 실행할 노드(=다음 작업)
  • thread_id 단위로 이력을 묶음

🧰 주요 Checkpointer

  • InMemorySaver — 개발·테스트
  • SqliteSaver — 단일 프로세스 영속화
  • PostgresSaver — 프로덕션 다중 워커
  • 커스텀 백엔드 구현 가능

🎁 얻는 것

  • 지속성 세션 간 대화 유지
  • 재개 Interrupt 후 이어서 실행
  • 시간여행 과거 체크포인트로 분기
  • 관측 각 스텝의 상태를 감사

        
1 / 3
🤖

Agent

LLM이 스스로 툴을 선택·호출하며 목표를 달성하는 루프

🔁 ReAct 루프

Reason → Act → Observe 를 반복하며 툴 결과를 보고 다음 행동을 결정

🧰 Tool Calling

함수 시그니처를 모델에 제공 → 모델이 호출할 툴·인자를 JSON으로 지정

🎁 create_agent

모델 + 툴만 주면 위 루프 그래프를 자동으로 조립해주는 프리셋

앞서 본 State · Graph · Checkpoint · Interrupt 가 모두 하나의 에이전트에 녹아듭니다.

create_agent — 프리셋 ReAct 에이전트

모델 + 툴 + 시스템 프롬프트만 주면 그래프를 자동으로 조립

🎁 무엇을 해주나?

  • 내부적으로 agent ↔ tools 를 오가는 ReAct 루프 그래프를 자동 생성
  • 메시지 상태(messages)와 add_messages reducer를 기본 제공
  • checkpointer 전달 시 대화 지속성 바로 사용
  • HumanInTheLoopMiddleware 로 툴별 approve·edit·reject 승인 설정
  • 반환값은 일반 CompiledGraph — 커스터마이즈·확장 가능

🧭 언제 쓰나?

  • 툴을 쓰는 일반적인 챗 에이전트를 빠르게 만들고 싶을 때
  • 직접 StateGraph로 조립하기 전, 프로토타입
  • 표준 패턴으로 충분하고, 특이한 분기가 필요 없을 때

※ 분기/병렬/도메인 특화 흐름이 필요하면 그대로 StateGraph로 내려가면 됩니다.


        
1 / 4

그래프 안에서 Agent 호출하기

create_agent 결과는 일반 Runnable — 노드 하나로 꽂을 수 있음

START
plan
🤖 weather_agent
summarize
END

        
1 / 4
Outer graph calling an agent: START → weather_agent → summarize → END

한 장 요약

LangChain(빌딩 블록) → LangGraph(상태 그래프) → Agent(ReAct 루프)

🔗 LangChain

  • Prompt — 변수 치환·역할별 메시지
  • Model — OpenAI·Gemini 등 통합 인터페이스
  • Output Parser — JsonOutputParser
  • Structured Output — 모델에 Pydantic 스키마 바인딩

🕸️ LangGraph

  • State · Node · Graph — 상태 머신으로 설계
  • Conditional Edge — 반환값으로 동적 분기
  • Interrupt — 사람 승인·편집 후 재개
  • Checkpoint — 지속성·재개·시간여행

🤖 Agent

  • ReAct 루프 — Reason → Act → Observe
  • Tool Calling — 모델이 툴·인자 선택
  • create_agent (langchain.agents) — 모델+툴만 주면 그래프 자동 조립
  • 필요 시 StateGraph로 커스터마이즈

🧠 사고 모델

"여러 단계의 LLM/툴 호출을 상태 머신처럼 설계하자." 각 노드는 상태를 조금씩 바꾸고, 엣지가 다음 단계를 정한다.

🛠 언제 쓰면 좋은가

  • 툴 호출이 있는 챗 에이전트
  • 멀티 에이전트 협업 (Planner/Worker/Critic)
  • 사람 승인이 필요한 자동화
  • 오래 걸리는 작업의 중단·재개

📚 더 읽을거리

  • LangChain: Prompts / Output Parsers / Structured Output
  • LangGraph: Concepts / Human-in-the-loop / Persistence
  • LangChain v1: create_agent + Middleware 가이드

더 공부해볼 것

에이전트를 실전에서 쓰려면 알아두면 좋은 개념들

🪝 Middleware & Hooks

create_agentagent loop 각 지점에 로직 삽입.

  • Node-style: before_agent / before_model / after_model / after_agent
  • Wrap-style: wrap_model_call / wrap_tool_call
  • 데코레이터(@before_model) 또는 AgentMiddleware 클래스로 정의

🧰 Built-in Middleware

  • SummarizationMiddleware — 긴 대화 자동 요약
  • HumanInTheLoopMiddleware — 툴 승인·편집·거절
  • ModelCallLimit / ToolCallLimit — 루프 폭주 방지
  • ModelFallbackMiddleware — 실패 시 백업 모델
  • PIIMiddleware — 개인정보 마스킹·차단
  • TodoListMiddleware, LLMToolSelectorMiddleware

🧠 Memory · Store

  • Short-term: Checkpointer 기반 thread 메모리
  • Long-term: Store — 사용자/도메인 지식 영속화
  • SummarizationMiddleware로 컨텍스트 관리

🌊 Streaming 모드

  • values — 매 스텝의 전체 State
  • updates — 노드가 반환한 변경분만
  • messages — 토큰 단위 LLM 스트림
  • customget_stream_writer로 임의 이벤트

🧵 Subgraph · Multi-agent

  • 그래프를 다른 그래프의 노드로 중첩
  • Supervisor / Swarm / Handoff 패턴
  • prebuilt: create_supervisor, create_swarm

🧪 Observability · 평가

  • LangSmith — 트레이싱·데이터셋·평가
  • Eval: 골든셋 + LLM-as-judge
  • 프로덕션 배포: LangGraph Platform

참고: langchain.agents.middleware / langgraph.store / LangSmith 공식 문서

🙌

감사합니다

질문·피드백 환영합니다 💬