Graph Engineering: 루프 하나로 부족해질 때

여러 에이전트 루프를 조율하는 계층을 그래프(노드, 엣지, 상태)로 보는 관점과, 노드 선별·공유 상태·라우팅·상호 동의라는 네 가지 난제. 대부분의 경우 그래프는 과하다는 비용 근거도 함께 담았다.

Cover image

루프 엔지니어링(loop engineering)은 6주쯤 주목받다가 타임라인에서 밀려났습니다.

7월 18일, OpenClaw를 만든 Peter Steinberger가 아홉 단어짜리 질문을 올렸습니다. "Are we still talking loops or did we shift to graphs yet?"

몇 시간 뒤 Hamel Husain이 "Loop Engineering Is Dead. Enter Graph Engineering."이라는 글을 냈습니다.

둘 다 절반은 농담이었습니다. 이 분야는 이름을 워낙 빨리 갈아치워서, 이름 바꾸기를 놀리는 일 자체가 하나의 장르가 됐습니다.

그런데 그 농담이 진짜 문제를 짚었습니다. 함께 돌아가야 하는 루프가 여러 개 생기는 순간 조율 문제가 생깁니다. 그리고 엔지니어들은 늘 그래프로 조율을 설명해 왔습니다.

이게 그래프 엔지니어링의 전부입니다. 이제 알맹이와 밈을 갈라 보겠습니다.

먼저, 그래프 자체

그래프는 세 가지로 이뤄집니다.

graph.add_node("research", research_agent)
graph.add_node("write", writer_agent)
graph.add_node("review", reviewer_agent)

graph.add_edge("research", "write")
graph.add_edge("write", "review")
graph.add_conditional_edge("review",
    lambda state: "done" if state.approved else "write")

거의 모든 예제가 쓰는 기본 그래프입니다. 조사자가 자료를 모으고, 작성자가 초안을 쓰고, 리뷰어가 판단합니다. 리뷰를 통과하면 실행이 끝납니다. 실패하면 엣지가 초안을 작성자에게 되돌려 보냅니다.

노드 셋, 엣지 넷, 그중 하나는 루프입니다.

여기서부터 모든 게 다시 보입니다. 에이전트 루프 하나는 자기 자신을 가리키는 엣지가 달린 노드 하나짜리 그래프일 뿐입니다. 그래프는 루프를 대체하지 않습니다. 루프를 잇고 관리합니다.

스택은 계속 커졌습니다

AI의 무게중심은 모델에서 계속 멀어지고 있고, 옮겨 갈 때마다 이름이 하나씩 붙었습니다.

각 계층은 앞 계층을 감쌉니다. 그래프는 루프로 이뤄지고, 루프마다 좋은 하네스가 필요하고, 하네스 호출 하나하나가 컨텍스트 문제이며, 모든 컨텍스트 안에는 프롬프트가 있습니다. 아래 계층을 건너뛰면 그래프는 더 복잡한 방식으로 실패할 뿐입니다.

솔직하게 짚을 게 하나 더 있습니다. 이 중에 새로운 기술은 없습니다. LangGraph는 공유 상태 위의 노드와 엣지라는 바로 이 모델을 2024년 1월에 이미 내놨습니다. Microsoft의 AutoGen에는 GraphFlow가 있고, Google은 ADK 2.0의 workflow runtime 전체를 같은 아이디어 위에 세웠습니다. 이름은 새롭지만 실천은 새롭지 않습니다. Hamel의 글에 달린 최고 인기 답글이 그냥 "welcome back, langchain"이었던 이유입니다.

그러니 이 분야가 발명한 건 그래프가 아닙니다. 언제 그래프를 써야 하는지, 그리고 그래프가 썩지 않게 어떻게 지킬지를 아는 것입니다. 거기에 어려운 문제가 넷 있습니다.

어려운 부분 1: 노드가 존재할 자격이 있는지 아는 것

가장 흔한 실패는 "이 PDF를 요약해줘"를 fetcher, chunker, summarizer, reviewer, formatter로 이뤄진 다섯 노드짜리 그래프로 만드는 것입니다.

노드는 진짜 전문성을 나타낼 때만 자리를 얻습니다. 다른 모델이거나, 다른 도구 모음이거나, 읽기 전용 리뷰어처럼 정말 따로 떨어진 역할일 때입니다. 기존 루프 안에 그냥 넣어도 되는 단계는 노드가 아닙니다.

