5편에서 루프에 정지 조건을 넣었다면, 다음 질문은 이것입니다. 누가 다음에 말할지, 무엇을 병렬로 돌릴지, 실패 시 어느 노드로 보낼지 — 한 줄짜리 plan→act→observe로는 더 이상 안 그려질 때입니다.
핵심 한 줄: 그래프 엔지니어링은 모델을 더 똑똑하게 만드는 일이 아니라, 노드(역할·단계)·엣지(의존·라우팅)·상태(공유 계약) 로 “누가 언제 무엇을”을 명시하는 일입니다.
이 글은 「코딩은 대화다」 6편입니다. 루프 다음에 지도로 올라갑니다. 멀티에이전트·하네스가 전제입니다.
루프가 부족한 순간
| 증상 | 루프만으로 | 그래프가 필요할 때 |
|---|---|---|
| 역할이 바뀜 | 한 에이전트가 전부 | Research → Implement → Review처럼 소유권이 이동 |
| 일이 갈라짐 | 직렬로 우겨 넣음 | 조사 A/B를 병렬 후 병합 |
| 정책이 갈라짐 | 프롬프트에 if 나열 | 조건부 엣지로 라우팅 |
| 실패 처리 | 같은 턴 재시도 | 에스컬레이션 노드(사람·시니어 역할) |
루프(5편)는 한 노드 안의 리듬입니다. 그래프는 노드들 사이의 교통망입니다. WIP=1은 여전합니다 — 그래프 전체를 한 번에 삼키지 말고, 지금 활성인 노드(들) 만 돌리세요.
Rendering diagram…
위 그림에서 Implement→Gate→Review는 파이프라인(대체로 DAG), Review↔FactFix는 품질 루프(사이클) 입니다. 둘을 같은 단어로 뭉개지 마세요.
DAG와 사이클 — 이름을 정확히
- DAG (Directed Acyclic Graph): 화살표가 순환하지 않는 방향 그래프. 에디토리얼 “단계 파이프라인”, 빌드 의존성, “Research가 끝나야 Outline”에 적합합니다.
- 사이클이 있는 그래프: 에이전트 피드백·재시도·리뷰 루프. LangGraph는 노드·엣지·공유
State로 이런 워크플로를 모델링하고, 실행은 super-step 단위로 진행합니다 (Graph API, as of 2026-08-03). - 실무 규칙: 바깥은 DAG(단계·게이트), 안쪽 노드는 루프(5편의 max_turns) . 바깥까지 사이클로 풀면 디버깅이 지옥이 됩니다.
PapaCoder의 Workflow Engine 카드도 파이프라인을 의존성을 지키는 agent DAG 로 실행한다고 적습니다 (agents/platform-intelligence/workflow-engine.md). 오케스트레이션 코드는 결정적(deterministic)이고, LLM은 노드 안에서만 확률적으로 움직입니다.
노드 · 엣지 · 상태
| 요소 | 의미 | 실무 예 |
|---|---|---|
| Node | 한 책임의 단계/역할 | Research, KR Writer, Fact Checker, Human Approve |
| Edge | 다음에 갈 곳 | Outline → KR Writer, accuracyFail → revise |
| Conditional edge | 관측 결과에 따른 분기 | 테스트 fail → Implement, pass → Review |
| State | 노드가 읽고 쓰는 공유 계약 | brief JSON, draft markdown, quality scores |
상태 스키마가 느슨하면 그래프는 “채팅 여러 개”와 다를 바 없습니다. 3편의 typed handoff 가 여기로 올라옵니다.
핸드오프 vs 도구로 부르는 에이전트
OpenAI 오케스트레이션 가이드는 두 패턴을 구분합니다 (Orchestration, as of 2026-08-03):
| 패턴 | 언제 | 무슨 일이 일어나나 |
|---|---|---|
| Handoffs | 전문가가 그 분기 대화를 소유해야 할 때 | 제어권이 전문가 에이전트로 이동 |
| Agents as tools | 매니저가 최종 답을 유지해야 할 때 | 매니저가 전문가를 유계 도구처럼 호출 |
SDK에서 handoff는 에이전트가 다른 에이전트에게 위임하는 장치입니다 (Handoffs). 그래프 용어로 말하면 엣지 위의 소유권 이전입니다. “전부 handoff”로 시작하면 라우팅 표면이 지저분해지니, 계약(도구·정책·프롬프트)이 실제로 달라질 때만 노드를 쪼개세요 — 가이드도 같은 조언을 합니다.
처음엔 모든 걸 한 Agent 모드에 몰아넣고 “알아서 리뷰까지”를 기대했습니다. 결과가 번갈아 좋아졌다 나빠지길래, Research / Implement / Review를 노드로 고정하고 엣지만 조건부로 바꿨더니 실패가 어디서 났는지 보이기 시작했습니다.
언제 사람에게 에스컬레이션 노드를 두나
그래프에 사람 노드를 넣는 기준(4·5편과 연결):
- Harness가 막을 수 없는 판단 — 제품 우선순위, 법적/브랜드, “이 초안을 올릴까”
- 루프 예산 소진 —
max_turns/ 동일 실패 N회 / 시간 박스 - 게이트 실패가 정책 — accuracyFail, 시크릿 경계, 프로덕션 배포
- 병렬 병합 충돌 — 두 Research가 모순일 때 자동 합의가 위험
에스컬레이션은 실패가 아니라 설계된 엣지입니다. “나중에 사람이 보겠지”를 암묵지로 두지 말고, 노드 이름과 진입 조건을 적으세요.
실습: 주말용 미니 그래프 스케치
코드 프레임워크 없이 먼저 텍스트 DAG 로 고정하세요.
# draft-pipeline.graph
nodes:
eic: { wip: 1, artifacts: [EditorialBrief] }
research: { depends: [eic], artifacts: [ResearchBrief] }
outline: { depends: [research], artifacts: [Outline] }
write_ko: { depends: [outline], artifacts: [draft.ko] }
write_en: { depends: [outline], artifacts: [draft.en] } # parallel OK after outline
review: { depends: [write_ko, write_en], gate: score>=85 }
facts: { depends: [review], gate: accuracyPass }
publish: { depends: [facts], owner: human } # never auto
edges_conditional:
review.on_fail -> write_ko # revise with new Observe
facts.on_fail -> review
any.max_turns -> human
LangGraph를 쓸 때는 StateGraph에 노드를 올리고 add_conditional_edges로 분기를 붙인 뒤 compile() 합니다. 사이클이 있으면 5편의 recursion_limit 을 바깥 예산으로 두세요.
OpenAI SDK 쪽이라면 triage → specialist를 handoff 엣지로, 요약 전용 헬퍼는 as tool 로 두는 식이 읽기 쉽습니다.
Cursor에서 그래프를 흉내 내는 법
- Task/서브에이전트로 Research 두 갈래를 병렬로 돌리고, 부모 채팅에서만 Merge하세요. 부모가 WIP=1 오케스트레이터입니다.
- 한 채팅에 “조사하고 구현하고 리뷰해”를 넣지 말고, 노드별 스레드 또는 명시적 단계 프롬프트로 나누세요.
- 머지 전에 각 노드 산출물을 파일(
research-brief.md등)로 고정 — 이게 공유 State입니다. - Stop 조건·훅·CI(4편) 없는 그래프는 예쁜 그림일 뿐입니다.
PapaCoder 에디토리얼 DAG
agents/editorial/workflow.md 파이프라인은 이미 그래프입니다.
EiC → Research → Outline → KR Writer → EN Writer
→ Humanizer → Reviewer → Fact Checker → SEO → Publisher(draft)
↘ accuracy/score fail → revise (새 입력)
Publisher → Admin(human publish)
시리즈 오케스트레이터(series-draft-run.md)는 이 DAG를 slug 하나(WIP=1) 로 실행합니다. 7편 현장 노트는 같은 지도를 제품 레포에 어떻게 붙였는지 이야기합니다.
FAQ
Q. 멀티에이전트(3편)랑 그래프는 뭐가 다르죠?
A. 3편은 역할과 계약, 6편은 역할이 시간에 따라 어떻게 연결되는지(토폴로지) 입니다. 역할 없이 그래프만 그리면 빈 상자가 됩니다.
Q. 모든 워크플로를 LangGraph로 짜야 하나요?
A. 아니요. 단계가 Straight line이면 루프+체크리스트로 충분합니다. 분기·병렬·게이트가 늘 때 그래프 비용이 이깁니다.
Q. DAG인데 리뷰 루프가 있으면 모순 아닌가요?
A. 바깥 단계 의존성은 DAG로 두고, 품질 재시도는 서브그래프/노드 내부 루프로 격리하면 됩니다.
Q. 에스컬레이션을 자동 재시도로 대체할 수 있나요?
A. 예산 안에서만. 예산을 넘기면 사람 노드가 정답입니다(5편).
소스
- LangGraph — Graph API — https://docs.langchain.com/oss/python/langgraph/graph-api (as of 2026-08-03)
- OpenAI — Orchestration and handoffs — https://developers.openai.com/api/docs/guides/agents/orchestration (as of 2026-08-03)
- OpenAI Agents SDK — Handoffs — https://openai.github.io/openai-agents-python/handoffs/ (as of 2026-08-03)
- PapaCoder —
agents/editorial/workflow.md,agents/platform-intelligence/workflow-engine.md
시리즈에서 다음
| # | 주제 |
|---|---|
| 01–05 | 도구 → 바이브 → 멀티에이전트 → 하네스 → 루프 |
| 06 | 그래프 (지금) |
| 07 | PapaCoder 현장 노트 — 같은 패턴을 제품/레포에 붙인 이야기 |
다음에 읽을 글: 현장 노트 — 이론을 책상 밖으로.
지금까지의 한 줄: 선으로 안 되면 지도를 그리고, 바깥은 DAG·안은 루프, 막히면 사람 노드로.