본문으로 바로가기

그래프 엔지니어링이란? LangGraph로 멀티 에이전트 오케스트레이션 실습 가이드

노드는 일을 하고, 엣지는 다음 실행을 결정하며, 공유 상태는 그 사이를 오가며 정보를 운반합니다. 이 그래프 엔지니어링 튜토리얼은 멀티 에이전트 그래프가 단일 루프보다 실제로 나을 때를 다루고, LangGraph에서 조건부 재시도 엣지를 갖춘 리서처-라이터-리뷰어 파이프라인 구축을 안내합니다.
업데이트됨 2026년 9월 25일  · 15분 읽기

AI와 탐험해 보세요

ChatGPTClaudePerplexity

에이전트에게 일을 하나만 맡기면 잘합니다. 세 개를 맡기면 두 번째 인계 시점에서 일이 벌어집니다. 1단계에서 찾은 것을 잊고, 자신의 초안을 후하게 평가하며, 결과물이 미완성인데 성공을 선언합니다.

이 패턴을 둘러싼 논쟁은 2026년 7월 중순에 폭발했습니다. "그래프 엔지니어링"이 X(구 트위터)에 등장하자 타임라인은 즉시 에이전트 루프의 종말을 선언하는 쪽과, 그 용어를 콘텐츠 농장용 채우기라고 부르는 쪽으로 갈라졌습니다.

제 견해는 그래프 엔지니어링이라는 라벨은 선택 사항이지만 그 밑바탕의 격상은 선택 사항이 아니며, 코드를 쓰기 전에 그 이유를 설명해 보겠다는 것입니다.

이번 달에 만드는 것의 대부분은 여전히 단일 루프여야 하며, 한 주를 낭비하는 가장 빠른 방법은 1개면 충분한 일을 상자 6개가 들어간 다이어그램으로 그리는 것입니다.

그래프 엔지니어링 한눈에 보기

에이전트 그래프는 세 부분으로 구성됩니다:

  • 노드는 일을 합니다.
  • 엣지는 다음에 무엇을 실행할지 결정합니다.
  • 하나의 공유 객체가 그 사이를 오가며, 지금까지 생성된 모든 것을 실어 나릅니다.

세 개의 번호 매긴 패널. 패널 1: research, write, review로 라벨이 붙은 개별 박스, 각기 "one job" 표시. 패널 2: write 박스에서 review 박스로 실선 화살표, END로 향하는 녹색 점선 "pass" 화살표, write로 되돌아가는 주황색 점선 "fail, try again" 화살표. 패널 3: 동일한 세 노드 위에 topic, notes, draft, verdict를 담은 하나의 shared state 박스.

작성자 제공 이미지. 뒤에서 구축할 파이프라인에 표시된 3가지 요소: 이름이 있는 3개의 노드, pass 엣지와 retry 엣지, 그리고 topic, notes, draft, verdict를 수집하는 하나의 상태 객체.

단일 에이전트가 경로를 임기응변으로 정하도록 두는 대신, 위 세 가지를 처음부터 선언하는 것이 그래프 엔지니어링이라는 용어가 설명하는 바입니다.

이 튜토리얼은 LangGraph를 사용해 파이썬으로 작동하는 리서처, 라이터, 리뷰어 파이프라인을 구축하며, 실패한 초안을 수정으로 되돌리는 조건부 엣지를 포함합니다.

파이썬, pip, 그리고 대형 언어 모델(LLM) 또는 AI 에이전트에 대한 기본 지식이 필요합니다. 에이전트가 처음이라면, 본 문서가 전제하는 개념은 Introduction to AI Agents 코스에서, 실습은 LangGraph 에이전트 튜토리얼에서 다룹니다.

그래프 엔지니어링이란?

그래프 엔지니어링은 에이전트 시스템의 제어 흐름을 모델의 재량에 맡기지 않고 코드로 명시하는 실천입니다.

어떤 전문화된 작업자가 존재하는지, 그 사이의 어떤 전이가 허용되는지, 그리고 그 전이를 따라 어떤 정보가 이동하는지 선언합니다.

에이전트는 여전히 자유롭게 추론하지만, 일 전체가 아니라 한 노드의 내부에서 추론합니다.

마지막 문장이 유일한 구분점입니다.

루프에서는 목표와 품질 기준을 설정하고, 에이전트가 이를 달성하기 위한 경로를 스스로 선택합니다. 그래프에서는 경로와 체크포인트를 고정하여, 모델의 자율성을 diff로 읽을 수 있는 구조 안에 한정합니다.

이 라벨은 2026년 7월 X에서 시끄러워졌지만, 시작은 그 전입니다. CodiumAI(현 Qodo)의 Itamar Friedman은 2024년 2월에 "프롬프트 엔지니어링에서 플로우(/그래프) 엔지니어링으로"의 전환을 설명했고, 그의 팀의 AlphaCodium 논문은 수치로 이를 보여주었습니다.

