다음에 올 것을 만들어가는 기술에 대한 심층 기사.

LLM 에이전트는 결국 분산 시스템이다

멀티 에이전트 LLM 시스템은 분산 시스템과 같은 문제에 부딪힙니다. 조율 비용, 합의, 장애 모드, 그리고 숨어 있는 CAP 정리까지 살펴봅니다.

테이블 주위에 메시지 튜브를 들고 모여 있는 빛나는 로봇들, 그중 한 대는 고장나 꺼져 있다.

AI 커뮤니티는 멀티 에이전트 시스템을 만들고 있습니다. 한 모델로는 풀 수 없는 문제를 해결하려고 LLM들이 작업을 나누고, 소통하고, 협업하는 팀을 구성하는 방식입니다. '리서처' 에이전트는 정보를 모으고, '코더' 에이전트는 구현을 맡고, '리뷰어' 에이전트는 품질을 점검하고, '코디네이터' 에이전트는 전체 워크플로를 관리합니다. 잘 돌아가는 엔지니어링 팀처럼 전문화된 에이전트들이 협업한다는 발상은 꽤 매력적입니다.

익숙하게 들리시나요? 그럴 만합니다. 분산 시스템 연구자들은 독립된 프로세스들을 조율하는 문제를 40년 동안 연구해 왔습니다. 멀티 에이전트 LLM 시스템은 분산 시스템 커뮤니티가 수십 년 전에 해결했거나 해결 불가능하다고 증명한 문제들을 처음부터 다시 발견하고 있는 셈입니다. 이런 유사점을 이해하면 같은 해법을 처음부터 다시 만드는 수고를 덜 수 있고, 예측 가능하고 잘 알려진 방식으로 실패하는 시스템을 피할 수 있습니다.

조율의 세금

분산 시스템의 첫 번째 교훈은 조율에는 비용이 든다는 것입니다. 서로 다른 작업을 독립적으로 처리하는 두 프로세스는 하나일 때보다 두 배 빠릅니다. 반면 같은 작업을 두고 조율이 필요한 두 프로세스는 종종 하나일 때보다 느립니다. 통신과 동기화에 드는 오버헤드가 병렬화로 얻는 이득을 넘어서기 때문입니다.

멀티 에이전트 LLM 시스템도 곧바로 이 문제에 부딪힙니다. '리서처' 에이전트가 리포트를 만들면, '코더' 에이전트는 그 리포트를 이해해야 코드를 짤 수 있습니다. '리뷰어' 에이전트는 리포트와 코드를 모두 이해해야 쓸모 있는 피드백을 줄 수 있습니다. 에이전트 사이에 작업이 넘어갈 때마다 맥락을 프롬프트로 직렬화해야 하고, 받는 쪽 에이전트는 그것을 파싱하고 이해해야 합니다. 이는 공유 상태라는 전형적인 분산 시스템 문제이고, 에이전트를 늘릴수록 더 심해집니다.

Single agent vs. multi-agent for a coding task:
Single agent:
1. Understand the problem         (1 LLM call)
2. Research relevant APIs          (2 LLM calls)
3. Write implementation            (1 LLM call)
4. Review and fix                  (1 LLM call)
Total: 5 LLM calls, full context throughout
Multi-agent (researcher + coder + reviewer):
1. Coordinator describes task      (1 LLM call)
2. Researcher reads and plans      (1 LLM call)
3. Researcher does research        (3 LLM calls)
4. Researcher summarizes findings  (1 LLM call)
5. Coder reads summary             (1 LLM call)  ← context lost here
6. Coder writes implementation     (1 LLM call)
7. Reviewer reads code + summary   (1 LLM call)  ← context lost here
8. Reviewer provides feedback      (1 LLM call)
9. Coordinator synthesizes         (1 LLM call)
Total: 11 LLM calls, context degraded at each handoff
More agents = more communication = more cost = worse context.

분산 시스템의 언어로 말하면, 이는 통신에 적용된 암달의 법칙입니다. 병렬화로 얻는 속도 향상은 병렬화할 수 없는 순차적 통신에 의해 제한됩니다. 긴밀한 조율이 필요한 작업에 에이전트를 더 추가하면 시스템은 빨라지는 게 아니라 느려집니다.

합의 문제

