AEGLOSLAB ChatGPT 같은 AI를 만들고 서비스하기

제6부 응용: 프롬프트·RAG·에이전트

6.7 에이전트 II — 멀티에이전트·워크플로우·MCP

"에이전트를 만든다"는 말은 실무에서 매우 다른 두 가지를 한 단어로 묶는다. 하나는 당신이 코드로 작성해 둔 파이프라인에 LLM 호출 몇 개를 삽입하는 것이고, 다른 하나는 모델에게 목표만 제시하고 "알아서 해라"라며 제어권을 넘기는 것이다. 이 둘은 신뢰성도, 비용도, 디버깅 난이도도 다른 세계에 산다. 그래서 이 장은 그 경계를 긋는 데서 시작한다 — 현장에서 가장 비용이 큰 실수 하나가 코드로 고정하면 될 일을 자율 에이전트에게 맡기는 것이기 때문이다. 마케팅이 "에이전트"라는 단어를 부풀린 탓에, 분류·요약·추출처럼 미리 명세되는 과제까지 자율 루프로 만들어 놓고 재현 불가능한 비용 폭주에 시달리는 경우가 흔하다.

6.6에서 단일 에이전트의 핵심 — 관찰·행동·반성 루프, 계획, 메모리 — 을 세웠다. 도구를 하나 붙이고 결과를 다시 넣는 단일 루프는 이미 안다고 가정한다. 여기서는 그 위로 두 방향으로 확장한다. 위로는 여러 LLM 호출을 정해진 순서·분기로 구성하는 워크플로우와 자율 에이전트를 가르고, 워크플로우 다섯 패턴을 하나씩 다룬다. 옆으로는 에이전트 하나가 아니라 여럿을 두는 멀티에이전트가 언제 이기고 언제 지는지를 토큰 회계로 따진다. 밑으로는 도구·컨텍스트·리소스를 표준 인터페이스로 노출하는 프로토콜 MCP가 어떤 문제를 푸는지 본다. 마지막으로 이 모든 것이 작동하는지 어떻게 아는가 — 궤적·성공률·비용으로 재는 평가와 관측성 — 을 다룬다.

6.7.1 워크플로우와 에이전트 — 제어 흐름은 누구 손에 있나

이 장 전체를 가르는 축은 하나다. 제어 흐름이 코드에 있느냐, 모델에 있느냐.

워크플로우(workflow)에서는 단계·분기·순서가 당신이 미리 작성해 둔 코드에 하드코딩되어 있다. LLM은 각 단계에서 "칸을 채우는" 역할이고, 다음에 무엇을 할지는 코드가 정한다. 분류기가 세 갈래 중 하나를 고르든, 게이트가 형식을 검사하든, 그 판단은 결정적인 if 문이다. 같은 입력을 두 번 넣으면 같은 경로를 밟는다.

자율 에이전트(agent)에서는 LLM이 스스로 다음 행동을 정한다. 어떤 도구를 어떤 순서로 쓸지, 언제 멈출지를 모델이 결정하고, 루프는 열려 있다(open-ended). 경로가 실행마다 달라지고, 같은 입력이라도 이번엔 도구를 세 번 부르고 다음엔 일곱 번 부를 수 있다.

워크플로우 — 제어 흐름이 코드에 에이전트 — 제어 흐름이 모델에 경로 A 경로 B 모델이 스스로 멈춤 입력 LLM 단계 1 분기 (코드가 판단) LLM 단계 2A LLM 단계 2B 출력 입력·목표 LLM: 다음 행동 결정 출력 도구 실행

이 구분이 사소해 보여도 실무의 거의 모든 결정이 여기서 갈린다. 워크플로우는 경로가 고정돼 있으니 테스트할 수 있고, 실패하면 코드의 어느 줄인지 특정되고, 호출 수에 상한이 있어 비용이 예측 가능하다. 자율 에이전트는 그 셋을 전부 유연성과 맞바꾼다. 문제가 미리 다 명세되지 않을 때 — 경로를 코드로 고정할 수 없을 만큼 열려 있을 때 — 만 그 거래가 남는다. 뒤에서 볼 오케스트레이터-워커 같은 패턴은 이 경계선 위에 걸쳐 있어서, "어디까지가 워크플로우이고 어디부터가 에이전트인가"가 그 자체로 설계 판단이 된다.

6.7.2 자율성은 능력이 아니라 비용이다

가장 흔한 오해는 자율성을 "더 똑똑함"으로 읽는 것이다. 그렇지 않다. 자율성은 능력이 아니라 비용이다 — 유연성을 사는 대신 신뢰성·비용 예측성·디버깅 용이성을 다룬다. 그래서 실무의 기본값은 "가능한 한 단순하게, 필요할 때만 에이전트"다. 단일 LLM 호출 → 워크플로우 → 자율 에이전트로 자율성이 올라가는 사다리에서, 요구를 만족하는 가장 낮은 칸을 골라야 한다.

세 축에서 무엇이 나빠지는지를 구체적으로 보자.

축워크플로우(결정적)자율 에이전트
신뢰성·예측가능성경로가 고정 → 같은 입력에 같은 경로. 회귀 테스트가 성립경로가 실행마다 달라 재현·보장이 어렵다
비용·지연호출 수에 상한이 있고 예측 가능루프가 몇 회 반복될지 사전에 모른다 → 분포의 꼬리가 두껍다
디버깅실패가 코드 위치로 특정된다실패가 모델의 긴 궤적 안에 흩어진다

"비용의 꼬리가 두껍다"는 말은 수사적 표현이 아니다. 자율 루프는 도구 호출 횟수의 분포가 오른쪽으로 길게 늘어진다. 평균 4회 반복하는 에이전트가 어떤 입력에서는 30회 반복될 수 있고, 그 30회 반복 사례가 전체 비용의 큰 몫을 차지한다. 그래서 자율 에이전트를 프로덕션에 배포하려면 평균 지연·비용이 아니라 p95·p99와 상한을 봐야 한다(7.5). 워크플로우는 이 꼬리 자체가 없다 — 호출 수가 코드로 정해져 있으니까.