CodeContests 검증 세트에서 GPT-4 pass@5 정확도는 잘 설계된 단일 프롬프트로 19%였고, 다단계 플로우로 44%였습니다. 두 조건 모두 문제당 5회 시도이며 단발성이 아닙니다.

2026년 7월에 일어난 건 증폭이었습니다.

7월 18일, Peter Steinberger가 X에서 물었습니다. "여전히 루프를 얘기하나요, 아니면 이미 그래프로 옮겼나요?" 이는 Mike Masson이 프롬프트, 컨텍스트, 하니스, 루프, 그래프라는 사다리를 올린 지 일주일 뒤였습니다. 이 질문은 310만 조회를 얻었고, 널리 퍼진 표현은 이미 사용 중이었습니다.

반박도 빨랐습니다. LangGraph를 만든 팀의 LangChain 공동 창업자 Harrison Chase는 물었습니다. 이게 "기본적으로 그냥 langgraph 아닌가요?"라고.

Dale Everett는 반대편에서, 루프는 언제나 단일 노드 그래프였다고 주장하며 7월의 열광이 오래된 땅을 재발견한 것이라고 밀어붙였습니다. LangChain의 회고 글인 LangGraph와 함께한 3년의 그래프 엔지니어링도 유사한 관점을 취하며, 에이전트 그래프를 3년간 구축해온 패턴으로 정리합니다.

그래서 저는 이 용어를 유용한 약칭으로 분류합니다.

이 용어가 가져다준 것은, 예전에는 프레임워크 문서 속에 묻혀 있던 설계 질문들에 대한 공통된 이름입니다. 이름은 풀 리퀘스트에서 아키텍처를 두고 논쟁할 때 제값을 합니다.

그래프 엔지니어링이 아닌 것

그래프 엔지니어링은 실행 구조를 설명합니다. 이는 그 어휘를 차용하는 두 가지와 구분됩니다.

지식 그래프와 GraphRAG은 데이터를 설명합니다.

문서를 엔터티와 관계로 변환해, 검색 시스템이 사실 간 연결을 따라갈 수 있게 합니다. 도구, 스토리지, 평가 지표가 모두 다릅니다.

이 측면에 대해서는, 지식 그래프를 사용해 RAG 애플리케이션 구현하기 튜토리얼이 올바른 출발점이며, 그래프 이론 입문은 두 영역 아래에 놓인 수학을 다룹니다.

두 번째로, 이것은 새로운 능력이 아닙니다.

LangGraph, 구글의 Agent Development Kit(ADK), Microsoft AutoGen은 모두 이 라벨이 바이럴되기 전에 멀티 에이전트 오케스트레이션을 선보였습니다. StateGraph를 작성해 보셨다면 이미 이 작업을 하고 계셨던 겁니다.

많은 독자들은 지난 1년 동안 이를 "내 LangGraph 파이프라인"이라는 이름으로 해왔다는 사실을 알게 될 겁니다.

AI 엔지니어링 사다리

AI 엔지니어링의 각 층은 모델에서 한 걸음 더 바깥의 무언가에 대한 통제를 가져옵니다.

이 표를 읽는 유용한 방법은 우측 열입니다. 그 단계 하나를 건너뛰고 그 위에 구축하려 할 때 실제로 무엇이 망가지는지를 말해줍니다.

레이어 통제하는 것 건너뛰면 깨지는 것
프롬프트 요청의 문구 모델이 묻지 않은 질문에 답함
컨텍스트 어떤 입력이 모델에 도달하는지 잘 추론하지만 엉뚱한 자료 위에서 함
하니스 도구, 메모리, 파일 및 API 접근 채팅 창 밖의 어떤 것도 건드리지 못함
루프 완료까지 반복하는 사이클 일찍 멈추거나, 영원히 멈추지 않음
그래프 다음에 어떤 작업자가 무엇을 실행하는지 한 에이전트가 4명 몫을 하려다 3명을 잊어버림

한 단을 건너뛰는 것은 그래프 프로젝트가 실패하는 가장 흔한 방식이며, 실패는 드물게만 눈에 띕니다.

신뢰할 수 없는 3개의 노드를 서로 연결한다고 해서 신뢰할 수 있는 시스템이 평균적으로 나오지 않습니다.

그 결과는 더 많은 지점에서 실패하고, 실패당 비용이 더 들며, 불량 출력이 원인 노드에서 두 번의 인계를 거친 뒤에 나타나기 때문에 진단에 더 오래 걸리는 시스템입니다.

에이전트 그래프의 3가지 구성요소

에이전트 그래프는 3노드든 30노드든, 노드, 엣지, 공유 상태로 분해됩니다.

코드베이스에서 이 세 부분의 이름을 붙일 수 있게 되면, 대부분의 오케스트레이션 프레임워크는 문서 없이도 읽힙니다.

