에이전트에게 필요한 것은 더 나은 재시도가 아니라 서킷 브레이커(Circuit Breaker)입니다
요약
에이전트 시스템에서 단순 재시도 로직은 추론 실패 문제를 해결하지 못하고 오히려 비용과 오류를 증폭시킵니다. 따라서 인프라 장애를 위한 재시도 대신, 지속적인 추론 오류를 차단하는 서킷 브레이커 패턴 도입이 필요합니다.
핵심 포인트
- 재시도는 네트워크 타임아웃 같은 일시적 실패에만 유효함
- 에이전트의 추론 실패는 재시도로 초기화되지 않는 구조적 문제임
- 잘못된 추론에 대한 무분별한 재시도는 실행 비용을 급격히 증가시킴
- 에이전트 시스템에는 서킷 브레이커 패턴 적용이 필수적임
분산 시스템(distributed systems)에서 일해 본 엔지니어라면 누구나 서킷 브레이커(circuit breaker)를 알고 있습니다. 이 패턴은 간단합니다. 의존성(dependency)이 지속적으로 실패하면, 해당 대상에 요청을 보내는 것을 중단하는 것입니다. 대상이 회복될 시간을 주는 것이죠. 이 패턴이 작동하는 이유는 단 하나의 가정 때문입니다. 즉, 재시도(retries)는 실패가 일시적(transient)일 때만 유용하다는 것입니다. 실패가 일시적이지 않을 때 재시도를 하는 것은 문제를 더 악화시킵니다.
에이전트 시스템(Agent systems)에도 이와 유사한 실패 모드가 존재하지만, 제 경험상 이 로직에 서킷 브레이커(circuit breaker)를 적용하는 팀은 거의 없습니다. 에이전트가 잘못된 추론을 하는 것은 일시적인 문제가 아닙니다. 잘못된 컨텍스트(context), 잘못 보정된 판단, 잘못 읽은 도구(tool) 응답 — 이 중 어느 것도 재시도 사이에 초기화되지 않습니다. 에이전트는 외부에서 무언가가 멈추게 할 때까지, 매번 동일한 확신과 동일한 비용을 들여 똑같이 틀린 답으로 재시도를 반복할 것입니다. 그리고 그 "외부의 무언가"는 대개 새벽 2시에 Slack 알림을 읽으며, 4달러면 끝날 줄 알았던 실행 비용이 왜 60달러까지 치솟았는지 의아해하는 엔지니어인 경우가 많습니다.
1. 재시도 로직(Retry Logic)이 실제로 가정하는 것
표준 재시도 로직(Standard retry logic)은 특정 범주의 실패를 해결합니다. 바로 요청 자체와 무관한 이유로 실패한 요청입니다. 네트워크 타임아웃(network timeout), 일시적인 서비스 중단, 일시적인 잠금(transient lock) 등이 이에 해당합니다. 이 모든 실패는 실패의 원인이 요청 외부에 존재하기 때문에 두 번째 시도가 합리적인 방식으로 발생합니다. 이러한 가정은 인프라 실패(infrastructure failures)에는 유효합니다. 하지만 추론 실패(reasoning failures)에는 적용되지 않습니다. 잘못된 도구를 선택했거나, 사용자의 의도를 오해했거나, 오래된 컨텍스트(stale context)를 바탕으로 행동한 에이전트는 일시적인 문제를 겪고 있는 것이 아닙니다. 문제는 추론(reasoning) 안에 있으며, 재시도는 추론을 초기화하지 않습니다. 재시도는 첫 번째 시도가 왜 실패했는지 설명하기 위해 에이전트가 스스로 만들어낸 약간 다른 파라미터(parameters)를 가지고, 동일한 의존성(dependency)을 향해, 동일한 잘못된 판단을 더 빠르게 보낼 뿐입니다.
2. 원래 문제보다 더 큰 비용을 초래하는 연쇄 반응(Cascade)
고객 지원 해결을 오케스트레이션(orchestrating)하는 에이전트가 환불 검증 도구를 호출했는데, 명확한 에러도 아니고 명확한 성공도 아닌 모호한 페이로드(payload)를 받았습니다. 에이전트는 이를 실패로 해석하고 재시도(retry)합니다. 결과는 동일합니다. 에이전트는 첫 번째 시도에 잘못된 파라미터(parameter)가 있었을 것이라고 추론하며, 수정된 인자(argument)로 다시 재시도합니다. 네 번째 재시도에 이르러서 에이전트는 두 번째 지원 티켓을 생성하고, 고객에게 두 번 통지하며, 사람이 해결하는 데 2시간이 걸리는 결제 불일치(billing discrepancy)를 만들어냅니다. 검증 도구는 내내 정상적으로 작동하고 있었습니다. 문제는 응답에 대한 에이전트의 해석이었습니다. 재시도를 한다고 해서 그 해석이 바뀌지는 않았습니다. 에이전트는 자신이 진전을 보이고 있다고 확신하는 동안, 하류(downstream) 비용만 네 배로 증폭시켰을 뿐입니다.
3. 기존 방식 vs 새로운 방식 (Old Way vs New Way)
기존 방식: 서비스 메쉬(service mesh)가 네트워크 계층에서 지수 백오프(exponential backoff)를 적용하여 재시도 로직을 수행하며, 의존성(dependency)으로부터 발생하는 에러율이 이동 창(rolling window) 동안 임계값을 넘으면 서킷 브레이커(circuit breaker)가 작동합니다. 일시적인 장애(transient failures)는 조용히 해결됩니다. 지속적인 장애(persistent failures)는 빠르게 포착됩니다. 새로운 방식은 실패가 HTTP 500 에러처럼 보이지 않는 에이전트를 포함합니다. 대신 의미론적으로(semantically) 틀렸지만, 유효하고 확신에 차 있으며 잘 구성된 응답처럼 보입니다. 평소에 모니터링하는 조건들인 에러율, 지연 시간(latency), 예외(exception) 횟수는 모두 정상(green) 상태를 유지합니다. 인프라는 건강합니다. 하지만 에이전트는 그렇지 않습니다. 그리고 기존의 서킷 브레이커 조건들은 이러한 차이를 포착하도록 설계되지 않았습니다.
4. 왜 재시도 사이에 확신(Confidence)이 초기화되지 않는가
이 상황을 악화시키는 점은 재시도(retries)가 확신(confidence)을 재조정(recalibrate)하기보다 오히려 증폭시키는 경우가 많다는 것입니다. 한 번 재시도한 에이전트는 이미 그 실패한 시도를 자신의 컨텍스트 윈도우(context window)에 포함하고 있습니다. 이제 에이전트는 첫 번째 접근 방식이 작동하지 않았음을 알기에, 다른 방향으로 추론합니다. 이때 보통 더 높은 확신을 가지고 추론하게 되는데, 이는 가능성을 하나씩 제거해 나가고 있기 때문입니다. 이는 여러분이 원하는 바와 정반대입니다. 전통적인 시스템에서의 서킷 브레이커(circuit breaker)는 의존성(dependency)이 실패할 때 이를 완전히 차단함으로써, 호출자(caller)가 망가진 기반 위에서 더 깊은 가정을 쌓아가는 것을 방지합니다. 에이전트의 경우에도 추론 스레드(reasoning thread)가 같은 자리를 맴돌고 있다면(circling), 더 창의적인 파라미터 변형을 시도하며 확신을 높여가며 재시도하는 것이 아니라, 해당 추론 스레드를 차단해야 합니다.
5. 에이전트 추론을 위한 서킷 브레이커가 실제로 모니터링하는 것
전통적인 시스템에서 서킷 브레이커는 이동 창(rolling window) 내에서 의존성의 에러율이 임계값(threshold)을 넘을 때 작동합니다. 이는 *Release It! *(Pragmatic Bookshelf, 2007)에서 설명하는 패턴과 같습니다.
6. 트리핑 조건(Trip Condition)과 그 이후에 발생하는 일
전통적인 서킷 브레이커가 트리핑(trips)되면 회로를 개방(opens)합니다. 즉, 냉각 기간(cooldown period) 동안 실패하는 의존성으로 더 이상 요청을 보내지 않습니다. 에이전트의 경우, 이에 상응하는 조치는 대기 중인 작업의 가역성(reversibility)에 따라 추론 스레드를 중단하고 사람에게 전달하거나, 폴백 정책(fallback policy)을 실행하거나, 강제 중단(hard abort)하는 것입니다. 제 경험상, 팀들이 이를 건너뛰는 이유는 논리에 동의하지 않아서가 아니라, 스택의 어느 지점에 트리핑 조건(trip condition)을 두어야 할지 모르기 때문입니다. 이는 에이전트 자체가 아니라 오케스트레이션 계층(orchestration layer)에 속해야 합니다. 에이전트는 한 번에 하나의 재시도만을 봅니다. 오케스트레이터(orchestrator)는 재시도 전반에 걸친 패턴을 봅니다. 동일한 목표를 향해 점점 더 절박하게 다섯 번을 시도하는 것이, 더 많은 창의성으로 해결할 문제가 아니라 개방되어야 할 회로라는 것을 인식할 수 있는 것은 오직 오케스트레이터뿐입니다.
7. 당신이 주시하지 않고 있는 경고
제 경험상, 대부분의 에이전트 모니터링 설정은 도구 호출 지연 시간(tool call latency)과 에러율(error rate)에 대한 알림을 갖추고 있습니다. 하지만 의도(intent)당 재시도율(retry rate) — 즉, 에이전트가 성공하거나 중단하기 전까지 동일한 근본 목표를 몇 번이나 시도했는지 — 에 대한 알림을 갖춘 경우는 거의 없습니다. 이 수치가 상승하는 추세는 도구가 느리다는 신호가 아닙니다. 그것은 특정 의도 유형에 대한 에이전트의 추론(reasoning)이 불안정하다는 신호이며, 그 불안정성은 해당 의도를 트리거하는 모든 사용자에게 복리로 쌓이게 됩니다. 도구 호출 스팬(tool call spans)과 함께 추론 스레드(reasoning thread)당 재시도 횟수를 로그로 남기세요. 지연 시간을 추적하는 것과 동일한 방식으로 이를 이동 p95(rolling p95)로 추적하십시오. 특정 의도 카테고리에서 이 수치가 상승 추세를 보인다면, 그것은 인프라 문제가 아니라 추론의 보정 오류(reasoning miscalibration)입니다. 그리고 그 해결책은 더 긴 백오프 시간(backoff time)이 아니라, 프롬프트 변경이나 도구 규약(tool contract)의 수정입니다.
서킷 브레이커(Circuit Breaker)가 분산 시스템에서 가장 잘 확립된 패턴 중 하나인 이유는, 팀들이 "시스템이 재시도 중이다"라는 상황을 "시스템이 회복 중이다"라는 상황과 혼동하는 것을 방지해주기 때문입니다. 이 둘은 서로 다른 것이며, 그 차이는 여러분이 구축한 그 어떤 API보다 에이전트에게 더 중요합니다. 왜냐하면 에이전트는 자신이 루프(loop)에 빠져 있다는 사실을 알지 못하기 때문입니다. 에이전트는 외부에서 이 패턴이 처음부터 제공했어야 할 입마개(muzzle)를 씌워줄 때까지 확신에 차서 계속 진행할 뿐입니다. 에이전트가 프로덕션에 배포되기 전에 차단 조건(trip condition)을 구축하십시오. 그것이 필요해지는 시점이 되면, 그것을 설계할 시간이 없을 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Hacker Noon AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기