PG 연동 결제 API를 붙였는데 며칠 전에 사고가 하나 났습니다. 결제 요청을 보냈는데 응답이 늦게 오길래 타임아웃이 떴고, 저희 쪽에서 자동으로 한 번 더 재시도를 했거든요. 근데 알고 보니 첫 요청이 실패한 게 아니라 그냥 응답만 늦었던 거라 결과적으로 같은 유저한테 두 번 결제가 잡혔더라고요. 환불 처리하느라 진땀 뺐습니다.


찾아보니까 이런 걸 멱등성 키(Idempotency-Key)로 막는다고 하던데, 제가 이해한 흐름이 맞는지 봐주시면 감사하겠습니다. 클라이언트가 결제 요청마다 UUID로 키를 하나 만들어서 헤더에 실어 보내고, 서버는 그 키를 DB에 저장하면서 락을 잡는다. 그리고 같은 키로 또 요청이 들어오면 실제 결제를 다시 태우지 않고 처음에 저장해둔 응답을 그대로 돌려준다. 이런 식이요.


POST /payments
Idempotency-Key: 3f9a2c11-4b7e-4d2a-9c11-8e5f0a1b2c3d
Content-Type: application/json

{ "order_id": 10293, "amount": 15000 }


궁금한 게, POST는 원래 멱등하지 않은 메서드잖아요. 근데 이렇게 키만 붙이면 안전하게 재시도해도 되는 건가요? 그리고 저장한 키는 언제까지 들고 있어야 하는지(영구 보관은 좀 아닌 것 같고), 재시도가 첫 요청이랑 겹쳐서 거의 동시에 들어오면 락은 어떻게 처리하는 게 정석인지도 궁금합니다. 실무에서 쓰시는 분들 조언 부탁드려요.