자율 에이전트로 갈지 말지는 네 질문으로 거른다. 하나라도 "아니오"면 더 단순한 칸에 머문다.

첫째, 복잡성: 과제가 다단계이고 사전에 완전히 명세하기 어려운가? "이 설계 문서를 검토해 관련 파일 전부에 걸친 PR로 바꿔라"는 그렇지만, "이 PDF에서 제목만 뽑아라"는 아니다. 둘째, 가치: 결과가 높은 비용·지연을 정당화하는가? 셋째, 실현성: 모델이 이 과제 유형을 실제로 잘 하는가 — 벤치마크가 아니라 당신의 데이터에서? 넷째, 오류의 대가: 틀렸을 때 검출하고 복구할 수 있는가 — 테스트·리뷰·롤백이 있는가, 아니면 조용히 잘못된 결과가 사용자에게 나가는가?

실무의 대다수 과제는 이 관문에서 걸러진다. 분류·요약·추출·정해진 파이프라인은 단일 호출이나 워크플로우로 충분하고, 그쪽이 더 저렴하고 더 신뢰성 있고 디버깅하기 쉽다. 실제 자율 에이전트가 필요한 구간은 생각보다 좁다 — 그리고 그 좁은 구간에서도, 다음 절에서 보듯 자율성 전체를 켜기 전에 워크플로우 패턴으로 대부분을 해결할 수 있다.

6.7.3 프롬프트 체이닝과 게이트

"결정적 오케스트레이션"이라고 해서 밋밋한 일직선은 아니다. LLM 호출을 코드로 연결하는 재사용 가능한 골격이 있고, 이후 다섯 절에서 다루는 다섯 패턴은 자율 에이전트로 뛰기 전에 대부분을 해결한다. 이름보다 "언제 쓰나"가 중요하고, 이들은 레시피가 아니라 조립 블록이다 — 실제 시스템은 이들을 섞고, 필요할 때만 그 위에 자율성을 추가한다.

첫째는 프롬프트 체이닝(prompt chaining)이다. 한 과제를 고정된 하위 단계의 사슬로 분해해, 각 LLM 호출의 출력이 다음 호출의 입력이 된다. 중간에 게이트(gate) — 코드로 된 검사 — 를 두어 조건을 통과 못 하면 멈추거나 되돌린다.

통과 실패 입력 LLM: 개요 작성 게이트 (형식·길이 검사) LLM: 초안 작성 중단·재시도 LLM: 톤 다듬기 출력

이 패턴이 통하는 원리는 단순하다. 한 번의 호출로 "개요를 잡고 초안을 쓰고 톤까지 맞춰라"를 시키면 모델이 세 가지를 동시에 저글링하다 각각을 어설프게 한다. 단계를 분할하면 각 호출이 하나의 좁고 선명한 일만 하므로 단계별 정확도가 올라간다. 대가는 지연이다 — 한 번이면 될 것을 세 번 순차로 부르니 종단 지연이 세 배 가까이 늘어난다. 그 트레이드오프가 남는 것은 과제를 깨끗하게 순차 분해할 수 있을 때, 즉 각 단계의 출력이 다음 단계의 온전한 입력이 될 때다. 문서 개요→초안→교정, 마케팅 카피 생성→다른 언어로 번역이 전형이다.

게이트의 존재가 이 패턴을 자율 루프와 가른다. 게이트는 코드다 — 정규식으로 JSON 형식을 검사하든, 길이가 상한을 넘는지 보든, 결정적이다. 모델이 "이 정도면 됐어"라고 스스로 판단하는 것이 아니라, 당신이 통과 기준을 코드로 고정한다. 그래서 실패가 났을 때 어느 단계의 어느 검사인지가 즉시 드러난다.

6.7.4 라우팅 — 분류해서 전용 경로로

두 번째 패턴은 라우팅(routing)이다. 입력을 먼저 분류해 전용 후속 경로로 보낸다. 한 프롬프트에 모든 경우를 욱여넣으면 서로 간섭해 전부가 흐려지는데, 관심사를 분리하면 각 경로가 자기 경우만 적절히 처리한다.

단순 FAQ 환불 요청 기술 지원 입력 LLM 또는 분류기: 라우팅 결정 작고 저렴한 모델 환불 전용 프롬프트 도구 붙은 에이전트

라우팅은 비용 최적화의 핵심 수단이다. 고객 문의의 대부분이 단순 FAQ라면, 그것들을 값비싼 대형 모델에 전부 투입하는 것은 낭비다. 라우터가 쉬운 질의를 작은 모델로, 어려운 것만 큰 모델로 보내면 같은 품질을 훨씬 저렴하게 낸다(5.6의 모델 라우팅, 7.5의 비용). 관심사 분리라는 품질 이득과 모델 선택이라는 비용 이득이 한 패턴에서 겹친다.

함정은 라우터 자체다. 라우터가 틀리면 이후 전부가 그 위에서 흐른다 — 환불 요청을 FAQ로 오분류하면 사용자는 잘못된 자동응답을 받는다. 그래서 라우팅 정확도는 최종 출력과 따로 평가해야 한다. 라우터를 별도 데이터셋으로 채점하지 않으면, 시스템 전체 정확도가 떨어질 때 그것이 라우터 탓인지 후속 경로 탓인지 구분할 수 없다. 라우터를 LLM으로 할지 전통 분류기로 할지도 트레이드오프다. 범주가 뚜렷하고 데이터가 있으면 작은 분류기가 저렴하고 빠르고 결정적이며, 범주가 애매하고 자연어 뉘앙스에 의존하면 LLM 라우터가 낫다.

6.7.5 병렬화 — 분할과 투표