노드: 작업자

노드는 이름과 단일 책임을 가진 작업의 최소 단위입니다.

전용 프롬프트와 자체 도구를 갖춘 LLM 호출일 수도 있고, 데이터베이스를 조회하거나 스키마를 검증하거나 파일을 쓰는 평범한 파이썬 함수일 수도 있습니다.

의미 판단이 필요한 단계에만 모델 호출을 아껴 두세요.

규칙의 답이 정해져 있다면, 마이크로초 단위로 실행되고 비용이 들지 않으며 두 번 호출해도 같은 결과를 주는 파이썬에 넣으세요.

무언가를 분리해야 할지에 대한 제가 쓰는 테스트는 이렇습니다. 접속사를 쓰지 않고 한 문장으로 그 노드를 설명해 보세요.

"자료를 모으고 충분한지 판단한다"는 노드는 이미 테스트에 실패했습니다. 검색 부분을 교체하면 판단 부분을 건드리지 않을 수 없기 때문입니다.

엣지: 라우팅

엣지는 현재 노드가 끝난 뒤 무엇이 실행될지를 결정합니다.

네 가지 형태면 대부분의 구성을 포괄합니다:

  • 직선. 노드 A가 끝나면 노드 B를 시작합니다.
  • 조건부. 라우팅 함수가 현재 상태를 읽고 다음 노드의 이름을 반환합니다. 리뷰어의 평결이 갈림길이 되는 지점입니다. 승인하면 종료, 거절하면 초안을 작성자에게 되돌립니다.
  • 팬아웃. 한 노드가 동시에 실행되는 여러 노드를 시작합니다. 5개의 소스를 대기열 대신 병렬로 조회하는 방식입니다.
  • 팬인. 병렬 분기가 하나의 노드에서 다시 합류해 결과를 병합합니다.

엣지는 또한 중지 로직이 있어야 할 곳입니다. 재시도 상한, 품질 게이트, 에스컬레이션 규칙은 모두 라우팅 결정이며, 이를 엣지 함수에 두면 노드 본문을 뒤지지 않고 제어 흐름을 한 곳에서 감시할 수 있습니다.

공유 상태: 시스템의 메모리

공유 상태는 실행이 진행되는 동안 모든 노드가 읽고 쓰는 단일 객체입니다.

이것이 없다면, 이웃 작업을 하는 여러 에이전트가 서로에게 아무것도 전달하지 않는 셈이므로, 라이터는 리서처가 찾은 것을 볼 수 없고, 리뷰어는 둘 다 볼 수 없습니다.

LangGraph에서 상태는 보통 TypedDict입니다.

우리의 상태는 주제, 리서처의 노트, 현재 초안, 리뷰어의 평결과 피드백, 수정 횟수를 누적합니다. 각 노드는 자신이 변경한 필드만 반환하고, 프레임워크는 그 반환 값을 실행 중인 객체에 병합합니다.

쓰기 소유권은 그래프가 먼저 부식되는 지점입니다.

코드를 작성하기 전에 어떤 노드가 어떤 필드를 쓸 수 있는지 결정하세요. 3개의 서로 다른 노드가 덮어쓸 수 있는 상태 객체는, 이미 자신에게 예약해 둔 디버깅 세션과 같습니다.

루프 엔지니어링 vs 그래프 엔지니어링: 언제 무엇을 쓸까

루프 엔지니어링은 단일 에이전트가 완료까지 반복하는 사이클을 설계하고, 그래프 엔지니어링은 그 여러 사이클 사이의 조정을 설계합니다.

이것이 본 문서에서 가장 중요한 결정이므로, 튜토리얼보다 앞에 둡니다.

기본 답은 루프입니다.

엄격한 검증기를 갖춘, 범위가 잘 정의된 단일 에이전트는 동일한 일을 하는 어떤 그래프보다도 구축이 빠르고, 실행 비용이 낮으며, 디버깅이 훨씬 쉽습니다.

이것은 제 선호일 뿐만이 아닙니다.

UC 버클리 팀(제1저자 Mert Cemri)은 멀티 에이전트가 단일 에이전트 대비 얻는 이익이 종종 미미하다는 관찰에서 출발해, 7개 멀티 에이전트 프레임워크의 1,600개 이상의 실행 추적을 주석 달아 원인을 파악합니다(arXiv:2503.13657, v3).

그들의 분류는 그중 150건을 면밀히 읽어 구축되었고, 14개의 뚜렷한 실패 양상을 이름 붙였습니다.

그 14가지 양상은 시스템 설계 이슈, 에이전트 간 불일치, 태스크 검증의 3가지 범주로 나뉩니다.

세 번째 범주는 리뷰어 노드에 도달할 때까지 기억해 두세요.

의사결정 표: 루프 vs 그래프

이 항목들은 체크리스트가 아니라 트리거로 보세요.

