Quiz: Idempotency Keys and Duplicate Transfers
한국어 원문으로 표시합니다.
이체 API 가 POST 인데도 클라이언트가 응답을 못 받으면 재시도한다. RFC 9110 의 관점에서 이 상황을 가장 정확히 설명한 것은?
- POST 는 멱등이 아니므로 서버가 재시도를 거절하는 것이 규격에 맞다
- POST 도 본문이 같으면 규격상 멱등이므로 서버는 아무것도 하지 않아도 된다
- 멱등은 메서드의 성질이고 POST 는 여기 속하지 않으므로, 재시도 안전성은 애플리케이션이 따로 만들어야 한다
- 재시도는 프록시가 알아서 막으므로 서버는 중복을 고려할 필요가 없다
멱등 키 표에 기록할 때 '먼저 SELECT 해서 없으면 INSERT' 로 구현했다. 어떤 일이 벌어지는가?
- 같은 순간에 들어온 재시도 두 건이 둘 다 '없음' 을 보고 둘 다 이체를 실행할 수 있다
- SELECT 가 공유 잠금을 잡으므로 두 번째 요청은 반드시 기다렸다가 중복을 발견한다
- SQLite 는 단일 파일이므로 조회와 삽입 사이에 다른 연결이 끼어들 수 없다
- INSERT 가 나중에 실패하더라도 이미 조회에서 걸러졌으므로 결과는 같다
같은 멱등 키로 금액만 다른 요청이 들어왔다. IETF 초안이 권하는 응답과 그 이유로 알맞은 것은?
- 200 으로 답하고 나중에 온 본문으로 이체를 실행한다. 사용자의 마지막 의도가 진짜다
- 200 으로 답하고 아무 일도 하지 않는다. 키가 같으니 중복으로 보는 것이 안전하다
- 409 로 답한다. 두 요청이 충돌했으므로 잠시 뒤 다시 보내면 해결된다
- 422 로 답한다. 같은 키에 다른 본문이 온 것은 클라이언트가 고쳐야 할 요청이다
요청 본문의 지문을 json.dumps(body) 의 결과로 sha256 을 계산했다. 어떤 문제가 생기는가?
- 해시가 너무 빨라 같은 지문이 우연히 겹칠 수 있다
- 클라이언트가 필드 순서나 공백만 바꿔도 다른 지문이 되어 정상 재시도가 422 로 거절된다
- 본문에 한글이 있으면 sha256 이 계산되지 않는다
- json.dumps 는 딕셔너리 키를 항상 정렬하므로 지문이 요청마다 달라진다
멱등 키를 '완료' 로 먼저 기록하고 이체를 실행하는 구현이 있다. 이체 도중 프로세스가 죽으면?
- 키가 없으므로 재시도가 정상 처리되어 이체가 한 번 일어난다
- 재시도가 이체를 다시 실행해 돈이 두 번 나간다
- 돈은 나가지 않았는데 재시도는 '이미 처리됨' 을 받아, 이체가 영영 일어나지 않는다
- 데이터베이스가 롤백하면서 키 기록도 함께 사라져 아무 문제가 없다
멱등 키의 보관 기간을 24시간으로 정하고, 클라이언트는 최대 48시간 동안 재시도하도록 만들어져 있다. 무슨 일이 생기는가?
- 24시간이 지난 뒤 온 재시도는 기록이 없으므로 새 요청이 되어 이체가 한 번 더 일어난다
- 보관 기간이 지나면 서버가 422 로 답하므로 클라이언트가 스스로 멈춘다
- 키를 지워도 이체 번호가 같으므로 중복 삽입이 막혀 결과는 안전하다
- 클라이언트의 재시도 상한과 서버의 보관 기간은 서로 무관하므로 아무 문제가 없다