멱등성 설계의 함정: 두 번째 요청이 달라지면 벌어지는 일

대표 이미지

멱등성 설계의 함정: 두 번째 요청이 달라지면 벌어지는 일

단순한 키 조회로 해결된다고 믿었던 멱등성 구현이 실제 분산 시스템의 동시성 충돌과 데이터 불일치 상황에서 어떻게 무너지는지 분석하고 실무적인 해결책을 제시합니다.

분산 시스템을 설계하는 개발자라면 누구나 ‘멱등성(Idempotency)’이라는 단어를 접합니다. 동일한 요청을 여러 번 보내도 결과가 항상 같아야 한다는 이 개념은 이론적으로 매우 단순해 보입니다. 많은 팀이 멱등성 키(Idempotency Key)를 데이터베이스에 저장하고, 이미 존재하는 키라면 기존 응답을 그대로 반환하는 방식으로 구현합니다. 하지만 실제 운영 환경에서는 이 단순한 논리가 처참하게 무너지는 순간이 옵니다. 바로 ‘ 요청이 와 미세하게 다를 때’입니다.

우리는 보통 네트워크 오류로 인한 재시도(Retry) 상황만을 가정합니다. 하지만 클라이언트의 버그, 악의적인 요청, 혹은 프런트엔드 프레임워크의 상태 관리 오류로 인해 동일한 멱등성 키를 가지고 있지만 내용은 다른 요청이 들어오는 경우가 빈번합니다. 이때 시스템이 단순히 키의 존재 여부만 확인하고 이전 응답을 반환한다면, 사용자는 데이터가 수정되었다고 믿지만 실제로는 아무런 변화가 일어나지 않는 ‘침묵의 실패’를 경험하게 됩니다.

멱등성 구현이 생각보다 어려운 진짜 이유

단순한 키-값 저장소 방식의 멱등성 처리가 위험한 이유는 요청의 ‘의도’와 ‘식별자’를 동일시하기 때문입니다. 멱등성 키는 요청의 고유성을 보장하는 수단이지, 요청 내용의 무결성을 보장하는 수단이 아닙니다. 여기서 발생하는 핵심적인 문제들은 다음과 같습니다.

  • 페이로드 불일치(Payload Mismatch): 동일한 request_id를 사용하면서 결제 금액이나 수신자 주소를 변경해 보낸 경우, 서버는 이를 동일 요청으로 간주해 이전의 잘못된 결과를 반환합니다.
  • 동시성 경합(Race Condition): 거의 동시에 두 개의 동일한 요청이 들어왔을 때, 요청이 처리 완료되어 응답을 저장하기 전 요청이 진입하면 중복 처리가 발생할 수 있습니다.
  • 부분적 성공과 불확실성: 외부 API(예: PG사 결제)를 호출한 후 우리 시스템의 DB 업데이트 직전에 타임아웃이 발생했다면, 재시도 시 이 요청을 ‘성공’으로 볼 것인지 ‘실패’로 볼 것인지 결정하기 어렵습니다.
  • 응답 재생(Response Replay)의 한계: 저장된 응답을 그대로 돌려주는 방식은 효율적이지만, 응답에 포함된 타임스탬프나 일회성 토큰이 만료되었을 때 클라이언트에게 유효하지 않은 데이터를 제공하게 됩니다.

기술적 구현 전략: 단순 저장을 넘어 검증으로

단순히 키가 있는지 확인하는 수준을 넘어, 진정한 멱등성을 확보하기 위해서는 ‘요청 해시 검증’과 ‘상태 머신’ 도입이 필요합니다. 요청이 들어오면 멱등성 키뿐만 아니라 요청 바디(Request Body) 전체를 해싱하여 함께 저장하는 방식입니다.

만약 동일한 키로 요청이 들어왔는데 해시값이 다르다면, 이는 재시도가 아니라 ‘잘못된 요청’으로 간주하여 400 Bad Request 또는 409 Conflict 에러를 반환해야 합니다. 이를 통해 클라이언트에게 멱등성 키를 재사용하면서 내용을 변경했다는 사실을 명확히 알릴 수 있습니다.

또한, 분산 락(Distributed Lock)을 활용해 원자성을 보장해야 합니다. Redis의 Redlock이나 DB의 SELECT FOR UPDATE를 통해 특정 멱등성 키에 대해 한 번에 하나의 프로세스만 접근하도록 제어함으로써 동시성 문제를 해결할 수 있습니다. 처리 상태를 STARTED, SUCCESS, FAILED로 세분화하여 관리하면, 처리 중인 요청에 대한 중복 진입을 효과적으로 막을 수 있습니다.

실제 사례: 이커머스 결제 시스템의 붕괴와 복구

한 이커머스 플랫폼에서는 주문 생성 API에 멱등성 키를 도입했습니다. 초기 설계는 간단했습니다. order_id가 DB에 있으면 기존 주문 정보를 반환하는 식이었습니다. 하지만 어느 날, 사용자가 주문 수정 페이지에서 상품 수량을 변경한 뒤 ‘결제하기’를 눌렀는데, 네트워크 지연으로 인해 버튼을 여러 번 클릭하는 상황이 발생했습니다.

