RAG2026-5일28차시 · Conditional Edge 이해5 / 17← 이전목차다음 →MetaContents

28차시. Conditional Edge 이해

2. 분기 함수의 4가지 규칙

출처: 원본 PDF 28차시_ConditionalEdge이해.pdf 5~7쪽 · 쪽 그림 5쪽 6쪽 7쪽

이 규칙을 지키면 라우팅 버그가 거의 사라집니다.

2-1) 규칙 ① — State만 보고 판단한다

❌ 외부 상태나 랜덤에 의존

출력
──────────────────────────────────────
import random
def bad_route(state):
    if random.random() > 0.5:      # 재현 불가!
        return "a"
    return "b"

def bad_route2(state):
    if datetime.now().hour > 18:   # 시간에 따라 달라짐
        return "night"
    return "day"

✅ State만 사용

출력
──────────────────────────────────────
def good_route(state) -> str:
    return "ok" if state.get("retrieval_ok") else "empty"

→ 같은 State면 항상 같은 경로
→ 테스트와 재현이 가능합니다

💡 시간이나 랜덤이 필요하다면?
노드에서 값을 계산해 State에 넣고,
분기 함수는 그 값을 읽기만 합니다.
노드: {"is_night": datetime.now().hour > 18}
분기: return "night" if state["is_night"] else "day"
이러면 테스트할 때 is_night를 직접 넣어 검증할 수 있습니다.

2-2) 규칙 ② — 부수 효과 금지

❌ State를 수정

출력
──────────────────────────────────────
def bad_route(state):
    state["retries"] += 1          # 금지!
    return "retry"

→ LangGraph가 이 변경을 인식하지 못합니다
→ 병렬 실행 시 충돌합니다
→ 언제 몇 번 호출됐는지 보장되지 않습니다

✅ 판단만 하고, 변경은 노드가

출력
──────────────────────────────────────
def good_route(state) -> str:
    return "retry"                 # 판단만

def bump_node(state):              # 변경은 노드가
    return {"retries": state.get("retries", 0) + 1}

2-3) 규칙 ③ — 모든 경우를 처리한다

출처: 원본 PDF 7쪽

❌ 빠져나갈 구멍이 없음

출력
──────────────────────────────────────
def bad_route(state):
    if state["grade"] == "pass":
        return "done"
    if state["grade"] == "retry":
        return "again"
    # grade가 "research"면? → None 반환 → 에러!

✅ 마지막은 조건 없이

출력
──────────────────────────────────────
def good_route(state) -> str:
    grade = state.get("grade", "retry")     # 기본값
    if grade == "pass":
        return "done"
    if grade == "giveup":
        return "giveup"
    return "regenerate"                     # 그 외 전부

2-4) 규칙 ④ — 반환값 = 경로맵의 키

출처: 원본 PDF 7쪽

Python
def route(state) -> str:
    return "ok"          # ← 이 문자열이

g.add_conditional_edges("retrieve", route, {
    "ok": "generate",    # ← 여기 키와 정확히 같아야 함
    "empty": "fallback",
})

⚠️ 가장 흔한 에러
분기 함수는 "OK"를 반환하는데
경로맵의 키는 "ok"인 경우.
대소문자 하나에 런타임 에러가 납니다.
예방법 — 경로 이름을 상수로 정의하세요.
OK, EMPTY = "ok", "empty"
def route(state): return OK if ... else EMPTY
g.add_conditional_edges(..., {OK: "generate", EMPTY: "fallback"})

← 이전 절28차시 · 1. 왜 모든 질문을 같게 처리하면 안 될까?다음 절 →28차시 · 3. 무엇을 기준으로 나눌까?