Design · Development · Thoughts

안녕하세요,
Practical AI Lab 입니다.

AI·에이전트·LLM 실전 연구

AI 에이전트 재시도 중복 실행 방지: 멱등성 설계


반응형

여러 요청 경로가 하나의 개찰구로 모이는 멱등성 설계 대표 이미지

AI 에이전트 재시도 중복 실행 방지는 프롬프트만으로 보장할 수 없습니다. 2026년 9월 18일 기준, 쓰기 도구를 자동화한다면 업무 작업마다 멱등성 키를 저장하고 서버가 중복 요청을 판별하도록 설계해야 합니다. 다만 키의 보관 기간·동시 처리·외부 시스템 경계까지 다루지 않으면 ‘한 번만 실행’이라는 약속은 깨집니다.

이 글은 Stripe의 Idempotent requests, AWS Builders’ Library의 Making retries safe with idempotent APIs, MCP 2025-06-18 Tools 명세를 바탕으로 티켓 생성 에이전트의 재시도 구조를 설명합니다. 특정 제품의 신규 기능 소개가 아닌 기술 해설이며, 아래 티켓 사례와 운영 체크리스트는 문서 원리를 적용한 설계 예시입니다.

이 글의 핵심
  • 1~2장: 업무 작업과 개별 호출을 나누고 응답 유실을 해석하는 법
  • 3장: 멱등성 키를 발급·저장·재사용하는 위치
  • 4~5장: 티켓 생성 사례와 재시도 전략의 역할 비교
  • 6장: 동시 실행·보관 기간·외부 API의 실패 경계
  • 7장: 배포 전 테스트와 관측 항목

핵심 원문: AWS의 멱등 API 설계 설명


1. AI 에이전트 재시도에서 멱등성이 뜻하는 것

업무 작업과 네트워크 호출을 구분합니다

사용자가 ‘장애 티켓 하나를 만들어 달라’고 승인한 것이 업무 작업입니다. 그 요청을 전달하다 연결이 끊겨 다시 보내는 것은 새로운 업무가 아닌 전달 시도입니다. 멱등성은 같은 업무 요청을 반복해도 추가 부작용을 만들지 않는 성질입니다.

한 번만 전달된다는 뜻은 아닙니다

AWS 문서는 동일 요청 식별자를 사용한 재시도에 의미상 동등한 응답을 제공하는 계약을 설명합니다. 이 글에서 다루는 대상은 전달 횟수보다 티켓 같은 업무 객체의 중복 생성 여부입니다.


2. 타임아웃 뒤 무조건 재실행하면 왜 중복될까?

티켓 생성 완료 뒤 응답 유실로 에이전트가 결과를 모르는 흐름

실행은 끝났는데 응답만 사라질 수 있습니다

서버가 티켓을 저장한 직후 응답 연결이 끊겼다고 가정합니다. 에이전트는 성공 메시지를 받지 못했지만 티켓은 존재합니다. 여기서 새 요청으로 다시 생성하면 티켓이 하나 더 생깁니다. AWS가 설명하는 ‘처리는 됐지만 응답을 받지 못한 호출’이 바로 이 모호한 상태입니다.

도구 오류는 처리 상태와 함께 읽어야 합니다

MCP Tools 명세는 JSON-RPC 프로토콜 오류와 isError: true로 전달하는 도구 실행 오류를 구분합니다. 이 오류 구분만으로 연결된 외부 시스템의 변경이 전부 취소됐다고 판단해서는 안 됩니다. 도구 구현은 업무 식별자와 조회 방법, 재시도 가능 여부를 함께 전달하도록 설계하는 편이 안전합니다.

이 글의 운영 제안: 상태를 성공·실패 두 개로만 두지 말고 ‘결과 미확인’을 별도로 둡니다. 쓰기 요청에서 타임아웃을 만나면 기존 작업 조회 또는 동일 키 재시도로 분기하고, 새 업무 작업을 즉시 만들지 않습니다.


3. 멱등성 키는 어디서 만들고 언제 재사용할까?

작업 확정부터 동일 키 재사용과 결과 재전달까지의 흐름

키는 모델의 재생성 영역 밖에 둡니다

업무 작업을 확정하는 애플리케이션 계층이 식별자를 만들고 영속 저장하도록 설계합니다. 에이전트 세션이 재시작되거나 담당 하위 에이전트가 바뀌어도 동일 작업 레코드를 참조하게 합니다. 매번 모델에게 새 UUID를 생성시키면 서버는 각 시도를 서로 다른 요청으로 인식할 수 있습니다.