오른쪽 열에서 하나가 명확히 예스면 충분하며, 흐릿한 다섯 개는 충분하지 않습니다.

작업에 대한 질문 루프로 처리 그래프가 필요
작업을 하나의 지시문으로 쓸 수 있나요? 가능, 한 사람이 처음부터 끝까지 따를 수 있음 서로 다른 두 역할 간 인계처럼 읽힘
모든 단계가 같은 모델을 원하나요? 처음부터 끝까지 하나의 모델과 도구셋 수집은 저렴하고 빠름을, 판단은 예리함을 원함
서로 의존하지 않는 단계가 있나요? 각 단계가 이전 단계의 출력을 필요로 함 동시에 실행될 수 있는 여러 조회
출력이 충분히 좋은지 누가 결정하나요? 에이전트가 자신의 작업을 다시 읽음 작성하지 않은 무엇인가가 승인해야 함
어떤 단계가 실패하면 어떻게 해야 하나요? 재시도하고 계속 진행 실패를 격리해 나머지 실행이 살아남게 함
누군가가 지나간 경로를 감사해야 하나요? 트레이스는 당신과 팀원을 위한 것 외부인이 어떤 단계가 왜 실행되었는지 봐야 함

제가 가장 자주 마주치는 과도한 엔지니어링 버전은 에이전트와조차 관련이 없습니다. 800개 호텔 주소 목록을 정제하고 지오코딩해야 하는데, 5노드 그래프로 도착합니다. 로더 노드, 정규화 노드, 지오코더 노드, 검증 노드, 기록 노드, 이들 사이로 공유 상태가 실로 꿰듯 이어집니다.

이 단계들은 모두 결정적이므로, 실제로 만든 것은 프레임워크를 걸친 40줄짜리 파이썬 스크립트입니다. 이제 행(row)마다 비용이 들고, pandas라면 결코 일어나지 않을 방식으로 실패합니다.

적정 규모의 버전이 바로 지금 만들 버전입니다.

짧은 리서치 브리프를 만드는 일은 단일 루프가 애쓰는 작업으로 갈라집니다. 원자료 수집, 이를 산문으로 바꾸기, 그리고 그 산문을 바깥에서 심사하기.

세 번째 단계가 그래프가 존재하는 이유입니다. 자신의 초안을 자신의 에이전트가 리뷰하는 것은 리뷰가 아니기 때문입니다.

그래프가 제값을 하는 신호

세 가지가 노드를 정당화합니다.

추가한 각 노드마다 이 중 하나를 가리키지 못한다면, 그 노드를 삭제하고 이웃에 접어 넣으세요.

첫째는 진짜 전문화입니다.

우리의 리서처는 저렴하고 빠른 모델과, 프로덕션에서는 검색 도구를 원합니다. 라이터는 그 어떤 것도 원하지 않으며 더 강한 모델의 이점을 봅니다. 따라서 이 분리는 다이어그램을 꾸미는 게 아니라 실제 일을 합니다.

둘째, 실제로 체감할 병렬성입니다.

팬아웃은 분기가 독립적이고 누군가에게 벽시계 시간 절감이 중요할 때 이득이며, 둘 다 아니라면 복잡도만 늘립니다.

셋째, 그리고 제가 가장 강하게 옹호할 것은, 독립적인 검증입니다.

자기 숙제를 채점하는 에이전트는 관대하게 채점합니다. 따라서 초안에 대한 읽기 전용 접근만을 가진 별도의 리뷰어 노드는 보통 어떤 그래프에서든 가장 가치 있는 노드입니다.

프레임워크 수준에서 서로 다른 라이브러리가 이러한 패턴을 어떻게 표현하는지 보려면, CrewAI vs LangGraph vs AutoGen 비교가 트레이드오프를 정리합니다.

LangGraph로 멀티 에이전트 그래프 구축하기

리서처, 라이터, 리뷰어로 구성된 LangGraph 멀티 에이전트 파이프라인을 구축해, 짧은 리서치 브리프를 만들고 실패한 초안을 수정으로 되돌립니다.

LangGraph는 상태를 가진 에이전트를 위한 저수준 오케스트레이션 프레임워크이며, 그 StateGraph는 앞 절의 노드, 엣지, 상태와 거의 일대일로 대응합니다.

아래 모든 내용은 2026년 9월의 langgraph 1.2.11과 langchain-anthropic 1.7.1 기준으로 확인했습니다.

이 라이브러리가 처음이라면 LangGraph 튜토리얼에서 기초를 다지세요. 이 절은 속도가 빠르며, LangChain vs LangGraph vs LangSmith vs LangFlow 가이드는 이 제품군의 각 구성요소가 무엇을 하는지 구분해 줍니다.

연구자, 작가, 리뷰어 노드가 있는 3노드 에이전트 그래프 다이어그램. 승인 시 종료 상태로 가는 조건부 엣지와, 점선으로 라이터로 되돌아가는 수정 엣지.