세 번째 패턴은 병렬화(parallelization)다. 여러 LLM 호출을 동시에 실행한다. 성격이 다른 두 갈래가 있다.

분할(sectioning)은 과제를 독립 하위 과제로 분해해 병렬 실행 후 합친다. 긴 문서의 여러 섹션을 동시에 요약하거나, 여러 파일을 동시에 분석하는 식이다. 투표(voting)는 같은 과제를 여러 번 실행해 결과를 모은다 — 다수결이나 합의로 신뢰도를 높이거나, 서로 다른 관점을 얻는다. 코드가 안전한지 세 번 독립으로 검사해 하나라도 위험하다고 하면 막는 식의 보수적 게이트가 투표의 전형이다.

입력 분할·복제 (코드) LLM 호출 A LLM 호출 B LLM 호출 C 집계 (코드) 출력

병렬화의 이득은 지연을 처리량으로 사는 것이다. 순차로 하면 $n$ 개 하위 과제에 $n$ 배 시간이 들지만, 병렬로 하면 가장 느린 하나의 시간에 끝난다 — 대신 같은 순간에 $n$ 개의 요청을 서빙 시스템에 보내니 처리량 부담이 커진다. 여기서 분할과 투표를 반드시 구분해야 한다. 분할은 하위 과제가 정말 독립일 때만 안전하다. 섹션 A를 요약하는 데 섹션 B의 내용이 필요하다면, 둘을 따로 실행한 결과는 서로 모순되거나 맥락을 놓친다. 하위 과제가 서로 의존하면 병렬화가 아니라 오케스트레이터-워커(다음 절)가 맞다. 투표는 반대로 독립성이 아니라 다양성이 관건이다 — 같은 모델을 같은 프롬프트로 세 번 실행하면 셋이 거의 같은 답을 내 투표가 무의미해질 수 있다. 온도를 높이거나 프롬프트를 조금씩 달리해 시도들이 실제로 갈라지게 해야 투표가 값을 한다.

6.7.6 오케스트레이터-워커

네 번째 패턴은 오케스트레이터-워커(orchestrator-workers)다. 중앙 오케스트레이터 LLM이 과제를 동적으로 하위 과제로 분해해 워커 LLM들에게 위임하고, 결과를 종합한다.

하위과제 1 하위과제 2 하위과제 k 입력·목표 오케스트레이터 LLM (과제 분해·위임) 워커 LLM 1 워커 LLM 2 워커 LLM k 오케스트레이터 (결과 종합) 출력

병렬화와 그림이 닮았지만 결정적 차이가 있다. 병렬화는 하위 과제가 코드에 고정돼 있다 — 문서를 3개 섹션으로 나누라고 당신이 정한다. 오케스트레이터-워커는 하위 과제의 수와 성격을 오케스트레이터가 입력을 보고 정한다. "이 큰 코드 변경을 관련 파일 전부에 적용하라"에서 어느 파일 몇 개가 관련 있는지는 실행 때 결정되므로, 코드로 고정할 수 없다.

바로 이 지점에서 자율성이 개입한다. 오케스트레이터가 "몇 개로, 무엇으로 쪼갤지"를 스스로 정하는 순간 제어 흐름의 일부가 모델로 넘어간다. 그래서 이 패턴은 워크플로우와 멀티에이전트의 경계에 걸친다 — 워커가 단순한 단일 호출이면 아직 워크플로우에 가깝고, 워커가 독립된 도구·메모리를 갖고 스스로 루프를 반복하면 이미 멀티에이전트다. 여기서 흔한 과잉 설계 하나를 명시해 두자. 만약 하위 과제가 항상 같은 개수·같은 성격이라면 오케스트레이터-워커는 낭비다 — 단순히 병렬화로 고정 분할하는 편이 단순·저렴·디버깅 쉽다. 오케스트레이터의 계획 호출은 하위 과제 수가 실제로 가변일 때만 값을 한다.

6.7.7 평가자-최적화 루프

다섯 번째 패턴은 평가자-최적화(evaluator-optimizer)다. 한 LLM이 생성하고, 다른 LLM(또는 같은 모델의 다른 역할)이 기준 대비 평가·피드백하며, 그 피드백으로 다시 생성하는 루프를 반복한다. 코드가 종료 조건 — 합격 기준이나 최대 반복 — 을 쥔다.

합격 수정 필요 + 피드백 입력 생성기 LLM 평가자 LLM (기준 대비 채점) 출력

이 패턴이 통하려면 두 조건이 맞아야 한다. 명확하고 검사 가능한 평가 기준이 있어야 하고, 반복 개선이 실제로 측정 가능한 이득을 줘야 한다. 코드가 테스트를 통과할 때까지 고치는 루프가 이상적인 후보다 — 통과/실패가 이진적이고 반복이 확실히 나아지니까. 번역 품질처럼 "사람이 피드백을 주면 나아지는" 과제도 후보다.

두 가지가 이 패턴을 망친다. 하나는 후한 평가자다. 평가자가 웬만하면 합격을 주면 루프가 한 바퀴 만에 끝나 개선이 안 일어난다. 반대로 평가자가 편향돼 잘못 판단하면 루프가 잘못된 방향으로 무의미하게 반복된다 — 그래서 평가 기준을 구체적·검사 가능하게 만드는 것이 핵심이고, 이것이 LLM-as-judge의 설계 문제와 직결된다(4.2). 다른 하나는 종료 조건의 부재다. 평가자가 계속 "조금 더"를 요구하면 루프가 무한히 반복하며 비용을 소모한다. 최대 반복을 코드로 반드시 걸어라 — 이것은 평가자-최적화뿐 아니라 뒤에 나올 모든 자율 루프에 공통이다. 종료 조건 없는 루프는 프로덕션에서 언젠가 반드시 문제가 생긴다.

6.7.8 워크스루 — 오케스트레이터-워커 한 과제의 토큰 회계