AWS는 호출자가 제공한 고유 요청 식별자를 선호하는 이유로 의도를 명확히 표현할 수 있다는 점을 듭니다. 같은 제목의 티켓 두 개가 실제로 필요한 경우도 있기 때문입니다.

같은 키에 다른 내용을 넣지 않습니다

서버는 사용자 또는 테넌트·작업 종류·멱등성 키를 적절한 범위로 묶어 조회하고, 최초 요청의 주요 인자와 새 요청을 비교해야 합니다. 같은 키인데 티켓 대상이나 내용이 바뀌었다면 충돌로 처리합니다. AWS와 Stripe 모두 같은 식별자에 다른 인자를 넣는 경우를 검증 오류로 다룹니다.

Stripe 문서는 충분한 엔트로피가 있는 임의 문자열이나 UUID v4를 키 생성 방식으로 권장하며, 이메일 같은 민감정보를 키에 넣지 말라고 안내합니다. 아래 예시의 op-demo-001은 설명용 값이지 운영용 키 형식 권장이 아닙니다.


4. 티켓 생성 에이전트에 적용하는 설계 예시

업무 레코드를 먼저 남깁니다

다음은 실제 서비스 응답이나 실행 로그가 아닌 개념용 JSON입니다. 애플리케이션이 보관할 최소한의 관계를 보여 줍니다. operation_id는 사용자 의도를 가리키고 idempotency_key는 해당 생성 요청의 재전달에 사용합니다. 여러 단계의 업무라면 단계별 키를 따로 연결합니다.

{
  "operation_id": "op-demo-001",
  "tool": "create_ticket",
  "idempotency_key": "demo-ticket-step-001",
  "arguments": {"project": "support", "title": "접속 장애 확인"},
  "state": "pending",
  "result_id": null
}

재시도는 기존 작업의 이어서 처리입니다

첫 호출에 응답이 없으면 이 레코드를 읽고 동일한 키와 인자로 다시 요청합니다. 도구 서버가 이미 작업을 완료했다면 보관한 결과 식별자를 반환하고, 진행 중이라면 그 상태에 맞는 대기·조회 계약을 적용합니다. 성공을 확인한 뒤 result_id를 기록하면 이후 에이전트는 티켓 내용을 조회할 수 있습니다.

승인 흐름이 필요한 쓰기 도구에서는 ‘승인받은 대상·인자’와 이 작업 레코드를 결속하는 것이 별도 과제입니다. 입력 요청과 외부 승인 흐름의 차이는 MCP Elicitation 작동 원리: 입력 요청과 URL 승인 차이에서 다뤘습니다.


5. 백오프·상태 조회와 멱등성 키는 무엇이 다를까?

백오프와 멱등성 키와 상태 조회의 서로 다른 역할 비교

부하 제어와 중복 제어를 함께 적용합니다

수단 해결하는 문제 단독으로 남는 빈틈
백오프·지터 장애 중 요청 집중 완화 늦게 보낸 요청도 중복 생성 가능
멱등성 키 같은 업무 요청의 중복 식별 서버 계약·보관 기간에 의존
상태 조회 기존 작업의 결과 확인 조회와 재실행 사이 상태 변화 가능
사람 확인 결과 미확인 상태의 의사결정 동시 호출 자체를 원자적으로 막지는 못함

운영 설계에서는 서버가 안내하는 재시도 규칙과 제한을 따르면서 이 수단들을 결합합니다.

제품별 응답 재사용 정책을 확인합니다

Stripe 공식 문서는 첫 요청의 상태 코드와 본문을 저장해 같은 키의 후속 요청에 반환하며, 여기에 500 오류도 포함된다고 설명합니다. 같은 키로 반복하면 언젠가 성공 응답으로 바뀐다는 가정은 틀릴 수 있습니다.

다만 실행 시작 전의 인자 검증 실패나 동시 실행 요청과의 충돌은 결과를 저장하지 않는 예외로 설명합니다. 이는 Stripe의 계약이며 모든 도구 서버의 공통 동작이 아닙니다. 에이전트용 도구 문서에도 어느 오류가 재사용되고 어느 오류가 다시 실행되는지 명시해야 합니다.


6. 동시 요청·키 만료·외부 API에서 생기는 한계

동시 요청과 키 만료와 원격 부작용에서 생기는 보장 한계

조회 후 저장 사이의 경쟁을 막아야 합니다

두 워커가 동시에 ‘키 없음’을 확인한 뒤 각자 티켓을 만들면 단순한 캐시 조회는 실패합니다. AWS 문서는 멱등성 토큰 기록과 관련 변경 작업을 ACID 특성에 맞게 처리해야 한다고 설명합니다. 같은 데이터베이스 안에서라면 고유 제약과 트랜잭션 등으로 최초 처리권 확보와 업무 변경을 연결하는 설계가 필요합니다.

