Skip to main content
LangGraph는 아래 3개를 이해하면 거의 끝입니다.
  • State: 그래프가 공유하는 데이터
  • Node: State를 읽고 업데이트하는 실행 함수
  • Edge: 다음 Node로 이동하는 경로

실행 흐름

1) State 정의

from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages
from langchain_core.messages import BaseMessage

class State(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]
    intent: str

2) Node 정의

def classify(state: State) -> State:
    # state를 읽고 intent를 결정
    return {"intent": "search"}


def retrieve(state: State) -> State:
    return {"messages": [("assistant", "검색 결과를 가져왔습니다.")]}

3) Edge 연결

from langgraph.graph import StateGraph, START, END

graph = StateGraph(State)
graph.add_node("classify", classify)
graph.add_node("retrieve", retrieve)
graph.add_node("respond", respond)

graph.add_edge(START, "classify")

def route(state: State):
    return "retrieve" if state["intent"] == "search" else "respond"

graph.add_conditional_edges("classify", route, {
    "retrieve": "retrieve",
    "respond": "respond",
})
graph.add_edge("retrieve", "respond")
graph.add_edge("respond", END)

app = graph.compile()

입문자 실수 3가지

  1. State 키를 노드마다 다르게 써서 충돌
  2. 조건부 엣지 반환값과 매핑 키 불일치
  3. END로 가는 엣지를 빼서 무한 루프

다음: 도구 호출 에이전트

Node/Edge/State를 이해했으면 ToolNode 기반 에이전트로 넘어가세요.

실무 적용 체크리스트

  • 노드 입출력 State 계약을 문서화했습니다.
  • 조건부 엣지 default/END 경로를 테스트했습니다.
  • recursion_limit/timeout을 설정했습니다.
  • 실패 시 재시도와 중단 규칙을 분리했습니다.

자주 나는 실수

  1. State 키를 일관되게 관리하지 않아 노드 간 충돌이 납니다.
  2. 조건부 라우팅 반환값과 매핑 키가 불일치합니다.
  3. END/재시도 경로를 누락해 무한 루프가 발생합니다.

다음 문서

다음: LangGraph 조건부 엣지

학습 흐름을 이어서 진행합니다.

구현 체크 포인트

  • State 키는 팀 표준 네이밍을 사용합니다.
  • Node는 한 가지 책임만 수행하도록 작게 유지합니다.
  • Edge 조건식은 비즈니스 규칙 문서와 동일한 용어를 사용합니다.
이 원칙을 지키면 그래프가 커져도 디버깅과 유지보수가 쉬워집니다.

디버깅 루틴

문제가 생기면 아래 순서로 확인합니다.
  1. State 입력이 예상 스키마인지 확인
  2. 각 Node 반환 키가 State 계약과 일치하는지 확인
  3. Edge 조건 분기에서 누락된 라우팅이 없는지 확인
이 루틴을 팀 표준으로 고정하면 장애 분석 시간이 크게 줄어듭니다.