그림만 보면 미끄러진다. 오케스트레이터-워커를 한 과제로 끝까지 실행해 토큰을 세어 보자. 모든 수치는 설명용 개략값이다.

과제는 "이번 분기 실적 요약 보고서를 만들어라"이고, 하위 과제 수가 입력에 따라 달라져 오케스트레이터-워커가 적합하다. 워커는 단순 단일 호출(+도구 1회)로 두어 워크플로우 쪽에 가까운 형태다. 시스템 프롬프트 $S = 500$ 토큰을 모든 호출이 다시 읽는다고 하자.

병렬 병렬 위임 사용자 오케스트레 이터 워커: 재무 워커: 경쟁사 워커: 초안 분기 보고서 만들어라 계획: 3개 하위과제로 분해 재무지표를 표로 경쟁사 3곳 동향 매출·마진 표 경쟁사 요약 위 둘을 종합해 초안 보고서 초안 검토·통합 최종 보고서

궤적을 호출 단위로 회계한다. 워커 A·B는 각자 도구를 1회 호출하므로 워커당 LLM 호출이 2회(도구 호출을 내는 1차, 도구 결과를 받아 답을 내는 2차)다.

호출입력 토큰출력 토큰
① 오케스트레이터 계획$S{+}300 = 800$150 (하위과제 3개)
② 워커 A 1차 (도구 호출)$S{+}250 = 750$120 (tool_use)
③ 워커 A 2차 (표 작성)$750{+}120{+}600 = 1470$400 (재무 표)
④ 워커 B 1차 (검색 호출)750120
⑤ 워커 B 2차 (요약)1470400
⑥ 오케스트레이터→워커 C 초안$S{+}150{+}400{+}400 = 1450$1200 (보고서 초안)
⑦ 오케스트레이터 검토·통합$S{+}1200{+}100 = 1800$300
합계8,4902,690

LLM 호출은 7회로, 오케스트레이터-워커가 흔히 무는 "5~8회" 범위 안이다. 이 회계에서 순수 오버헤드가 어디인지가 눈에 들어온다. 호출 ①과 ⑦ — 오케스트레이터의 계획과 검토 — 은 조정 호출로, 합쳐 약 2,600 입력토큰이 실제 내용 생산이 아니라 관리에 쓰인다. 호출 ⑥에서 워커 C가 A·B의 결과 800토큰을 다시 읽고, 호출 ⑦에서 오케스트레이터가 초안 1200토큰을 다시 읽는 것이 컨텍스트 재전송이다. 단일 에이전트가 같은 일을 한 컨텍스트에서 순차로 했다면 도구 호출 수는 비슷하되 이 재전송·조정 항이 줄어든다 — 대신 A와 B를 동시에 못 실행해 병렬성을 잃는다. 오케스트레이터-워커가 사는 것은 속도(병렬)와 집중(각 워커가 짧고 선명한 컨텍스트)이고, 내주는 것은 이 조정 호출과 재전송이다.

대략적인 돈으로 환산해 보자. 발표 시점 기준 대형 모델의 개략 단가를 입력 100만 토큰당 5달러, 출력 100만 토큰당 25달러로 가정하면, 이 보고서 한 건은 입력 $8{,}490 \times 5/10^6 \approx \$0.042$, 출력 $2{,}690 \times 25/10^6 \approx \$0.067$, 합쳐 약 11센트다. 시스템 프롬프트 $S$ 와 반복되는 프리픽스를 프리픽스 캐시로 재사용하면 입력 비용이 크게 준다(5.6). 정확한 단가는 벤더·모델·시점마다 달라 공식 가격표를 확인해야 하지만, 회계의 구조 — 조정 호출과 재전송이 오버헤드로 추가된다 — 는 단가와 무관하게 남는다.

6.7.9 멀티에이전트 — 역할 분업·토론·핸드오프·통신

오케스트레이터-워커에서 워커가 독립된 도구·메모리·역할을 갖고 스스로 루프를 반복하는 에이전트가 되면, 우리는 멀티에이전트 시스템에 들어선 것이다. 단일 에이전트를 여럿 두고 협업시키는 대표 패턴들을 보자.

역할 분업(role specialization)은 각 에이전트에 좁은 역할·도구·시스템 프롬프트를 준다 — "리서처", "코더", "리뷰어". 이것이 도움이 되는 실제 이유는 도구 선택에 있다. 한 에이전트가 도구를 수십 개 들고 있으면 프롬프트가 비대해지고, 매 스텝 "이 중 무엇을 쓸까"의 선택지가 흐려져 오답률이 오른다. 역할을 나누면 각 에이전트가 자기에 필요한 몇 개의 도구만 보므로 선택이 선명해진다. 대가는 역할 간 핸드오프와 컨텍스트 이전이 새 비용·실패점이 된다는 것이다.

토론·비평(debate·critique)은 여러 에이전트가 같은 문제에 서로 다른 입장을 내고 반박·비평을 주고받아 답을 벼린다. 평가자-최적화를 여러 에이전트로 확장한 셈이다. 토론이 단일 답보다 사실성·추론을 개선한다는 연구가 있지만, 이것은 모든 과제에서 항상 그런 것이 아니라 특정 조건의 결과이고 비용이 곱절로 든다. 실무에서 흔한 실패는 "두 에이전트가 서로 예의 바르게 동의"하며 무의미하게 반복하는 것이다 — 같은 모델에 같은 맥락을 주면 둘이 금방 합의해 버려 토론이 무의미해진다. 입장을 강제로 다르게 배정하거나(한쪽은 반박 담당, 한쪽은 옹호 담당) 근거를 다르게 줘야 실효가 생긴다.

핸드오프(handoff)는 한 에이전트가 대화·과제의 제어권을 다른 에이전트에 넘긴다. 고객 지원의 "상담원 전환" 비유가 맞다.

