최근 스터디에서 '가상면접 사례로 배우는 대규모 시스템 설계 기초 2'를 하고있는데
11장 결제 시스템에서 멱등성이라는 개념이 나와 전에 작업했을때 비슷한 경험이 있어서 정리해볼까한다
책에서는 멱등성이란 최대 한 번 실행을 보장하기 위한 핵심 개념으로 안내하고있다
위키백과에 따르면 “멱등성은 수학 또는 컴퓨터 과학적 연산이 가질 수 있는 한 가지 속성으로, 연산을 여러 번 실행하여도 최초 실행 결과가 그대로 보존되는 특성을 일컫는다”
API 관점에서 보면 멱등성은 클라이언트가 같은 API 호출을 여러 번 반복해도 항상 동일한 결과가 나온다는 뜻이 된다

PSP란? 결제 서비스 공급자, 즉 Payment Service Provider
참고 : RFC 7231
| Method | Safe | Idempotent | Reference |
|---|---|---|---|
| CONNECT | no | no | Section 4.3.6 |
| DELETE | no | yes | Section 4.3.5 |
| GET | yes | yes | Section 4.3.1 |
| HEAD | yes | yes | Section 4.3.2 |
| OPTIONS | yes | yes | Section 4.3.7 |
| POST | no | no | Section 4.3.3 |
| PUT | no | yes | Section 4.3.4 |
| TRACE | yes | yes | Section 4.3.8 |
표에 따르면
그렇다면 책에 나온 방법대로 하는것이 맞는가?
나는 아니라고 생각한다
책은 참고일뿐 항상 실제 구현할때와 책과는 조금 차이가 있다
실제 구현은 많이 쓰는 방법으로 구글링해서 정리하였고 시스템마다 각각 좋은 방법이 다를수 있으니 이런 방법도 있었구나 하고 참고하시면 되겠다
| 구분 | 책 | 실제 구현 |
|---|---|---|
| 멱등키 조건 | 유니크한 UUID | 유니크한 UUIDv4 |
| API 호출시 멱등키의 위치 | body내 필드에 존재 | 요청 header에 포함 권장 |
| 멱등키 UUID 발급 주체 | 클라이언트에서 발급 | 클라이언트에서 발급(권장)하거나 내부서버나 외부의 고유 ID 발급 서비스(예: AWS의 DynamoDB, Redis)를 사용해 멱등 키를 발급하여 응답으로 내려줌 |
| 멱등키 UUID 저장 | 멱등키 DB에 별도 저장 | 멱등키 DB에 별도 저장 |
| 에러 코드 | 처리 후 그외의 같은 멱등키일 경우 429 Too Many Requests | 이전 요청 처리가 아직 진행 중에 같은 멱등키로 새로운 요청이 올 때 409 Conflict payload가 처음 요청과 다른데 같은 멱등키를 또 사용했을 때 422 Unprocessable Entity |
개인적으로 전직장때 비슷한 작업을 한 적있다
어드민에서 저장을 누르면 캐싱이 갱신되는 방식이였는데
저장을 누를때마다 갱신되니 누가 나쁜마음을 먹고 연속적으로 누르거나 따닥을 하게되면
N번 저장되고 N번 캐싱이 같은 내용으로 갱신된다는게 비효율적으로 느껴졌었다.
이걸 고쳐보고자 처음에는 서버에서 동일한 요청인지 payload와 db에 저장되어있는 값 하나하나 체크했었는데
어느순간 이게 많아지면 너무 속도에 영향을 준다는 생각이 들어서
클라이언트에 멱등키 UUID를 발급을 요청했던 경험이 있었다
하지만 클라이언트도 값이 변경될때마다 UUID를 재발급해야되는 로직이 필요했고
이게 클라이언트도 조금 부담인건지 로직이 꼬여 에러가 발생하는 상황이 생겼었다
괜히 나의 욕심으로 클라이언트가 부담이 된 것같아 다시 초반처럼 서버에서 payload를 하나하나 체크하는 것으로 롤백하였던 기억이있다
(에러코드는 어드민이라 운영자가 따닥 하는 실수를 방지하거나 같은 사용자가 같은 내용을 계속 보내는 걸 방지하는게 목적이라 그때 당시에는 이전 요청과 동일할 경우엔 별도로 에러코드로 안뱉고 서버내에서만 저장로직을 안타고 그대로 응답을 내려주었었다)
결제할때의 멱등성 보장은 반드시 해야되는 문제고 작업하다보면 상황에 따라 다른 도메인에서도 멱등성을 보장해야되는 도메인이 있을것이다
멱등성을 보장하기 전 멱등키를 어디서 어떻게 발급하고 서버에서는 어떻게 관리를 해나갈것인가? 에 대해 좀더 고민해보고 구현하는 것이 좋을것같다
참조문헌
알렉스 쉬/산 람, 「가상 면접 사례로 배우는 대규모 시스템 설계 기초 2」, 이병준, 인사이트(insight)
https://docs.tosspayments.com/blog/what-is-idempotency
https://f-lab.kr/insight/understanding-idempotency-and-its-applications
https://f-lab.kr/insight/understanding-idempotency-in-api-design