노드는 State 전체를 고쳐 쓰지 않고 갱신분 dict만 반환 — 병합은 그래프가 맡습니다 (다음 장의 불변 갱신 원칙)
takeaway
조건 엣지가 본 것도, 답변 노드가 쓴 것도 전부 이 State 안의 값입니다 — State 설계가 곧 그래프 설계인 이유입니다.
PART 1 · 핵심 구조
State 설계 원칙
그래프의 데이터 계약 — 필드 최소 · 불변 갱신 · 자동 누적
핵심 포인트
TypedDict
상태 스키마를 타입으로 선언 — 필드 구조가 곧 그래프의 계약
최소 필드
필요한 값만 State에 — 필드가 늘수록 메모리와 디버깅 부담 증가
불변 갱신
노드는 State를 직접 수정하지 않고 갱신분을 반환 — 흐름 추적 용이
Annotated[list, add]
리스트 필드 자동 누적 — messages처럼 쌓이는 값에 사용
코드
python
from typing import TypedDict
# 그래프 전체가 공유하는 상태 스키마
class RAGState(TypedDict):
question: str
documents: list
relevance_score: float
answer: str
retry_count: int
# 노드는 State를 받아 갱신분만 반환하는 순수 함수
def retrieve(state: RAGState):
docs = retriever.invoke(state["question"])
return {"documents": docs}
PART 1 · 핵심 구조
StateGraph 코드 패턴
add_node → add_edge → compile() — 3단계로 그래프 조립
python
from langgraph.graph import StateGraph, MessagesState, START, END
# 노드 = State를 받아 업데이트를 반환하는 순수 함수
def retrieve(state): ...
def generate(state): ...
# State 스키마로 그래프 선언 — MessagesState는 messages를 자동 누적
graph = StateGraph(MessagesState)
graph.add_node("retrieve", retrieve)
graph.add_node("generate", generate)
graph.add_edge(START, "retrieve") # START/END 특수 노드로 진입·종료 지정
graph.add_edge("retrieve", "generate")
graph.add_edge("generate", END)
app = graph.compile() # 컴파일하면 invoke/stream 가능한 Runnable이 됨