여러 에이전트가 같은 작업을 할 때는 무언가에 합의해야 합니다. 요구사항은 무엇인가? 어떤 접근법을 쓸 것인가? 이 구현은 맞는가? 분산 시스템에서 이것이 바로 합의 문제이고, 증명상으로도 어려운 문제입니다. FLP 불가능성 정리는 장애가 단 하나의 프로세스에서만 발생해도, 비동기 시스템에서는 결정론적 합의가 불가능하다는 것을 보여 줍니다.

LLM 에이전트는 비결정적이라서 합의 측면에서는 전통적인 분산 프로세스보다 더 까다롭습니다. 같은 에이전트에게 같은 질문을 두 번 해도 답이 다르게 나올 수 있습니다. 같은 코드를 검토한 두 에이전트가 그 코드가 맞는지를 두고 의견이 갈릴 수도 있습니다. 그 불일치를 해결하라고 맡긴 '코디네이터' 에이전트는 동전을 던지듯 답을 바꿀지도 모릅니다.

멀티 에이전트 프레임워크는 보통 두 가지 방식으로 이 문제를 다룹니다. 하나는 최종 권한을 가진 코디네이터 에이전트를 지정하는 것입니다. 단순하지만 단일 장애 지점이 됩니다. 다른 하나는 다수결 투표인데, 결정 하나마다 최소 세 개의 에이전트가 필요하니 비용이 큽니다. 둘 다 동작은 하지만, 애초에 작업을 여러 에이전트에 나눴기 때문에 생긴 문제를 푸는 셈입니다.

익숙한 장애 모드들

멀티 에이전트 시스템은 분산 시스템 엔지니어라면 바로 알아볼 방식으로 실패합니다.

  • 연쇄 장애. 에이전트 A가 잘못된 결과를 내놓습니다. 그걸 입력으로 받은 에이전트 B는 더 나쁜 결과를 만듭니다. B의 작업을 리뷰하는 에이전트 C는 잘못된 전제를 물려받아서 원래 오류를 잡아내지 못합니다. 분산 시스템에서 말하는 오류 전파와 같습니다. 쓰레기가 들어가면 쓰레기가 나오고, 단계마다 그 쓰레기가 증폭됩니다.
  • 데드락. 에이전트 A는 진행하려고 에이전트 B의 결과를 기다리고, 에이전트 B는 진행하려고 에이전트 A의 피드백을 기다립니다. 둘 다 앞으로 나아가지 못합니다. 실제로는 에이전트들이 작업을 주고받기만 하고 수렴하지 못하는 무한 루프로 나타납니다.
  • 스플릿 브레인. 관련된 작업을 맡은 두 에이전트가 문제에 대해 서로 다른 그림을 갖게 됩니다. 한쪽은 API가 JSON을 반환한다고 가정하고, 다른 쪽은 XML이라고 가정합니다. 각자의 결과물은 개별적으로는 맞지만 서로 호환되지 않습니다.
  • 썬더링 허드. 코디네이터 에이전트가 여러 에이전트에 작업을 동시에 배분합니다. 그러면 모두가 같은 API를 두드리고, 같은 레이트 리밋을 소진하거나, 같은 파일을 수정하려고 합니다. 단일 에이전트라면 겪지 않았을 자원 경합이 생깁니다.

멀티 에이전트가 실제로 도움이 되는 경우

분산 시스템과의 비유는 양쪽으로 작용합니다. 분산 시스템은 특정 문제에서 실질적인 이점을 줍니다. 멀티 에이전트 시스템도 마찬가지입니다. 문제를 실제로 나눌 가치가 있을 때 그렇습니다.

손쉽게 병렬화되는 작업. 50개의 코드베이스에서 같은 패턴을 찾아야 한다면, 50개의 에이전트가 독립적으로 일할 때 실제로 50배 빠릅니다. 조율이 필요 없습니다. 각 에이전트가 서로 다른 입력을 받아 독립된 출력을 만들면 됩니다. 이것은 MapReduce 패턴이고, 분산 데이터 처리에서 잘 통하듯 LLM 에이전트에서도 잘 통합니다.

다양한 관점. 서로 다른 시스템 프롬프트를 가진 에이전트 세 개에게 같은 코드를 리뷰하게 하면, 한 번의 리뷰가 놓치는 문제를 찾아낼 수 있습니다. 여러 명이 PR을 리뷰하는 것과 같은 중복성 패턴입니다. 컴퓨팅 비용은 세 배지만 커버리지는 넓어집니다.