작성자 제공 이미지. 지금 구축할 파이프라인. 실선은 3개의 직선 엣지, 점선과 점묘선은 하나의 조건부 엣지에서 갈라지는 두 분기입니다.

설치 및 공유 상태 정의

패키지를 설치합니다. 키를 소스 밖에 두기 위해 python-dotenv도 함께 설치하세요:

pip install langgraph langchain-anthropic python-dotenv

스크립트 옆에 .env 파일을 만드세요:

ANTHROPIC_API_KEY=sk-ant-your-key-here

이제 임포트와 상태 스키마입니다. 먼저 TypedDict를 작성하는 데 2분을 쓰는 가치는 큽니다. 모든 노드가 동의하는 계약이기 때문입니다:

from typing import Literal, TypedDict
 
from dotenv import load_dotenv
from langchain_anthropic import ChatAnthropic
from langgraph.graph import END, START, StateGraph
 
load_dotenv()
 
MAX_REVISIONS = 3
 
# A cheap model for gathering, a stronger one for writing and reviewing.
fast_llm = ChatAnthropic(model="claude-haiku-4-5-20251001", max_tokens=2000)
main_llm = ChatAnthropic(model="claude-sonnet-5", max_tokens=2000)
 
 
class BriefState(TypedDict):
    topic: str
    notes: str
    draft: str
    verdict: str
    feedback: str
    revisions: int

모델은 하나가 아니라 둘입니다. 이는 의사결정 표의 "단계별로 다른 모델" 트리거가 실제 코드로 드러난 것입니다. 리서치는 고볼륨·저판단 작업이어서 비싼 모델이 필요 없습니다.

MAX_REVISIONS는 조용하지만 중요한 역할을 합니다.

상한이 없다면, 엄격한 리뷰어와 완고한 라이터가 초안을 서로 주고받다 인보이스가 흥미로워질 수 있습니다.

리서처, 라이터, 리뷰어 노드 만들기

모든 노드는 동일한 계약을 따릅니다. 현재 상태를 받고, 자신의 일을 하나 수행하며, 자신이 변경한 필드만 담은 딕셔너리를 반환합니다.

리서처는 원자료를 수집해 notes에 씁니다:

def researcher(state: BriefState) -> dict:
    """Gather raw material and write it into shared state as notes."""
    prompt = (
        f"Topic: {state['topic']}\n\n"
        "List 6 to 8 concrete facts, numbers, or named examples a writer "
        "could use. Bullet points only. No introduction, no conclusion."
    )
    response = fast_llm.invoke(prompt)
    return {"notes": response.text}

프로덕션 버전의 이 노드는 모델의 자체 지식에 의존하는 대신 검색 도구를 호출할 것입니다.

그래프 구조가 드러나도록 .invoke() 한 번으로 두었으니, 생성된 노트는 검증되지 않은 것으로 보세요.

라이터는 그 노트를 읽고 초안을 작성합니다. 또한 리뷰어 피드백을 확인해, 재시도 엣지가 작동할 근거를 제공합니다:

def writer(state: BriefState) -> dict:
    """Turn notes into a draft, applying reviewer feedback on a retry."""
    feedback = state.get("feedback", "")
    revision_note = (
        f"\n\nThe reviewer rejected your last draft. Fix this: {feedback}"
        if feedback
        else ""
    )
    prompt = (
        f"Write a 200-word brief on: {state['topic']}\n\n"
        f"Use only these notes:\n{state['notes']}{revision_note}"
    )
    response = main_llm.invoke(prompt)
    return {
        "draft": response.text,
        "revisions": state.get("revisions", 0) + 1,
    }

리뷰어는 초안을 점수화합니다.

리뷰어는 라이터의 추론을 보지 못했고 텍스트를 생산하지도 않았으므로, 결과에 대해 직설적일 수 있습니다.

이는 버클리 분류의 세 번째 실패 범주가 독립 노드로 주어진 것입니다.

태스크 검증은 독립적으로 출력을 확인하는 것이 없을 때 무너집니다. 따라서 해결책은 자신의 숙제를 스스로 채점할 수 없는 작업자를 두는 것입니다:

def reviewer(state: BriefState) -> dict:
    """Score the draft. This node never writes, so it can be honest."""
    prompt = (
        "You are a skeptical editor. Reject the draft if it makes a claim "
        "the notes do not support, or if it runs past 250 words.\n\n"
        f"NOTES:\n{state['notes']}\n\nDRAFT:\n{state['draft']}\n\n"
        "Reply with APPROVE or REVISE on the first line. "
        "If REVISE, add one line explaining the single biggest problem."
    )
    response = main_llm.invoke(prompt)
    text = response.text.strip()
    verdict = "approve" if text.upper().startswith("APPROVE") else "revise"
    return {"verdict": verdict, "feedback": text}