결제 문의 기술 문의 정책 초과 해결 문의 진입 분류 에이전트 결제 에이전트 기술 에이전트 사람 상담원 종료

핸드오프의 성패는 무엇을 전달하느냐가 가른다. 넘길 때 대화 요약·상태·목표가 유실되거나 왜곡되면 받는 에이전트가 처음부터 다시 묻고, 사용자는 같은 말을 반복해야 해서 불만이 급증한다. 그래서 넘길 컨텍스트를 명시적 구조로 만들어야 한다 — "지금까지의 요약, 확인된 사실, 남은 목표"를 자유 텍스트가 아니라 정해진 필드로 넘겨야 유실이 줄어든다(7.1의 대화 UX·세션과 연결).

에이전트들이 어떻게 통신하는지도 설계 축이다. 크게 둘이다. 중앙 매개는 오케스트레이터가 허브가 되어 모든 소통이 그를 거친다 — 추적·제어는 쉽지만 병목이자 단일 실패점이다. 직접(peer-to-peer)은 에이전트끼리 직접 메시지를 주고받는다 — 유연하지만 에이전트가 $n$ 개면 소통 경로가 $O(n^2)$ 로 조합 폭발하고 추적이 어려워진다. 여기서 정직하게 밝혀 둘 것은, 멀티에이전트 통신 프로토콜은 아직 표준이 무르익지 않았다는 점이다. 프레임워크마다 방식이 다르고 구체 API는 빠르게 바뀐다. 원리 — 누가 무엇을 누구에게, 어떤 컨텍스트와 함께 넘기나 — 에 무게를 두고 특정 SDK의 메서드 이름에 종속되지 않는 편이 안전하다.

6.7.10 워크스루 — 멀티에이전트 토큰이 폭증하는 계산

멀티에이전트의 가장 큰 비용은 토큰이다. 왜 그런지를 산식으로 세우고 실제 숫자를 넣어 보면, "멀티에이전트가 비싸다"가 얼마나 비용이 큰지, 그리고 언제 그 값이 정당화되는지가 명확해진다. 오케스트레이터 + $k$ 개 워커의 토큰 비용은 대략

$$C_{\text{multi}} \;\approx\; C_{\text{orch}} \;+\; \sum_{i=1}^{k}\big(C_{\text{worker},i} + c_{\text{ctx}}\big)$$

로 쓸 수 있다. 여기서 $c_{\text{ctx}}$ 는 각 워커가 공유 컨텍스트(시스템 프롬프트 + 과제 브리프 + 하위 지시)를 새로 읽는 부트스트랩 토큰이다. 이 항이 워커 수 $k$ 에 비례해 곱절로 쌓인다는 것이 핵심이다.

너비 우선(breadth-first) 리서치 과제로 숫자를 넣어 보자. 다섯 개의 독립 하위 영역을 조사해야 하고, 각 워커가 자기 영역을 도구 4회(웹 검색 등) 호출로 심층 분석한다고 하자. 각 워커는 새 컨텍스트 — 시스템 500 + 공유 브리프 800 + 하위 지시 200 = 부트스트랩 1,500 토큰 — 로 시작하고, 도구를 4회 부르며 자기 컨텍스트가 자란다. 도구 결과가 각 1,000 토큰이면 한 워커의 LLM 호출들이 다시 읽는 입력의 합은 대략

$$1500 + (1500{+}1000) + (1500{+}2000) + (1500{+}3000) + (1500{+}4000) = 17{,}500 \text{ 입력토큰}$$

이고, 출력은 스텝당 300씩 5회로 약 1,500이다. 다섯 워커면 입력 87,500, 출력 7,500이다. 여기에 오케스트레이터가 추가된다 — 계획 호출(입력 1,300 / 출력 300)과, 다섯 워커의 요약을 각 500씩 다시 읽어 종합하는 호출(입력 $2500{+}800 = 3300$ / 출력 2,000). 전부 더하면:

구성요소입력 토큰출력 토큰
오케스트레이터 계획1,300300
워커 5개 (각 ≈ 17,500 / 1,500)87,5007,500
오케스트레이터 종합3,3002,000
합계92,1009,800

이 92,100 입력토큰 안에서 멀티에이전트에 특유한 낭비를 분리해 보자. $\sum_{i=1}^{5} c_{\text{ctx}} = 5 \times 1{,}500 = 7{,}500$ 토큰이 부트스트랩 중복이다 — 같은 시스템 프롬프트와 브리프를 다섯 워커가 각자 다시 읽는다. 종합 호출이 워커 출력 2,500토큰을 다시 읽는 것도 단일 에이전트라면 없었을 재전송이다. 개략 단가(입력 \$5/1M, 출력 \$25/1M)로 환산하면 이 리서치 질문 한 건이 입력 $92{,}100\times5/10^6 \approx \$0.46$, 출력 $9{,}800\times25/10^6 \approx \$0.245$, 합쳐 약 70센트다.

이제 정직하게 비교해야 한다. 같은 과제를 유능한 단일 에이전트가 한 컨텍스트에서 도구 15회가량으로 풀고, 프리픽스 캐시로 안정적인 앞부분을 재사용한다면 실효 비용은 대략 입력 20,000 + 출력 5,000, 약 22센트로 볼 수 있다 — 이 경우 멀티에이전트가 약 3배다. 반면 애초에 모델의 내부 지식만으로 답하는 단순 챗 한 턴(입력 1,000 + 출력 800, 약 2.5센트)과 비교하면 약 스물몇 배다. 공개된 멀티에이전트 리서치 사례가 "일반 챗 대비 약 15배 규모의 토큰"을 썼다고 보고한 것이 바로 이 후자의 비교이고, 정확한 배수와 조건은 워커 수·컨텍스트 크기에 따라 크게 변동하니 원 출처를 확인해야 한다.

