내 프로덕션 시스템에 직접 만든 신뢰성 도구를 실행해 보았다. 결과의 90%가 틀렸지만, 그것은 내가 수정한 가장 가치 있는 버그였다.
요약
멀티 에이전트 시스템의 구조적 신뢰성을 정적으로 분석하는 오픈 소스 도구 'swarm-test'를 실제 프로덕션 환경에 적용한 사례를 다룹니다. 도구가 정상적인 허브 앤 스포크 아키텍처를 심각한 결함으로 오판한 과정을 통해, 신뢰성 도구 구축 시 고려해야 할 중요한 교훈을 전달합니다.
핵심 포인트
- swarm-test는 LLM 호출 없이 에이전트 토폴로지를 정적으로 분석함
- 정상적인 허브 앤 스포크 구조를 단일 장애점으로 오판하는 오류 발생
- 도구의 분석 결과가 실제 시스템 설계 의도를 반영하지 못할 수 있음
- 신뢰성 도구 개발 시 정적 분석의 한계와 버그 수정의 중요성 강조
나는 swarm-test를 만들었습니다. 이는 멀티 에이전트 AI 시스템의 구조적 신뢰성 문제(탈출구가 없는 루프, 단일 장애점(Single Points of Failure), 조용히 깨지는 핸드오프(Handoffs) 등)를 정적으로 분석하는 오픈 소스 도구입니다. 실시간 LLM 호출이 없으며, API 비용이 들지 않고, 에이전트 토폴로지(Topology) 상에서 밀리초 단위로 실행됩니다.
지난주에 나는 모든 도구 제작자가 해야 하지만 대부분이 피하는 당연한 일을 했습니다. 바로 내 자신의 프로덕션 시스템을 대상으로 도구를 실행한 것입니다.
도구는 99개의 결과(findings)를 반환했습니다. 위험 점수(Risk score): 100점 만점에 0점. 심각(Critical) 항목 15개.
그리고 그 결과의 거의 대부분이 틀렸습니다.
무슨 일이 일어났는지, 왜 일어났는지, 그리고 해결 방법은 무엇인지 설명하겠습니다. 왜냐하면 이 버그는 내가 출시한 그 어떤 기능보다 신뢰성 도구를 구축하는 것에 대해 더 많은 것을 가르쳐 주었기 때문입니다.
테스트 대상 시스템
대상은 실제 시스템이었습니다. 프로덕션 환경에서 passport-photo, signature, document 파이프라인을 실행하는 14개의 에이전트로 구성된 FastAPI 오케스트레이터(Orchestrator)입니다. 하나의 OrchestratorAgent가 나머지 13개(얼굴 감지, 배경 제거, 향상, 검증, 컴플라이언스, 레이아웃 등)를 조정하며, 진화 및 상태 모니터링을 위한 몇 개의 백그라운드 루프도 포함되어 있습니다.
이것은 전형적인 허브 앤 스포크(Hub-and-spoke) 설계입니다. 오케스트레이터가 중심에 있는 것은 의도된 것이며, 그것이 오케스트레이터의 전체 역할입니다. 모든 요청은 이를 통해 흐르며, 워커(Worker)에게 작업을 위임하고 그 결과를 집계합니다.
이것은 정상적이고 올바른 아키텍처입니다. 버그가 아닙니다. 이 점을 명심하세요. 왜냐하면 내 도구는 이를 인지하지 못했기 때문입니다.
99개의 결과 보고서
swarm-test가 나에게 전달한 요약 내용은 다음과 같습니다:
Swarm Score: 0/100 — CRITICAL (심각 15개, 높음 41개 결과)
Cost Risk: 100/100 — SEVERE
cascade_failure FAILED 14 findings 14 critical
blast_radius FAILED 1 finding 1 critical
collusion_detection FAILED 4 findings
cost_risk FAILED 26 findings
...
1/8 tests passed — Overall: FAILED
14개의 치명적인 연쇄 장애 (cascade) 결과 — 단 하나의 에이전트도 빠짐없이 — 모두 똑같은 말을 하고 있었다: "폭발 반경 (blast radius) 92.3%, 장애가 12개의 에이전트로 연쇄 확산됨." 오케스트레이터 (orchestrator)는 재앙적인 단일 장애점 (single point of failure)으로 표시되었다. 25개의 비용 위험 (cost-risk) 결과 중 거의 대부분은 "SomeAgent와 OrchestratorAgent 사이의 피드백 루프 (feedback loop)"였다.
건강하고 올바르게 설계된 시스템이 5단계 경보 (five-alarm fire) 수준의 점수를 받은 것이다.
나의 첫 번째 본능은 위험한 쪽이었다. '어쩌면 프로덕션 시스템을 리팩터링 (refactor)해야 할지도 몰라. 폴백 (fallback) 에이전트를 추가하고, 오케스트레이터를 분해하자.' 그러다 나는 결과들을 제대로 읽기 시작했다.
왜 건강한 시스템이 0/100점을 받았는가
그 14개의 연쇄 장애 (cascade) 결과에서 실제로 무엇을 말하고 있는지 살펴보자. 모든 에이전트가 "92.3% 폭발 반경 (blast radius)"를 가지고 있다. 그래프의 모든 노드 (node)가 동일한 수치로 치명적이라고 표시된다면, 그것은 14개의 문제가 아니라, 하나의 구조적 사실이 14번 카운트된 것이다.
그 사실은 다음과 같다: 이것은 허브 앤 스포크 (hub-and-spoke) 그래프다. 모든 것이 오케스트레이터를 통해 라우팅 (routing)된다. 따라서:
- 오케스트레이터의 "폭발 반경 (blast radius)"는 매우 크다. 모든 것이 그것에 의존하기 때문이며, 이것이 바로 오케스트레이터의 역할이다.
- 모든 워커 (worker)의 폭발 반경 또한 매우 크게 나타났다. 도달 가능성 (reachability) 계산 방식이 허브를 통한 하위 노드들을 모두 포함했기 때문이다. 오직 오케스트레이터에 결과만 반환하는 리프 워커 (leaf worker)조차 마치 전체 시스템을 무너뜨릴 수 있는 것처럼 점수가 매겨졌다.
- 모든 "워커와 오케스트레이터 사이의 피드백 루프 (feedback loop)"는 단지 워커가 결과를 반환하는 과정일 뿐이었다. 이는 정상적인 요청/응답 (request/response)이지, 토큰을 낭비하는 사이클 (token-burning cycle)이 아니었다.
도구가 오케스트레이터를 사용한다는 이유로 내 시스템에 벌점을 주고 있었던 것이다. 도구는 의도된 중심성 (centrality)을 우연한 취약성 (fragility)으로 오해했다.
그리고 가장 뼈아픈 부분은 이것이다: 동일한 보고서 내에서, swarm-test는 OrchestratorAgent가 ORCHESTRATOR임을 99%의 확신도로 정확히 추론했으며, 프로필에는 문자 그대로 "높은 폭발 반경 예상 (expected high blast)"이라고 적혀 있었다. 도구는 이미 알고 있었다. 그러고 나서 모든 점수 산정 함수 (scoring function)가 도구가 알고 있던 사실을 무시해 버린 것이다.
근본 원인 (The root cause)
코드를 살펴보았습니다. 역할 분류기 (role classifier, classify_agent)가 실행되어 신뢰도 점수 (confidence scores)와 함께 역할을 추론하고, 이를 저장한 뒤 보고서에 렌더링했습니다. 심지어 role_adjusted_severity라는 함수도 있었습니다. 정의되어 있고 단위 테스트 (unit-tested)도 거쳤지만, 런타임 경로 (runtime path) 상에서는 그 어디에도 연결되어 있지 않았습니다.
즉, 아키텍처는 다음과 같았습니다: 역할을 추론하고, 역할을 표시한 다음, 마치 그 역할이 존재하지 않는 것처럼 모든 심각도 (severity)와 점수 (score)를 계산하는 방식이었습니다. 연쇄 테스트 (cascade test), 영향 범위 테스트 (blast-radius test), 비용-리스크 테스트 (cost-risk test) 중 그 어느 것도 역할을 참조하지 않았습니다. grep 명령어로 확인해 보니, role_adjusted_severity는 오직 자체 정의와 테스트 코드에서만 나타났습니다.
이 버그를 한 문장으로 요약하면 이렇습니다: 역할은 추론되었지만, 정작 중요한 모든 결정 과정에서 무시되었습니다.
*이것이 중요한 버그인 이유 *
이 문제를 단순한 점수 산정 방식의 미세한 조정 (minor scoring tweak) 정도로 치부하기 쉽습니다. 하지만 그렇지 않습니다. 이것은 신뢰성 도구 (reliability tooling)를 완전히 망가뜨리는 실패 모드 (failure mode)입니다.
양치기 소년 같은 도구는 아예 없는 것보다 못합니다. 개발자가 자신의 정상적인 오케스트레이터 시스템 (orchestrator system)에서 swarm-test를 처음 실행했을 때, 'CRITICAL 0/100'과 동일한 경고 14개가 뜨는 것을 본다면, 그들은 이 도구가 소음 (noise)이라고 결론짓고 삭제해 버릴 것입니다. 그리고 정작 도구가 진정으로 옳은 지적을 하는 단 한 번의 순간 — 실제 무한 루프 (unbounded loop)나 보호되지 않은 쓰기 (unguarded write)가 발생하는 순간 —에는 아무도 귀를 기울이지 않게 됩니다.
신뢰성 작업에서 오탐 (false positives)은 단순한 번거로움이 아닙니다. 그것은 곧 제품의 품질입니다. 신뢰 (Trust)가 가치 제안 (value proposition)의 전부입니다. 발견된 결과는 사용자가 그것을 믿을 때에만 가치가 있습니다.
해결책: 점수 산정에 역할을 반영하기
항상 그랬어야 했던 것처럼, 추론된 결과를 점수 산정 과정에 연결했습니다:
-
의도적인 허브(Hub)를 인식하기. 에이전트가 오케스트레이터(Orchestrator)(명시되었거나 높은 신뢰도로 추론된 경우)라면, 그 중심성(Centrality)은 당연한 것입니다. 이들의 넓은 영향 범위(Blast radius)는 CRITICAL(심각)한 연쇄 장애(Cascade)가 아니라, 정보 제공 차원의 "허브 앤 스포크 토폴로지(Hub-and-spoke topology)\
-
검증되지 않은 쓰기 작업 (Unvalidated write-back): EvolutionAgent가 10분마다 오케스트레이터(Orchestrator)의 설정을 변경하지만, 쓰기 경로(write path)에 대한 스키마 검증 (Schema validation)이 없습니다. 잘못된 값이 14개의 모든 에이전트(Agent)로 조용히 전파됩니다. 이는 실제적인 위험이며, 이제는 99개의 허위 경보(False alarms) 아래 묻혀 있는 대신 가장 핵심적인 발견 사항이 되었습니다.
-
오케스트레이터 우회 사이클 (Orchestrator-bypass cycle): 두 에이전트가 오케스트레이터의 감독을 건너뛰고 서로를 직접 호출하여, 그곳에서 발생하는 실패를 오케스트레이터가 감지할 수 없습니다.
이것들은 수정할 가치가 있습니다. 나머지 90개의 발견 사항은 전혀 그렇지 않았습니다.
*_내가 얻은 교훈 *
이후에 제가 만드는 모든 것에 적용할 몇 가지 사항입니다:
- 장난감이 아닌 실제 시스템에서 자신의 도구를 직접 사용해 보십시오 (Dogfood your own tool). 장난감 예제들은 모두 통과했습니다. 역할 추론 (Role inference)이 장식에 불과했다는 사실을 드러내기 위해서는 저의 실제 14개 에이전트 프로덕션 시스템이 필요했습니다.
- "정의되었으나 연결되지 않음 (Defined but disconnected)"은 실제적이고 위험한 상태입니다. role_adjusted_severity는 존재했고 테스트도 되었지만, 아무것도 이를 호출하지 않았기 때문에 아무런 역할도 하지 못했습니다. 연결되지 않은 함수에 대한 통과된 테스트 (Green tests)는 아무것도 증명하지 못합니다. 저는 해당 함수가 실제로 호출되는지 확인하는 회귀 테스트 (Regression test)를 추가하여, 다시는 조용히 연결이 끊어지는 일이 없도록 했습니다.
- 신뢰성 도구 (Reliability tooling)에서는 교정 (Calibration)이 곧 제품입니다. 탐지 엔진 (Detection engine)은 내내 괜찮았습니다. 도구를 신뢰할 수 있게 만들거나 혹은 가치 없게 만드는 것은 전적으로 발견된 사항을 어떻게 점수화하고 우선순위를 정하느냐에 달려 있었습니다.
swarm-test는 오픈 소스이며 MIT 라이선스를 따릅니다. CrewAI, LangGraph, AutoGen 및 커스텀 에이전트 시스템을 위한 정적 신뢰성 분석 (Static reliability analysis)을 수행하며, 실시간 LLM 호출이나 API 비용이 발생하지 않습니다.
pip install swarm-test
만약 프로덕션 환경에서 멀티 에이전트 시스템 (Multi-agent systems)을 운영 중이라면, 귀하의 토폴로지 (Topology)에 대해 이를 실행하여 실제 구조적 위험과 핸드오프 (Handoffs)가 깨질 수 있는 지점에 대한 결과 보고서를 기꺼이 보내드리겠습니다. 영업 목적이 아닌, 순수하게 보고서만 전달합니다.
그리고 만약 귀하께서 에러를 발생시키지 않는 형태의 조용한 멀티 에이전트 실패를 경험한 적이 있다면, 진심으로 그 이야기를 듣고 싶습니다. 그러한 이야기들이 우리 모두가 어디에 간극이 있는지 배우는 방법이기 때문입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기