세 노드 모두에서 .content가 아닌 .text에 주목하세요.

둘 다 단순 응답에는 문자열을 반환하지만, .text는 응답이 여러 콘텐츠 블록으로 올 때도 올바르게 처리합니다. 이는 나중에 혼란스러운 AttributeError: 'list' object has no attribute 'strip'를 피하게 합니다.

첫 줄에서 평결을 파싱하면 읽기 쉽지만, 취약합니다.

무인으로 돌아가는 작업에는 이 문자열 체크를 LangChain의 구조화된 출력으로 바꿔 평결이 접두사가 아닌 타입 필드로 돌아오도록 하세요. 모델이 접두사를 지킬 것이라 기대하지 않게 됩니다.

엣지 연결과 조건부 재시도 추가

라우팅 함수가 조건부 엣지입니다. 리뷰어가 실행된 뒤의 상태를 읽고 다음에 일어날 일의 이름을 반환합니다:

def route_after_review(state: BriefState) -> Literal["writer", "__end__"]:
    """The conditional edge: ship it, or send it back to the writer."""
    if state["verdict"] == "approve":
        return END
    # revisions counts every draft, including the first, so ">" allows
    # 1 original draft plus MAX_REVISIONS rewrites.
    if state["revisions"] > MAX_REVISIONS:
        return END
    return "writer"

그 함수는 조용히 두세요. 안에 print()가 있으면 스트림 루프가 아직 이전 청크를 출력하는 동안 stdout으로 흘러, 상한 공지가 한 단계 일찍 나타나 트레이스 순서가 어긋나 보입니다.

수정 상한은 노드 내부가 아니라 이곳에 둡니다. 중지는 제어 흐름의 결정이며, 제어 흐름은 엣지의 영역이기 때문입니다.

이제 그래프를 조립합니다. 노드, 그다음 엣지, 그리고 컴파일:

builder = StateGraph(BriefState)
 
builder.add_node("researcher", researcher)
builder.add_node("writer", writer)
builder.add_node("reviewer", reviewer)
 
builder.add_edge(START, "researcher")
builder.add_edge("researcher", "writer")
builder.add_edge("writer", "reviewer")
builder.add_conditional_edges(
    "reviewer",
    route_after_review,
    {"writer": "writer", END: END},
)
 
graph = builder.compile()

.add_conditional_edges()의 세 번째 인자는 경로 맵입니다.

라우팅 함수가 반환할 수 있는 모든 목적지를 나열하며, LangGraph는 어떤 노드도 실행되기 전에 그 분기를 그리는 데 이 정보를 사용합니다.

그래프 실행과 단계별 확인

초기 상태로 컴파일된 그래프를 호출합니다. 실행이 진행되며 다른 필드가 채워지므로, 값이 필요한 것은 topic과 revisions뿐입니다:

result = graph.invoke(
    {"topic": "Why Postgres beat MongoDB for most startups", "revisions": 0}
)
 
if result["verdict"] != "approve":
    print(f"Hit the {MAX_REVISIONS}-revision cap. Shipped as is.")
 
print(f"Revisions: {result['revisions']}")
print(f"Verdict: {result['verdict']}")
print(result["draft"])

이 방식은 최종 상태만 제공하므로, 실행이 탈선했을 때 많은 도움이 되지 않습니다.

stream_mode="updates"로 .invoke()를 .stream()으로 바꿔 각 노드가 무엇을 썼는지 보세요. 각 호출은 자체 모델 호출을 가진 별도의 실행이므로, 둘 중 하나만 사용하고 둘 다 실행하지 마세요:

for step in graph.stream(
    {"topic": "Why Postgres beat MongoDB for most startups", "revisions": 0},
    stream_mode="updates",
):
    for node, update in step.items():
        print(f"[{node}] wrote: {list(update.keys())}")

리뷰어가 첫 초안을 거절한 실행에서는 다음이 출력됩니다:

[researcher] wrote: ['notes']
[writer] wrote: ['draft', 'revisions']
[reviewer] wrote: ['verdict', 'feedback']
[writer] wrote: ['draft', 'revisions']
[reviewer] wrote: ['verdict', 'feedback']

최종 상태가 숨기는 두 가지가 여기서는 보입니다.

리서처는 한 번만 실행되었고, 그 노트는 두 번의 작성 과정 내내 유지되었습니다. 즉, 재시도가 재리서치를 하지 않습니다. 각 노드는 또한 자신 소유의 필드만 건드려, 앞서의 쓰기 소유권 규칙을 검증 가능한 형태로 바꿉니다.

이참에 호출 횟수를 세세요.

해당 거절 경로는 동일 작업의 단일 루프 버전에 비해 대략 1회 대신 5회의 모델 호출이 듭니다. 추가된 4회가 무엇을 사줬는지는 평결을 로깅해 직접 읽어 보는 수밖에 없습니다.

컴파일된 그래프 시각화