여기서 한 가지 통념을 조용히 깨 둘 필요가 있다. "단일 에이전트는 하나의 긴 컨텍스트를 매 스텝 통째로 다시 읽으니 멀티보다 비싸다"는 논리는 프리픽스 캐시가 없을 때만 맞는다. 캐시가 없으면 단일 에이전트의 입력은 스텝 수에 대해 거의 제곱으로 쌓여 — 이 예에서 순진하게 계산하면 20만 토큰을 넘긴다 — 오히려 컨텍스트를 나눠 담는 멀티에이전트가 유리해진다. 그런데 안정적인 프리픽스는 캐시로 0.1배 근처에 읽히므로, 캐시가 잘 걸리는 단일 에이전트가 대개 더 저렴하다. 그래서 멀티에이전트의 비용 우위는 "컨텍스트가 한 워커 창에 안 들어갈 만큼 넓고", "캐시가 잘 안 걸리는" 특수한 경우에나 생긴다. 이 조건이 안 맞으면 멀티는 단순히 더 비용이 큰 선택이다.

6.7.11 언제 멀티가 이기고 언제 지는가

앞의 계산이 이 절의 결론을 이미 예고한다. 멀티에이전트가 우월하다는 주장은 무조건이 아니라 조건부다. 이득과 해악을 갈라 보자.

멀티가 돕는 경우는 셋이다. 첫째, 병렬 탐색이다. 넓은 탐색 공간을 여러 하위 에이전트가 동시에·독립적으로 뒤지고, 각자 자기 컨텍스트 창을 써서 단일 창에 다 안 들어가는 정보를 나눠 담는다 — 너비 우선 리서치·검색에서 특히 유효하다. 둘째, 관심사 분리다. 역할별로 도구·프롬프트가 짧아져 각 에이전트의 선택이 선명해지고, 도구 수십 개를 든 단일 에이전트보다 낫다. 셋째, 컨텍스트 격리다. 한 하위 과제의 잡음이 다른 과제의 컨텍스트를 오염시키지 않는다.

멀티가 해로운 경우도 셋이다. 첫째, 조정 오버헤드다. 오케스트레이터의 계획·위임·종합 호출 자체가 비용·지연·실패점이고, 에이전트 수가 늘수록 조정이 초선형으로 커진다. 둘째, 비용 폭증이다 — 앞 절에서 본 $\sum c_{\text{ctx}}$ 가 워커 수에 비례해 쌓여, 멀티가 단일 대비 수 배에서 십수 배 토큰을 쓸 수 있다. 셋째, 오류 전파다. 오케스트레이터의 잘못된 분해, 워커 간 모순, 핸드오프 컨텍스트 유실이 연쇄한다 — 특히 오케스트레이터는 단일 실패점이라 그가 병목이자 전체를 붕괴시킬 지점이다. 여기에 디버깅 난이도가 더해진다. 실패가 여러 에이전트의 얽힌 궤적에 흩어져 "어느 에이전트가 어디서 왜"를 추적하기가 단일 에이전트보다 훨씬 어렵다.

"멀티에이전트가 낫다"는 말은 이 이득과 해악의 척도에서 이득이 클 때만 참이다. 공개 사례가 너비 우선 탐색에서 단일 에이전트를 능가했다고 보고한 것과 그 시스템이 십수 배 토큰을 썼다고 밝힌 것은 같은 사실의 양면이다 — "낫다"는 특정 과제 유형에 높은 비용을 감수할 때의 조건부 결론이다. 반대편에는 "멀티에이전트를 만들지 말라"는 실무 견해도 널리 있다. 컨텍스트를 여러 에이전트로 분해하면 결정의 일관성이 깨지고, 대개 단일 에이전트에 좋은 도구와 긴 컨텍스트를 주는 편이 더 신뢰성 있다는 주장이다. 내 입장은 중립이되 실용적이다 — 많은 경우 단일 에이전트 + 좋은 도구가 낫고, 멀티에이전트는 병렬 탐색·관심사 분리가 명백한 이득이고 비용·디버깅 대가를 감당할 수 있을 때만 켠다. 기본값은 단일 에이전트다.

의사결정을 신호로 정리하면 다음과 같다. 이것은 강요가 아니라 판단의 골격이다.

신호가리키는 쪽
경로가 사전에 명세됨워크플로우
순차·열린 과제, 도구 몇 개단일 에이전트
넓은 병렬 탐색이 본질(너비 우선)멀티에이전트(오케스트레이터-워커)
역할·도구가 뚜렷이 갈림멀티에이전트(역할 분업)
비용·지연이 민감함더 단순한 쪽으로
재현·감사·디버깅이 중요더 단순한 쪽으로

멀티에이전트로 가기로 했더라도 가장 단순한 위상 — 중앙 오케스트레이터 + 얕은 워커 — 부터 시작하는 편이 좋다. 직접 통신하는 깊은 에이전트 망은 조합 폭발과 추적 난이도를 한꺼번에 부른다.

6.7.12 N×M 통합 문제와 MCP

에이전트가 유용하려면 바깥 세계 — 파일 시스템, 데이터베이스, 사내 API, 깃 저장소, 검색 — 에 닿아야 한다. 6.5의 함수 호출은 "모델이 도구를 부르는 규약"을 줬지만, 그 도구가 어떻게 구현·연결·인증되는가는 애플리케이션마다 제각각이었다. 여기서 통합 문제가 발생한다.

$M$ 개의 AI 애플리케이션(챗봇·IDE·에이전트)과 $N$ 개의 도구·데이터 소스(Slack·GitHub·Postgres·Google Drive)를 잇는다고 하자. 표준이 없으면 각 애플리케이션이 각 도구마다 전용 연결 코드를 써야 한다 — $M \times N$ 개의 커스텀 통합. 새 도구 하나가 나오면 $M$ 개 애플리케이션이 각자 붙여야 하고, 새 애플리케이션은 $N$ 개를 다 붙여야 한다. 조합이 폭발한다.