이 주제로 글을 쓰는 실무자들에게서 쓸 만한 기준이 나옵니다. 그래프를 냅킨 한 장에 그릴 수 없다면 너무 복잡한 것입니다. 그리고 노드 둘을 하나로 합쳤을 때 잃는 게 없다면, 애초에 둘이 아니었습니다.

어려운 부분 2: 공유 상태를 깨끗하게 유지하기

루프에서는 컨텍스트 부패(context rot)가 실패 양상입니다. 그래프에서는 같은 병이 공유 상태로 옮겨 갑니다.

모든 노드가 상태 객체에 쓰기 때문에, 2번 노드가 엉성하게 써넣은 값을 5번 노드는 마치 확실한 입력처럼 받아들입니다. 결과가 틀릴 때까지 아무도 눈치채지 못하고, 그때쯤이면 잘못된 데이터가 시스템 절반을 이미 흘러 지나갔습니다.

해법은 단순하고 지루하지만 잘 듣습니다. 상태에 타입 스키마를 주세요. 어떤 노드가 어떤 필드에 쓸 수 있는지 명시적으로 정하세요. 노드 사이에서 상태를 체크포인트로 남겨서, 실행을 다시 돌려 보며 어디서 잘못됐는지 정확히 볼 수 있게 하세요.

리플레이에는 주의가 하나 따릅니다. 체크포인트 이후 노드는 다시 실행되므로, 메일을 보내거나 기록을 남기는 것처럼 외부 부작용이 있는 노드는 두 번 실행돼도 안전해야 합니다.

어려운 부분 3: 믿을 수 있는 라우팅

엣지는 결정이고, 문제는 그 결정을 누가 내리느냐입니다.

모델이 경로를 정하면 유연함과 불안정함을 한 묶음으로 얻습니다. 같은 상태가 실행마다 다른 경로를 타고, 그러면 디버깅이 괴로워집니다.

ADK 2.0을 만들며 Google이 세운 설계 원칙이 이 논의에서 가장 깔끔한 입장입니다. 예측 가능한 라우팅은 결정적 코드가 맡고, 모델은 진짜 판단이 필요한 단계만 다뤄야 한다는 것입니다.

조건을 확인할 수 있는 곳이면 코드로 경로를 정하고, 해석이 정말 필요한 곳에만 모델 호출을 쓰세요.

어려운 부분 4: 에이전트끼리 서로 동의하는 문제

루프 엔지니어링의 가장 날카로운 규칙은 에이전트가 자기 숙제를 스스로 채점하게 두지 말라는 것이었습니다.

그래프는 판돈을 키웁니다. 같은 베이스 모델로 만들고 같은 결함 있는 컨텍스트를 읽는 에이전트 스무 개는 서로 기꺼이 동의할 것이고, 모델은 측정될 만큼 뚜렷하게 자기 출력을 더 좋아합니다.

그 결과는 산업 규모의 "잘 정리된 헛소리"처럼 느껴집니다. 틀린 답을 흠잡을 데 없는 구조가 감싸고 있는 것입니다.

해법은 실제로 힘을 가진 리뷰어 노드입니다. 다른 모델로 돌리고, 전체 대화 대신 새 컨텍스트를 주고, 판정을 그래프가 지어낼 수 없는 증거에 묶으세요. 실제로 돌아간 테스트나 실제로 컴파일된 코드 같은 것 말입니다.

Cognition도 자사 코딩 에이전트 Devin을 1년 굴린 뒤 같은 결론에 닿았습니다. 이들이 쓰는 방식은 여러 에이전트가 작업물을 읽고 의견을 낼 수 있게 하되, 무언가를 바꿀 수 있는 에이전트는 언제나 하나뿐입니다.

그 분리가 쓸모 있는 대목입니다. 읽기는 병렬로 해도 안전합니다. 나쁜 의견은 누군가 그에 따라 행동하기 전까지 아무 비용도 들지 않기 때문입니다. 피해는 쓰기에서 생기므로, 눈에 보이는 한 곳에 몰아 둡니다.

그래프가 과한 경우

솔직한 답은 대부분의 경우입니다.

Anthropic이 공개한 수치가 비용을 구체적으로 보여 줍니다. 에이전트 하나는 일반 대화의 약 4배 토큰을 쓰고, 멀티 에이전트 시스템은 약 15배를 씁니다. 노드를 더할 때마다 그 값이 곱해집니다.