무엇을 만들었는지 모양을 보기 위해 추가 도구가 필요하지 않습니다:

print(graph.get_graph().draw_ascii())      # needs: pip install grandalf
print(graph.get_graph().draw_mermaid())    # paste into any Mermaid renderer

Mermaid 출력은 reviewer에서 __end__와 writer로 향하는 조건부 분기를 점선으로 렌더링합니다.

이는 어떤 노드도 실행하기 전에 재시도 엣지가 존재함을 확인해 줍니다. ASCII 보기는 시작에서 끝으로 가는 직선 경로만 그리므로, 루프를 보고 싶을 때는 Mermaid 출력을 사용하세요.

터미널 출력: 시작과 끝 표시 사이에 연구자, 작가, 리뷰어 노드가 수직 상자로 그려진 다이어그램.

작성자 스크린샷. 터미널에 __start__, researcher, writer, reviewer, __end__가 수직으로 연결된 .draw_ascii() 출력이 표시됩니다.

노드별 상태 검사와 함께 단계별 디버깅을 하려면, LangGraph Studio가 로컬 서버에 연결됩니다. 별도 패키지와 구성 파일이 필요하므로 pip install "langgraph-cli[inmem]"를 실행하고, 컴파일된 graph 객체를 가리키는 langgraph.json을 추가한 뒤, langgraph dev를 실행하고 출력되는 Studio URL을 엽니다.

LangGraph Studio 가이드는 인터페이스를 안내합니다(2024년에 작성되었으므로 설정 단계는 위 명령과 대조해 확인하세요). LangGraph 에이전트 튜토리얼은 우리 리서처처럼 노드에 실제 도구를 추가하는 방법을 다룹니다.

범위에 대한 한 가지 메모.

이 파이프라인은 순차적이어서, 리서처가 여러 소스를 동시에 조회하고, 조인 노드가 결과를 합치는 팬아웃 패턴을 보여주지 않습니다.

이는 자연스러운 다음 확장이며, 비용이 가장 빠르게 불어나는 지점이기도 합니다.

그래프 엔지니어링 모범 사례

에이전틱 AI 그래프 엔지니어링에서의 실패 양상은 이름 붙일 만큼 자주 반복됩니다. 배포 전에 제가 확인하는 세 가지입니다.

1. 그래프 전에 루프를 완성하세요

모든 노드는 그 자체로 하나의 루프이며, 프롬프트, 도구, 완료 정의를 가집니다.

불안정한 3개의 노드를 연결하면, 표면적이 3배로 늘고 디버깅 스토리가 훨씬 나빠진 불안정한 시스템이 생깁니다.

먼저 하나의 노드를 단독으로 제대로 작동시키세요.

직접 호출했을 때 모호한 노트를 반환하는 리서처는 그래프 안에서도 모호한 노트를 반환하며, 다운스트림의 라이터는 이를 근거로 자신 있게 작성합니다.

2. 노드를 작고 단일 목적에 맞게 유지

엣지에 있어야 할 로직을 노드에 넣고 싶은 유혹을 이기세요.

중지 조건, 분기 결정, 재시도 상한은 라우팅이며, 라우팅은 모든 것을 한 번에 읽을 수 있는 엣지 함수에 있어야 합니다.

앞서의 무접속사 테스트를 적용하세요.

소스를 검색하고 그 수가 충분한지 결정하는 노드는, 함수 시그니처만 공유하는 두 개의 노드입니다.

3. 비용을 주시하세요

팬아웃과 재시도 루프는 다이어그램에서는 전혀 보이지 않는 방식으로 토큰 사용량을 증폭시킵니다.

3회 재시도 상한이 있는 조인 노드에 5방향 팬아웃을 붙이면 호출이 5회가 아닙니다. 재시도 위치에 따라 조인을 세기 전에도 15회 이상이 될 수 있습니다.

우리가 MAX_REVISIONS로 한 것처럼 상한을 명시적으로 설정하세요. 그리고 노드별 토큰 사용량을 로깅해 일주일 뒤에 읽어보세요. 보통 가장 저렴하다고 가정한 노드가 가장 자주 실행됩니다.

프레임워크 선택

AutoGen은 여전히 그래프 오케스트레이션에 추천되곤 하며, 실험적 GraphFlow 작업은 실질적인 선행 연구였습니다. 하지만 저장소는 2026년 9월 기준 유지보수 모드로, 신규 기능이 없습니다.

Microsoft는 신규 사용자에게 자체 그래프 기반 워크플로를 제공하는 Microsoft Agent Framework를 안내하며, 공개된 마이그레이션 가이드를 제공합니다.

오늘 시작한다면 LangGraph, 구글 ADK, Microsoft Agent Framework가 더 안전한 선택이며, Building AI Agents with Google ADK 코스는 ADK를 심층적으로 다룹니다.

마무리

그래프 엔지니어링은 루프 엔지니어링 위의 조정 계층입니다.