MCP(Model Context Protocol) 의 발상은 USB-C나 언어서버프로토콜(LSP)과 같다 — 가운데에 표준 인터페이스를 두어 $M \times N$ 을 $M + N$ 으로 바꾼다. 도구 제공자는 MCP 서버를 한 번 만들면 모든 MCP 지원 애플리케이션이 쓰고, 애플리케이션은 MCP 클라이언트를 한 번 구현하면 모든 MCP 서버에 닿는다.

MCP 없이: 매 쌍마다 전용 통합 MCP로: 각자 표준 한 번 앱 1 앱 2 앱 3 도구 A 도구 B 도구 C 도구 D 앱 1 앱 2 앱 3 도구 A 도구 B 도구 C 도구 D MCP 표준 (클라이언트 ↔ 서버)
N×M 통합 → MCP 표준으로 N+M.

숫자로 개략을 파악하자. 앱 10개와 도구 20개를 잇는다면, 전용 통합은 최악의 경우 $10 \times 20 = 200$ 벌의 커넥터를 쓰고 유지해야 한다. 표준을 쓰면 앱 10개가 클라이언트를 한 번씩, 도구 20개가 서버를 한 번씩 — $10 + 20 = 30$ 벌이다. 도구 하나가 새로 나올 때 드는 일도 200 대 30의 구조에서 갈린다. 전용 방식에서는 새 도구를 앱 10곳이 각자 붙여야 하지만, 표준에서는 서버 한 벌만 만들면 10곳이 그대로 쓴다. LSP가 에디터 $\times$ 언어 통합을 $M+N$ 으로 바꿔 에디터마다 언어마다 플러그인을 다시 짜던 시대를 끝낸 것과 정확히 같은 판이다. 이 절약이 커질수록 도구 생태계가 네트워크 효과로 자란다 — 한 번 만든 서버를 여러 앱이 재사용하니까.

6.7.13 MCP의 세 프리미티브와 구조

MCP는 클라이언트-서버 구조다. 호스트 애플리케이션(챗 앱·IDE·에이전트)이 여러 MCP 클라이언트를 실행하고, 각 클라이언트는 하나의 MCP 서버에 연결된다. 서버는 자기 능력을 세 가지 표준 프리미티브로 노출하는데, 이 셋의 구분이 MCP의 개념적 핵심이다 — 누가 그것을 주도하느냐가 셋을 가른다.

프리미티브무엇누가 주도하나
도구(Tools)모델이 호출해 부작용을 내거나 계산하는 함수(예: send_email, run_query)모델 — LLM이 언제 부를지 정한다
리소스(Resources)모델 컨텍스트에 넣을 데이터(파일 내용·DB 레코드·문서)애플리케이션 — 앱이 무엇을 넣을지 정한다
프롬프트(Prompts)재사용 가능한 프롬프트 템플릿·워크플로우(예: "이 코드를 리뷰하라" 슬래시 명령)사용자 — 사용자가 골라 쓴다

함수 호출(6.5)이 "도구" 하나만 다뤘다면, MCP는 컨텍스트 데이터(리소스)와 재사용 프롬프트까지 같은 표준 아래 묶는다. 도구는 모델이, 리소스는 앱이, 프롬프트는 사용자가 주도한다는 이 세 갈래가 "무엇을 왜 표준화하나"의 답이다. 스펙은 계속 진화해서, 이 셋 외에 서버→클라이언트 방향 기능 — 모델에 생성을 되요청하는 sampling, 파일 시스템 루트를 알리는 roots, 사용자에게 되묻는 elicitation 등 — 이 버전에 따라 더해지고 바뀐다. 정확한 프리미티브 목록·명칭은 공식 스펙(modelcontextprotocol.io)을 확인하되, 이 장의 무게는 특정 스펙이 아니라 "모델·앱·사용자가 각각 주도하는 세 종류의 능력을 한 인터페이스로 묶는다"는 개념에 있다.

메시지 수준에서 MCP는 JSON-RPC 2.0 규약을 쓴다(요청·응답·알림). 클라이언트와 서버가 처음 연결할 때 능력 협상(capability negotiation)을 해 서로 무엇을 지원하는지 맞춘다. 전송(transport)은 크게 둘이다 — 로컬에서는 서버를 자식 프로세스로 기동해 표준입출력(stdio)으로 통신하고(로컬 파일·CLI 도구를 붙일 때), 원격에서는 네트워크 너머 서버에 HTTP 기반 전송으로 통신한다(호스팅된 SaaS를 붙일 때, 스트리밍 지원).

호스트 애플리케이션 (챗 앱·IDE· 에이전트) stdio HTTP LLM MCP 클라이언트 1 MCP 클라이언트 2 MCP 서버 (로컬 파일) MCP 서버 (원격 SaaS) 도구·리소스· 프롬프트 도구·리소스· 프롬프트

개념 스케치로, MCP 서버가 노출하는 도구 하나는 6.5의 함수 스키마와 닮았다.

{
  "name": "run_query",
  "description": "읽기 전용 SQL을 실행해 결과 행을 반환한다",
  "inputSchema": {
    "type": "object",
    "properties": {
      "sql": { "type": "string", "description": "SELECT 문" }
    },
    "required": ["sql"]
  }
}

애플리케이션이 MCP 서버에 붙으면 서버가 노출한 도구들이 6.5의 도구 목록으로 자동 편입되고, 모델은 그것이 MCP를 거쳐 왔는지 몰라도 된다. MCP는 "도구를 정의·연결·인증하는 층"을 표준화할 뿐, 모델이 도구를 고르는 메커니즘(함수 호출) 자체는 그대로다. 벤더마다 이 편입을 붙이는 방식이 다르다 — 예컨대 Anthropic API는 원격 MCP 서버를 붙이는 전용 파라미터와 베타 헤더를 두는데, 파라미터 이름과 헤더 값은 개정이 잦으니 기억으로 단정하지 말고 공식 문서(claude-api 스킬)를 확인해야 한다.

