two-thirteen
멱등 키: 같은 요청을 두 번 보내도 한 번만 처리하게
멱등 키: 같은 요청을 두 번 보내도 한 번만 처리하게
2026-11-09 Engineering Practices

멱등 키: 같은 요청을 두 번 보내도 한 번만 처리하게

재시도가 기본인 서버리스·에이전트 시대에 꼭 필요한 멱등 키(idempotency key)의 동작을 Stripe API 문서를 따라 정리한 메모입니다. 키 생성, 보관 기간, 파라미터가 다를 때의 처리, GET·DELETE에 쓰지 않는 이유를 다룹니다.

Lambda Durable Functions 글을 쓰며 "step 안에서 부르는 외부 시스템의 중복은 직접 막아야 한다"고 적었습니다. 그럼 어떻게 막는가. 이 분야의 교과서 같은 Stripe 문서를 다시 읽었습니다.

문제: 응답을 못 받았을 때

결제 API를 불렀는데 연결이 끊겼습니다. 결제가 됐는지 안 됐는지 모릅니다. 다시 부르면 두 번 결제될 수 있고, 안 부르면 결제가 빠질 수 있습니다.

재시도가 기본인 시스템에서는 이 상황이 일상입니다. 서버리스 플랫폼도, 메시지 큐도, 에이전트 프레임워크도 실패하면 다시 시도합니다.

해법: 요청에 이름을 붙인다

Stripe는 요청 헤더에 멱등 키를 붙이게 합니다.

curl https://api.stripe.com/v1/customers \
  -u sk_test_...: \
  -H "Idempotency-Key: KG5LxwFBepaKHyUD" \
  -d description="My First Test Customer"

같은 키로 다시 보내면 서버는 이것이 같은 요청의 재시도임을 알아봅니다. 연결 오류가 나도 객체가 두 번 만들어지거나 갱신이 두 번 일어날 걱정 없이 다시 보낼 수 있습니다.

문서가 정한 세부 규칙

  • 첫 응답을 저장해 돌려준다: v1 기준, 엔드포인트 실행이 시작된 뒤 첫 요청의 상태 코드와 본문을 저장합니다. 같은 키의 재시도에는 저장된 응답을 그대로 돌려줍니다. 500 오류도 그대로입니다.
  • 키는 클라이언트가 만든다: V4 UUID처럼 충돌하지 않을 만큼 무작위인 문자열을 권장합니다. 최대 255자이고, 이메일 같은 민감 정보는 키로 쓰지 말라고 합니다.
  • 24시간 뒤 정리될 수 있다: 정리된 뒤 같은 키를 쓰면 새 요청으로 처리됩니다.
  • 파라미터가 다르면 오류: 같은 키인데 내용이 다르면 실수로 보고 오류를 냅니다.
  • 실행 전 실패는 저장하지 않는다: 입력 검증에서 떨어졌거나 동시에 실행 중인 요청과 충돌하면 결과를 저장하지 않으니 다시 보내면 됩니다.
  • POST에만: GET과 DELETE는 원래 멱등이라 키가 의미 없습니다.

내 시스템에 적용한다면

키를 어디서 만드느냐가 관건입니다. 재시도할 때마다 새 UUID를 만들면 의미가 없습니다. 작업 단위가 정해지는 순간 한 번 만들어 저장해 두고, 재시도에서는 그 값을 다시 써야 합니다.

Durable Functions처럼 체크포인트가 있는 실행 환경이라면, 키를 만드는 일 자체를 step으로 감싸 두면 재실행 때도 같은 키가 나옵니다. 키 생성과 외부 호출을 같은 step에 넣으면, 재실행 때 새 키로 다시 부르는 실수가 생길 수 있으니 조심해야 합니다.