노드는 일을 하고, 엣지는 다음에 무엇이 실행될지 결정하며, 하나의 공유 객체가 그 사이를 오가며 정보를 운반합니다.

2026년 7월의 타임라인 소음을 걷어내면, 이것이 전부입니다.

우리의 파이프라인은 의도적으로 작게 유지했습니다. 3개의 노드, 4개의 엣지 선언(그중 1개는 조건부라 2개의 분기가 그려짐), 그리고 재시도가 폭주하지 않도록 하는 수정 상한.

이 정도 구조만으로도 작성자가 아닌 무엇인가가 초안을 리뷰하도록 만들 수 있었고, 이 단 하나의 속성이 루프가 제공하지 못하는 것이었습니다.

작업이 서로 다른 전문가를 요하는 단계로 갈라질 때, 그리고 그 전에는 결코, 그래프를 선택하세요. 회의론자들은 기계적 원리가 수십 년 전부터 있었고, 그 용어를 둘러싼 글의 대부분이 소음이라는 점에서 옳았습니다.

그리고 화요일 오후에 중요한 부분에서도 그들은 옳았습니다.

루프 모양의 문제에 약한 검증기를 붙인다고 해서, 상자를 더 그려 넣었다고 나아지지 않습니다.

이 패턴을 더 확장하려면, Multi-Agent Systems with LangGraph 코스가 이 튜토리얼이 다루지 않은 수퍼바이저 및 네트워크 설계를 소개합니다.

용어의 데이터 쪽을 이어가려면 Graph RAG with LangChain and Neo4j가 좋은 다음 단계입니다. 오케스트레이션 쪽에 머무르려면 Text-to-Query Agents with MongoDB and LangGraph가 라이브 데이터베이스를 대상으로 LangGraph 파이프라인을 구축하며, LLM Agents Explained는 그 모든 것 아래의 아키텍처를 보완합니다.

완성된 스크립트는 제 GitHub 저장소에 있으며, 그래프 렌더링 도우미와 실행당 비용에 대한 짧은 노트를 포함합니다.

FAQs

What is graph engineering?

그래프 엔지니어링은 에이전트 시스템의 제어 흐름을 명시적으로 작성하는 실천입니다. 이름 붙은 작업자, 그 사이에 선언된 경로, 그리고 모두가 공유하는 하나의 상태 객체를 갖습니다. 이 표현은 2024년 2월 Itamar Friedman이 프롬프트 엔지니어링에서 플로우(/그래프) 엔지니어링으로의 전환을 설명하면서 거슬러 올라가며, 2026년 7월 X에서 대중화되었습니다. 어휘는 유행보다 오래됐고, 능력은 둘보다 더 오래됐습니다.

Is graph engineering the same as knowledge graph engineering or GraphRAG?

아니요. 지식 그래프와 GraphRAG은 데이터를 엔터티와 관계로 모델링해 검색 시스템이 연결을 따라가게 합니다. 그래프 엔지니어링은 실행을 모델링합니다. 다음에 어떤 에이전트가 실행되고, 실행 시 무엇을 받는지입니다.

When should I use a graph instead of a single agent loop?

세 가지 신호가 정당화합니다. 진짜 전문화(단계가 다른 모델이나 도구셋을 원함), 체감 가능한 병렬성, 그리고 출력을 만들지 않은 무언가에 의한 독립 검증입니다. 이 중 하나라도 없다면, 엄격한 검증기를 갖춘 잘 범위 지정된 루프가 더 저렴하고 훨씬 디버그하기 쉽습니다.

Do I need LangGraph to do graph engineering?

아니요. Google ADK는 순차, 병렬, 루프 워크플로 에이전트를 제공하고, Microsoft Agent Framework는 AutoGen이 시작한 오케스트레이션 작업을 이어갑니다. LangGraph가 가장 흔한 파이썬 진입점인 이유는 그 StateGraph가 노드, 엣지, 상태에 일대일로 대응하기 때문입니다.

How much more expensive is a graph than a loop?

구축 전에 호출 수를 세세요. 이 튜토리얼의 3노드 파이프라인은 리뷰어가 첫 초안을 승인하면 모델 호출이 3회, 반려하면 5회 듭니다. 동일 작업의 단일 루프 버전은 대략 1회입니다. 팬아웃은 이를 다시 늘리므로, 첫 실행 전에 재시도 상한을 설정하세요.

주제
인공지능
대규모 언어 모델
AI Agents

Top DataCamp Courses

{count, plural, one {강의} other {강의}}

LangGraph로 배우는 Multi-Agent Systems

{hours}시간 {minutes}분
8.9K
LangGraph 프레임워크에서 새로운 에이전트 설계 패턴을 적용해 강력한 멀티 에이전트 시스템을 구축하세요.
자세히 보기Right Arrow
강의 시작
더 보기Right Arrow