여기서 두 가지 통념을 깨 둘 필요가 있다. 하나는 "에이전트를 만들려면 MCP가 필수"라는 것이다. 아니다 — MCP는 통합 표준이지 에이전트의 요건이 아니다. 도구를 앱 코드에 직접 함수로 붙여도(6.5) 에이전트는 실행된다. MCP가 빛나는 곳은 여러 앱이 같은 도구들을 재사용하거나 서드파티 도구 생태계에 붙고 싶을 때다. 내부에서 도구 두세 개를 붙이는 초기 단계라면 직접 함수 호출로 시작하고, 도구가 늘고 재사용·외부 생태계가 필요해질 때 MCP로 옮기는 것이 합리적이다. 다른 하나는 "MCP를 쓰면 보안이 공짜로 해결된다"는 것이다. 오히려 외부 MCP 서버는 프롬프트 인젝션·데이터 유출·과잉 권한의 새 공격면을 연다 — 신뢰할 수 없는 서버가 노출한 도구·리소스는 그 자체가 위험 입력이다. 자격 증명은 서버에 넘기지 말고 프록시가 요청 나갈 때 주입하도록 격리하고, 권한을 최소화하고, 인증을 별도로 설계해야 한다(7.4).

6.7.14 에이전트를 어떻게 평가하고 관측하나

워크플로우든 멀티에이전트든, 작동하는지 어떻게 아는가? 단일 호출은 "출력이 맞았나"만 보면 되지만, 에이전트는 여러 단계의 궤적을 밟으므로 평가·관측이 근본적으로 다르다. 세부는 7.6에서 다룬다 — 여기서는 에이전트 특유의 축을 포착한다.

세 축을 함께 봐야 한다. 결과 성공률은 최종 답이 옳은가·과제를 완수했나로, 궁극 지표지만 "왜 성공/실패인지"는 안 알려준다. 궤적 품질은 밟은 경로가 합당했나 — 도구를 옳게 골랐나, 불필요한 단계는 없었나, 같은 짓을 반복하지 않았나 — 로, 같은 정답도 5단계와 50단계는 비용·신뢰성이 다르다. 비용·지연은 호출 수·토큰·달러·시간으로, 에이전트는 꼬리가 두꺼우니 평균뿐 아니라 분포와 상한을 봐야 한다.

궤적 평가가 핵심이자 어렵다. "정답을 맞혔지만 경로가 엉망"(운 좋게 맞음)과 "틀렸지만 경로는 합리적"(도구가 실패)을 구분해야 개선점이 보인다. 궤적을 단계별로 채점하거나(각 도구 호출이 적절했나) 참조 궤적과 비교한다. 결과만 보는 것이 왜 위험한지는 명확하다 — 성공률만 보면 비용이 10배인 에이전트와 저렴한 에이전트가 같아 보인다. 반드시 비용과 함께 봐야 하고, 앞의 토큰 회계가 왜 필요했는지가 여기서 이어진다.

디버깅하려면 모든 단계를 기록·추적해야 한다. 최소한 다음을 남긴다. 트레이스는 한 과제의 전체 궤적 — 각 LLM 호출의 프롬프트·응답, 각 도구 호출의 입출력, 분기 결정, 멀티에이전트면 어느 에이전트/스레드가 무엇을 했나. 스팬은 개별 단계(LLM 호출 하나, 도구 호출 하나)에 지연·토큰·성공/실패를 태그. 그리고 성공률·평균 단계 수·평균 비용·루프 진입률·타임아웃률 같은 상위 지표.

여기서 궤적이 틀어짐 과제 트레이스 스팬: 계획 LLM 호출 (토큰·지연) 스팬: 도구 호출 A (입력·출력· 성공?) 스팬: 도구 호출 B (실패 → 재시도) 스팬: 종합 LLM 호출 디버깅 지점

멀티에이전트는 여기에 부담을 더한다. 트레이스가 여러 에이전트/스레드로 갈라지므로, 어느 하위 에이전트가 어디서 실패했는지 보려면 에이전트별 스레드 뷰와 부모-자식 관계가 필요하다 — 이것이 6.7.11에서 말한 "멀티에이전트 디버깅이 더 어렵다"의 구체적 정체다.

이 절에서 밟았던 흔한 실패와 대응을 정리해 두면, 앞 절들의 조각이 실무 절차로 이어진다. 같은 도구를 반복 호출하거나 같은 생각을 되풀이하는 무한 반성은 트레이스에서 반복 패턴으로 검출하고 최대 단계 수 상한을 코드로 건다. 부적절한 도구 선택은 도구 설명·프롬프트를 다듬거나 도구 수를 줄이고(라우팅·역할 분업) 도구 선택을 따로 평가한다. 앞 단계 정보를 뒤에서 잊는 컨텍스트 유실은 넘길 컨텍스트를 명시 구조로 만들고 긴 궤적은 요약·메모리로 압축한다(6.6). 초기 잘못이 연쇄하는 오류 전파는 중간 검증 게이트(평가자-최적화)를 코드로 삽입해 끊는다.

마지막으로 명시해 둘 것 하나. 에이전트는 비결정적이라 "한 번 통과"가 신뢰의 근거가 못 된다. 여러 번, 다양한 입력으로 실행해 성공률·비용의 분포를 봐야 한다. 재현 어려운 실패는 트레이스 없이는 사실상 못 고친다 — 관측성은 선택이 아니라 에이전트를 프로덕션에 배포하기 위한 전제조건이다. 여기까지가 텍스트를 전제한 에이전트·도구·오케스트레이션의 이야기이고, 다음 장은 이미지·오디오 입력, 음성 대화, 이미지 생성을 하나의 시스템에 결합하는 멀티모달로 넘어간다 — 지금까지 세운 프롬프트·도구·서빙의 골격에 새 입력·출력 양식이 부과하는 제약을 추가하면서.