본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 02. 07:42

왜 당신의 AI 에이전트가 이메일을 두 번 보냈을까: 멱등성 (Idempotency) 현장 가이드

요약

AI 에이전트가 API 타임아웃 시 도구를 공격적으로 재시도하면서 발생하는 중복 결제나 이메일 발송 같은 부작용 문제를 다룹니다. 이는 모델의 문제가 아닌 분산 시스템의 멱등성(Idempotency) 부재로 발생하는 운영 환경의 핵심 과제입니다.

핵심 포인트

  • 에이전트의 재시도는 쓰기 작업 시 중복 부작용을 초래할 수 있음
  • 재시도 폭풍, 동시 분기, 부분적 실패 등 4가지 주요 실패 패턴 존재
  • 해결책은 재시도를 줄이는 것이 아니라 호출을 멱등하게 만드는 것임
  • 모든 부수 효과가 발생하는 호출에 멱등성 키를 적용해야 함

지난해 저는 동일한 주문에 대해 고객의 환불을 세 번이나 처리해 버린 환불 에이전트 (refund agent)를 출시했습니다. 동일한 호출. 동일한 입력. 세 번의 Stripe 결제. 모델이 폭주한 것도 아니었습니다. 도구 (tools)가 실패한 것도 아니었습니다. 에이전트는 일시적인 API 타임아웃 (timeout) 발생 시 도구 호출을 재시도했고, 두 번째 호출은 성공했으며, 세 번째 호출은 아무도 모니터링하지 않았던 느린 경로 (slow path)를 탔습니다. 환불 엔드포인트 (endpoint)에 멱등성 키 (idempotency key)가 없었기 때문에, 작업이 세 번 실행된 것입니다.

결제, 이메일, API 쓰기 (writes), 데이터베이스 삭제 (deletes)와 같은 중복된 부작용 (side effect)은 제가 AI 에이전트 시스템에서 목격하는 가장 흔한 운영 환경 (production) 실패 사례입니다. 이것은 모델의 문제가 아닙니다. 프롬프트 (prompt)의 문제도 아닙니다. 이것은 재시도 (retry)의 문제이며, 에이전트는 여러분의 기존 HTTP 서비스가 가졌던 것보다 훨씬 더 많은 재시도를 수행합니다.

만약 여러분이 돈을 다루거나, 메일을 보내거나, 부작용을 일으키는 API를 호출하는 에이전트를 출시하고 있다면, 이 가이드는 여러분을 위한 것입니다.

실패의 형태

운영 환경의 에이전트들은 도구 호출을 공격적으로 재시도합니다. 모델은 타임아웃 (timeout), 5xx 에러, 또는 응답 누락을 감지하면 다음 턴 (turn)에 동일한 호출을 다시 발행합니다. 이는 읽기 (read) 작업에 있어서는 올바른 동작입니다. 하지만 쓰기 (write) 작업에 있어서는 재앙적입니다.

제가 반복해서 목격하는 네 가지 패턴은 다음과 같습니다:

  1. 불안정한 쓰기 엔드포인트에서의 재시도 폭풍 (Retry storms). 도구가 504 오류를 반환했지만, 부수 효과 (side effect)는 실제로 발생했습니다. 에이전트는 재시도를 수행합니다. 중복 결제, 중복 이메일, 중복 주문 이행이 발생합니다.
  2. 둘 다 "성공"하는 동시 분기 (Concurrent branches). 플래너 (planner)가 하나의 작업을 두 개의 하위 에이전트 (sub-agent)로 나눕니다. 두 에이전트 모두 동일한 의도로 동일한 결제 도구를 호출합니다. 둘 다 자신이 정식 호출 (canonical call)이라고 생각합니다. 둘 다 성공합니다.
  3. 부분적 실패 후의 보상 재시도 (Compensating retries). 첫 번째 시도가 레코드의 절반을 작성했고, 두 번째 시도는 응답을 받기 전에 타임아웃이 발생했으며, 세 번째 시도는 성공했습니다. 하지만 시스템은 첫 번째 시도가 실제였다는 사실을 전혀 알지 못합니다.
  4. 결과 캐싱이 없는 충돌-복구 재생 (Crash-recovery replays). 에이전트 프로세스가 재시작되었고, 내구 실행 프레임워크 (durable execution framework)가 모든 단계를 재생(replay)했습니다. 프레임워크의 단계 캐시 (step cache)에 부수 효과의 멱등성 키 (idempotency key)가 포함되지 않았기 때문에 부수 효과가 있는 단계들이 두 번 실행되었습니다.

이 모든 사례는 프롬프트 (prompt)로 포장된 분산 시스템 (distributed-systems) 문제입니다. 에이전트는 분산 시스템이 수십 년 동안 제대로 해내지 못했던 일을 하고 있는 것입니다. 즉, 비멱등적 (non-idempotent) 작업을 재시도하며 두 번째 시도가 성공하기를 바라는 것입니다.

해결책은 "재시도를 줄이는 것"이 아닙니다