명확한 인터페이스를 가진 전문화. 텍스트를 받아 번역된 텍스트를 돌려주는 번역 에이전트는 깔끔한 인터페이스를 갖습니다. 문서를 받아 요약을 돌려주는 요약 에이전트도 마찬가지입니다. 이것들을 번역한 다음 요약하는 식으로 조합하면 잘 동작합니다. 둘 사이의 인터페이스가 단순하기 때문입니다. 분산 시스템으로 치면, 잘 정의된 API를 가진 마이크로서비스가 복잡하고 수다스러운 인터페이스를 가진 마이크로서비스보다 잘 동작하는 것과 같습니다.

분산 시스템에서 얻는 교훈

멀티 에이전트 LLM 시스템을 만들고 있다면, 수십 년간 쌓인 분산 시스템의 지혜가 그대로 적용됩니다.

  1. 전문화된 여러 에이전트보다 적지만 더 유능한 에이전트를 택하세요. 잘 설계된 모놀리스가 엉성하게 설계된 마이크로서비스 아키텍처를 이기는 것처럼, 좋은 프롬프트를 가진 유능한 에이전트 하나가 대부분의 작업에서 좁은 역할의 에이전트 팀보다 낫습니다. 단일 에이전트가 작업량을 감당하지 못한다는 것을 증명했을 때만 에이전트를 추가하세요.
  2. 에이전트 사이의 인터페이스를 명확히 정의하세요. 각 에이전트의 입력과 출력은 잘 정의되어 있어야 합니다. '리서처가 찾은 내용을 파악해서 구현해'처럼 모호한 인계는 맥락 손실과 오해를 부릅니다. 자유 형식 텍스트보다 구조화된 데이터 계약이 낫습니다.
  3. 에이전트를 멱등하게 만드세요. 에이전트가 중간에 실패하더라도 같은 입력으로 다시 시작해서 올바른 결과를 얻을 수 있어야 합니다. 이를 위해서는 숨겨진 상태가 없고, 출력이 맞다고 확인되기 전까지 부수 효과를 일으키지 않는 에이전트여야 합니다.
  4. 관측 가능성을 확보하세요. 에이전트 간에 오가는 모든 메시지, 모든 결정, 모든 실패를 기록하세요. 멀티 에이전트 시스템이 잘못된 결과를 내면, 어느 에이전트가 왜 잘못된 결정을 내렸는지 추적할 수 있어야 합니다. 관측 가능성이 없으면 디버깅은 추측이 됩니다.
  5. 부분 실패를 가정하고 설계하세요. 어떤 에이전트든 실패하거나, 쓰레기 같은 결과를 내거나, 타임아웃될 수 있습니다. 시스템은 이를 우아하게 처리해야 합니다. 재시도하거나, 더 단순한 방식으로 대체하거나, 사람에게 물어봐야 합니다. 모든 에이전트가 성공할 거라고 가정하지 마세요.

불편한 진실

대부분의 멀티 에이전트 LLM 시스템은 좋은 프롬프트를 가진 단일 에이전트로 만드는 편이 더 잘 동작할 겁니다. 단일 모델이 처리할 수 있는 작업이라면, 멀티 에이전트 아키텍처의 조율 비용, 맥락 손실, 장애 모드가 이점을 거의 언제나 압도합니다. AI 도구가 발전하면서 정교한 멀티 에이전트 시스템을 만들고 싶은 유혹은 커지지만, 분산 시스템의 교훈은 분명합니다. 굳이 분산할 필요가 없는 것은 분산하지 마세요.

예외는 분명히 존재합니다. 손쉽게 병렬화되는 작업, 깔끔한 인터페이스를 갖춘 진짜 전문화, 단일 모델의 컨텍스트 창을 넘어서는 문제가 그렇습니다. 그 외의 경우라면 잘 구조화된 프롬프트, 좋은 도구, 신중한 재시도 전략을 갖춘 단일 에이전트가 에이전트 팀보다 더 잘 동작할 것입니다. 구조적으로 덜 멋져 보일 수 있지만, 더 잘 동작합니다. 가장 좋은 분산 시스템은 애초에 만들 필요가 없었던 시스템입니다.