요청은 수량 1개로 전송되었고, 서버는 이를 처리하기 시작했습니다. 하지만 클라이언트 측에서 상태 업데이트가 늦어지며 수량 2개로 변경된 요청이 동일한 order_id로 전송되었습니다. 서버는 이미 해당 키가 존재하므로 ‘성공’ 응답과 함께 수량 1개인 주문 정보를 반환했습니다. 사용자는 2개를 주문했다고 생각했지만, 실제로는 1개만 결제된 것입니다. 이는 전형적인 ‘ 요청의 내용 변경’으로 인한 멱등성 오류 사례입니다.

이 팀은 이후 요청 바디의 SHA-256 해시값을 멱등성 키와 함께 저장하는 방식으로 구조를 변경했습니다. 이제는 키가 같더라도 내용이 다르면 즉시 에러를 반환하여 클라이언트가 새로운 키를 생성하거나 요청을 수정하도록 강제합니다. 결과적으로 데이터 불일치 건수는 99% 이상 감소했습니다.

멱등성 설계의 장단점 비교

멱등성을 엄격하게 구현하는 것은 시스템의 안정성을 높이지만, 그만큼 비용이 따릅니다. 아래 표는 단순 구현과 엄격한 구현의 차이를 보여줍니다.

구분 단순 키 조회 방식 해시 검증 및 상태 관리 방식
구현 난이도 낮음 (단순 KV 저장) 높음 (해싱, 락, 상태 머신 필요)
데이터 정밀도 낮음 (내용 변경 감지 불가) 높음 (요청 무결성 보장)
성능 오버헤드 매우 낮음 중간 (해시 계산 및 락 대기 시간)
장애 대응력 취약 (침묵의 실패 발생) 강함 (명확한 에러 피드백)

실무자를 위한 단계별 액션 가이드

지금 운영 중인 API의 멱등성이 불안하다면, 다음 단계에 따라 설계를 개선해 보시기 바랍니다.

  1. 요청 식별자 정의: 클라이언트가 생성한 UUID 기반의 멱등성 키를 필수 헤더로 받도록 강제하십시오.
  2. 페이로드 해싱 도입: 멱등성 키 저장 시, 요청 바디를 해싱하여 함께 저장하십시오. 재요청 시 키는 같지만 해시가 다르다면 409 Conflict를 반환하십시오.
  3. 원자적 상태 관리: Redis 등을 이용해 ‘처리 중’ 상태를 기록하십시오. 처리 완료 전 들어오는 동일 키 요청은 425 Too Early 또는 202 Accepted(처리 중)로 응답하십시오.
  4. 만료 정책 설정: 멱등성 키를 영구히 저장할 수는 없습니다. 비즈니스 도메인에 따라 24시간 또는 7일 등의 TTL(Time To Live)을 설정하여 저장소 부하를 관리하십시오.
  5. 하위 시스템 전파: 우리 서버만 멱등한 것이 아니라, 호출하는 외부 API(PG사, 메시징 큐 등)에도 동일한 멱등성 키를 전달하여 전체 파이프라인의 일관성을 확보하십시오.

결론: 멱등성은 ‘결과’가 아니라 ‘과정’의 일관성이다

많은 개발자가 멱등성을 ‘결과값이 같으면 된다’고 오해합니다. 하지만 진정한 멱등성은 ‘동일한 의도의 요청이 동일한 결과를 낳는 것’입니다. 의도가 바뀌었는데 결과가 같게 나오는 것은 멱등성이 아니라 오류입니다.

분산 시스템에서 완벽한 일관성을 달성하는 것은 불가능에 가깝지만, 발생 가능한 실패 케이스를 정의하고 이를 명확한 에러 코드로 응답하는 것만으로도 시스템의 신뢰도는 비약적으로 상승합니다. 지금 바로 여러분의 API 명세서를 열어, ‘동일한 키로 다른 내용을 보냈을 때 우리 시스템은 어떻게 반응하는가?’라는 질문을 던져보시기 바랍니다.

FAQ

Idempotency Is Easy Until the Second Request Is Different의 핵심 쟁점은 무엇인가요?

핵심 문제 정의, 비용 구조, 실제 적용 방법, 리스크를 함께 봐야 합니다.

Idempotency Is Easy Until the Second Request Is Different를 바로 도입해도 되나요?

작은 범위에서 실험하고 데이터를 확인한 뒤 단계적으로 확대하는 편이 안전합니다.

실무에서 가장 먼저 확인할 것은 무엇인가요?

목표 지표, 대상 사용자, 예산 범위, 운영 책임자를 먼저 명확히 해야 합니다.

법률이나 정책 이슈도 함께 봐야 하나요?

네. 데이터 수집 방식, 플랫폼 정책, 개인정보 관련 제한을 반드시 점검해야 합니다.

성과를 어떻게 측정하면 좋나요?

비용, 전환율, 클릭률, 운영 공수, 재사용 가능성 같은 지표를 함께 보는 것이 좋습니다.

관련 글 추천

  • https://infobuza.com/2026/06/01/20260601-c7gwzp/
  • https://infobuza.com/2026/06/01/20260601-mr3wk2/

지금 바로 시작할 수 있는 실무 액션

  • 현재 팀의 AI 활용 범위와 검증 절차를 먼저 문서화합니다.
  • 작은 파일럿 프로젝트로 KPI를 정하고 2~4주 단위로 검증합니다.
  • 보안, 품질, 리뷰 기준을 자동화 도구와 함께 연결합니다.

보조 이미지 1

보조 이미지 2

댓글 남기기