본능적으로 재시도를 제한 (throttle)하려고 할 것입니다. 하지만 이는 문제를 악화시킵니다. 불안정한 도구는 재시도를 받을 자격이 있습니다. 해결책은 모든 부수 효과가 발생하는 호출을 재시도에 안전하게 (retry-safe) 만드는 것입니다. 이는 모든 쓰기 작업에 대해, 고유성을 보장할 만큼 충분히 좁은 범위이면서 동시에 적절한 중복을 잡아낼 수 있을 만큼 충분히 넓은 범위의 멱등성 키 (idempotency key)를 부여하는 것을 의미합니다.

구체적으로, 세 가지가 필요합니다:

  1. 도구 호출(tool call) 단위가 아닌, 논리적 작업(logical operation) 단위로 안정적인 멱등성 키 (idempotency key)를 생성하세요. 키는 작업의 의도(예: 주문 ID, 고객 ID, 작업 유형)로부터 유도되어야 하며, 동일한 논리적 작업은 재시도(retry) 시에도 동일한 키를 생성해야 합니다. 만약 재시도할 때마다 새로운 UUID를 생성한다면, 문제를 해결한 것이 아닙니다. Stripe의 멱등성 키가 이런 방식으로 작동하는 데에는 이유가 있습니다.

  2. 키를 다운스트림 API (downstream API)에 전달하여 중복 제거 (dedupe)를 맡기세요. 대부분의 현대적인 쓰기 API (Stripe, Twilio, SendGrid, HubSpot, GitHub, Slack, 모든 데이터베이스 트랜잭션)는 멱등성 키를 수용합니다. 이를 활용하세요. 만약 사용 중인 API가 지원하지 않는다면, 자체적인 중복 제거 레이어(dedupe layer)로 호출을 감싸세요. "최근 24시간 내에 확인된 키"를 저장하는 작은 테이블만으로도 충분합니다.

  3. 호출뿐만 아니라 결과(result)를 캐싱하세요. 내구적 실행 프레임워크 (Durable execution frameworks: Inngest, Temporal, Restate)는 단계별 결과(step results)를 캐싱하므로, 재실행(replay) 시 캐싱된 결과를 확인하고 부수 효과 (side effect)를 건너뜁니다. 프레임워크를 사용하지 않는다면, 부수 효과 원장 (side-effect ledger)이 필요합니다. 즉, 다음 재시도 시 참조할 수 있는 "이 멱등성 키, 이 결과"에 대한 기록이 있어야 합니다.

오늘 바로 실행할 수 있는 10분 감사 (audit)

최근 발생한 5건의 운영 장애 (production incidents)를 살펴보세요. 각 사례에 대해 다음 질문에 답해 보십시오.

  • 에이전트가 동일한 논리적 작업에 대해 부수 효과를 일으키는 도구를 두 번 이상 호출했는가? 만약 그렇다면, 그것이 근본 원인입니다.
  • 도구 호출에 멱등성 키가 포함되어 있는가? 포함되어 있지 않다면, 중복 발생은 구조적으로 보장된 것이나 다름없습니다.
  • 프레임워크가 해당 단계를 재실행(replay)했는가? 만약 그렇고 해당 단계에 결과 캐시가 없다면, 중복은 반드시 발생하게 되어 있습니다.

첫 번째 질문에 대한 답이 단 하나의 장애 사례에서라도 '예'라면, 멱등성은 당신의 가장 우선적인 운영 부채 (operational debt)입니다. 다른 모든 문제는 이 문제의 하위 결과일 뿐입니다.

더 흥미로운 신호는 "간헐적(intermittent)"이며 "X의 중복을 포함하는" 장애들입니다. 이는 거의 항상 멱등성 문제입니다. 제가 함께 일했던 에이전트 팀 중 분기에 이러한 사례가 3건 이상 발생한 팀은 모델의 문제가 아니라 도구(tooling)의 결함이 있는 팀이었습니다.

도구 레이어(tooling layer)가 제공하지 않는 것

LangSmith, Langfuse, Helicone, Arize, 그리고 Braintrust는 모두 트레이스(traces)를 제공합니다. 하지만 그 중 어느 것도 사이드 이펙트(side effects)의 중복을 제거(dedupe)해주지는 않습니다. 이 도구들은 중복된 도구 호출(tool call)을 보여줄 뿐, 그것을 막아주지는 않습니다. 재시도 정책(retry policy), 멱등성 키(idempotency key), 결과 캐시(result cache), 그리고 내구 실행 프레임워크(durable execution framework)는 모두 여러분이 그 위에 직접 구축하거나 구매해야 하는 것들입니다.

그 부분이 바로 대부분의 팀이 건너뛰는 지점입니다. 그리고 바로 그 부분이 가장 중요한 지점입니다.

만약 여러분이 프로덕션 에이전트(production agent)에서 발생하는 중복 사이드 이펙트 문제로 한계에 부딪혔고, 트레이스에 대한 정밀 분석 — 5개의 트레이스, 실제 근본 원인에 대한 한 페이지 분량의 보고서, 그리고 구체적인 수정 목록 — 을 원하신다면, 제가 149달러에 도와드리겠습니다. Milo Antaeus, AI Ops Checkup: miloantaeus.com/ai-ops-checkup.html.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0