작업이 진짜로 병렬화되는 경우라면 천장도 실재합니다. Anthropic의 멀티 에이전트 연구 시스템은 내부 연구 평가에서 Opus 에이전트 하나보다 90.2% 더 나은 성적을 냈습니다. 연구는 독립적인 검색 여러 갈래로 자연스럽게 퍼지기 때문입니다. 하지만 Building Effective Agents에서 밝힌 이들의 기본 조언은 그대로입니다. 가능한 가장 단순한 해법을 찾고, 작업이 요구할 때만 복잡도를 더하라는 것입니다.

LangGraph 자체 가이드조차 속내를 말합니다. 에이전트가 도구를 쓰는 단순한 루프라면 LangGraph는 과합니다.

판단 기준은 꽤 단순합니다. 작업이 진짜 전문 영역으로 갈라지거나, 병렬로 퍼뜨렸다가 합치는 게 필요하거나, 단계마다 다른 모델이 필요하거나, 실패를 격리하고 경로를 감사할 수 있어야 할 때 그래프를 꺼내세요. 그 밖에는 루프에 머무르세요.

어디서 시작할까

첫날부터 에이전트 조직도가 필요하지는 않습니다. 차근차근 쌓아 올리세요.

핵심 정리

그래프 엔지니어링은 루프 엔지니어링을 밀어내는 새 분야가 아닙니다. 에이전트를 만드는 사람이면 언젠가 마주하는 결정에 붙어서 살아남은 이름입니다. 루프 하나로 부족해지는 순간, 조율이 곧 엔지니어링이 됩니다.

이 단어는 올해를 못 넘길 수도 있습니다. 설계 질문은 남습니다.

정리하면 이렇습니다.

읽어 주셔서 고맙습니다.

Cheers :)

Akshay.


Deep Dive

2026-08-14

공유 상태를 지킨다는 뜻

공유 상태는 여러 노드가 함께 쓰는 구조화된 작업 기록이다. 조사 노드는 근거를, 구현 노드는 변경 내용을, 테스트 노드는 실행 결과를 쓰는 식으로 책임을 나눈다. 아무 노드나 모든 필드를 바꿀 수 있게 두면, 한 노드가 추측을 사실처럼 써넣고 뒤의 노드들이 이를 믿으면서 오류가 퍼진다.

이를 막으려면 상태의 타입과 필수 필드를 정하고, 노드마다 쓸 수 있는 필드를 제한해야 한다. 값에는 출처와 작성 노드를 함께 남기고, 단계마다 체크포인트를 저장한다. 그러면 잘못된 값이 어디서 들어왔는지 찾고 그 지점부터 다시 실행할 수 있다. 메일 발송이나 결제처럼 외부 결과를 만드는 노드는 재실행해도 같은 작업이 중복되지 않게 만들어야 한다.

코드로 라우팅한다는 뜻

라우팅은 현재 상태를 보고 다음 노드를 고르는 일이다. 테스트 종료 코드, 승인 여부, 재시도 횟수처럼 값만 확인하면 되는 조건은 일반 코드가 맡는다. 그래야 같은 상태가 언제나 같은 경로를 타고, 경로 선택을 테스트하고 재현할 수 있다.

문장의 뜻이나 사용자의 의도처럼 해석이 필요한 판단은 모델이 맡을 수 있다. 다만 모델이 다음 노드를 직접 고르게 두기보다 missing_evidence, bad_patch, style_only처럼 제한된 값으로 판단을 내놓게 한다. 시스템이 그 값의 형식을 검사한 뒤 코드가 조사, 구현, 작성 노드로 연결한다.

두 원칙이 연결되는 지점

안정적인 그래프는 모델이 애매한 현실을 해석하고, 시스템이 그 결과를 스키마와 쓰기 권한으로 검사해 공유 상태에 보관한 뒤, 코드가 다음 행동을 고르는 순서로 움직인다. 공유 상태가 오염되면 정확한 라우팅 코드도 잘못된 길을 고른다. 상태가 정확해도 모델이 경로를 즉흥적으로 정하면 같은 실행을 재현하기 어렵다.

Key Insight

모델은 애매한 현실을 해석하고, 공유 상태는 그 결과를 검증 가능한 형태로 보관하며, 코드는 다음 행동을 결정한다.