보관 기간이 지난 재시도는 새 작업이 될 수 있습니다

Stripe는 키가 최소 24시간 지난 뒤 제거될 수 있으며, 제거된 키를 재사용하면 새 요청을 만든다고 명시합니다. ‘24시간마다 반드시 삭제’ 또는 ‘영원히 중복 방지’로 읽으면 안 됩니다. 자동화의 최대 재시도 기간과 서비스의 키 보관 정책을 함께 정해야 합니다.

원격 부작용은 로컬 트랜잭션 밖에 있습니다

로컬 DB에 처리 완료를 쓰는 것과 외부 메일 발송은 일반적으로 하나의 DB 트랜잭션이 아닙니다. 메일은 전송됐지만 완료 기록 전에 프로세스가 죽을 수 있습니다. 이 경우 원격 서비스의 멱등성 지원이나 메시지·작업 식별자 조회, 대사 절차가 별도로 필요합니다.

멱등성을 지원하지 않고 결과 조회도 불가능한 쓰기 API에서는 에이전트 앞단에 키를 붙였다는 사실만으로 종단 간 정확히 한 번 처리를 보장할 수 없습니다. 모호한 결과를 보류하거나 사람에게 넘기는 정책까지 설계해야 합니다.


7. 배포 전에 확인할 테스트와 로그 항목

장애를 넣는 위치를 바꿔 테스트합니다

  • 서버 변경 직후 응답을 끊고 재시도해 업무 객체가 늘어나는지 확인합니다.
  • 같은 키·같은 인자를 동시에 보내고 최종 생성 객체 수와 응답 계약을 대조합니다.
  • 같은 키에 다른 인자를 보내 명시적인 충돌이 나오는지 확인합니다.
  • 프로세스 재시작 후 기존 업무 키를 복구하는지 확인합니다.
  • 키 보관 기간 밖의 지연 요청을 보내 만료 정책이 적용되는지 확인합니다.

이 목록은 권장 검증 시나리오이며 이번 글에서 실제 외부 API를 호출한 결과는 아닙니다. 테스트 성공을 서비스 완료와 구분하는 방법은 AI 코딩 에이전트 검증 루프: 테스트 통과와 완료의 차이를 함께 참고할 수 있습니다.

로그는 업무 단위와 시도 단위를 나눕니다

업무 식별자, 개별 시도 식별자, 도구 이름, 처리 상태, 원격 결과 ID, 중복 응답 재사용 여부를 연결해 기록합니다. 개인정보가 포함된 인자를 그대로 남기기보다 필요한 필드만 제한해 보관합니다. 그래야 ‘여러 번 호출됐지만 업무는 하나’와 실제 중복 생성을 구분해 점검할 수 있습니다.


8. Q&A와 정리

Q1. 읽기 전용 도구에도 같은 장치가 필요한가요?

업무 상태를 변경하지 않는 조회는 중복 생성 위험이 상대적으로 작습니다. 그래도 호출 비용·레이트리밋·조회 시점 차이는 남으므로 재시도 횟수와 결과 신선도를 관리해야 합니다.

Q2. 사용자가 직접 다시 눌렀을 때도 같은 작업인가요?

화면에서 ‘재전송’인지 ‘추가 생성’인지 구별해야 합니다. 이전 요청이 처리 중인지 보여 주고, 새 작업이 필요한 경우에만 별도 의도를 확정하는 방식이 좋습니다.

Q3. 취소 요청도 따로 식별해야 하나요?

생성과 취소는 서로 다른 업무 동작입니다. 취소에도 자체 재시도 계약을 두고 원래 작업 ID와 연결해야 뒤늦게 도착한 생성 요청과의 순서를 추적하기 쉽습니다.

Q4. 멱등성 키를 알면 남의 결과를 볼 수 있나요?

키가 권한을 대신해서는 안 됩니다. 같은 키를 제시해도 인증·테넌트·리소스 권한 검사를 거쳐야 하며 결과를 재전달할 때도 이 검사를 생략하지 않아야 합니다.

Q5. 멱등성 처리는 악성 도구 호출도 막나요?

허용되지 않은 작업의 최초 실행까지 차단하는 장치는 아닙니다. 권한 제한·사용자 승인·입력 검증은 별도의 통제이며 중복 방지와 함께 적용해야 합니다.

설계 리뷰에서는 ‘어떤 범위와 기간에서 추가 부작용을 막는가’를 문서로 남기십시오. 그 범위를 벗어난 요청은 정상 경로와 다른 복구 정책을 가져야 합니다.


9. 참고 자료

반응형