
서비스를 운영하다 보면 생각보다 단순한 행동 하나가 큰 사고로 이어질 때가 있다.
대표적인 예가 바로 이런 상황이다.
고객이 모바일 앱에서 결제하기 버튼을 급하게 두세 번 연속으로 눌렀다.
서버에는 거의 동시에 여러 요청이 들어왔고, 시스템은 이를 각각 별개의 요청으로 처리했다.
그 결과 고객은 한 번만 결제하려 했는데 실제로는 두 번, 세 번 청구되는 사고가 발생한다.
이럴 때 흔히 이렇게 생각한다.
버튼을 한 번만 누르게 막으면 되는 거 아닌가?
물론 프론트엔드에서 중복 클릭을 막는 것도 필요하다.
하지만 그것만으로는 충분하지 않다. 네트워크 재전송, 앱 재시도, 브라우저 새로고침, 외부 시스템 재호출 같은 상황은 언제든 발생할 수 있기 때문이다.
이 문제를 기술적으로 근본에 가깝게 막아주는 개념이 바로 멱등성(Idempotency) 이다.
1. 멱등성이란 무엇인가
멱등성은 쉽게 말하면,
같은 요청을 여러 번 보내도, 결과는 한 번 처리한 것과 같아야 한다
는 성질이다.
조금 더 실무적으로 표현하면 이렇다.
사용자가 같은 의도로 같은 요청을 여러 번 보냈을 때,
시스템은 이를 매번 새로운 요청으로 처리하지 않고
이미 처리된 요청인지 식별해서 중복 실행을 막아야 한다는 뜻이다.
예를 들어 보자.
- 계좌이체 요청을 같은 내용으로 두 번 보냈다.
- 주문 생성 요청이 타임아웃 후 재전송됐다.
- 결제 승인 API가 응답을 못 받아 같은 요청을 다시 호출했다.
- 배치가 실패한 줄 알고 운영자가 같은 작업을 다시 실행했다.
이런 상황에서 멱등성이 없는 시스템은 요청이 들어온 횟수만큼 실제 작업을 반복할 수 있다.
반면 멱등성이 설계된 시스템은 “이건 이미 처리된 요청이다”라고 판단해
중복 생성, 중복 결제, 중복 전송을 막을 수 있다.
멱등성은 단순히 에러를 막는 기술이 아니다.
실무적으로는 데이터 정합성과 금전 사고를 막는 안전장치에 가깝다.
즉, 개발자만 알아야 하는 개념이 아니라
IT기획자나 PM도 반드시 알아야 하는 개념이다.
왜냐하면 멱등성이 필요한 업무와, 멱등성이 없어도 되는 업무를 구분하는 것은
결국 비즈니스와 데이터 흐름을 이해하는 사람의 판단이기 때문이다.
2. 구체적인 사용 예시
멱등성은 특히 돈, 주문, 재고, 외부 연동, 배치 재처리처럼
중복 실행되면 큰 문제가 되는 영역에서 중요하다.
2-1. 결제 요청
가장 대표적인 예다.
고객이 결제 버튼을 여러 번 눌렀거나,
앱이 응답을 받지 못해 같은 결제 요청을 다시 보냈다고 가정해보자.
멱등성이 없으면 서버는 이를 각각 다른 결제로 처리할 수 있다.
그 결과 한 건의 주문에 대해 카드 승인만 여러 번 일어나는 사고가 발생할 수 있다.
이 경우 시스템은 “이 요청은 이미 처리된 결제 요청”이라고 식별할 수 있어야 한다.
2-2. 주문 생성
고객은 주문을 한 번만 했다고 생각하는데,
서버는 중복 요청을 두 건으로 받아서 주문을 두 개 생성할 수 있다.
이런 경우에는
- 주문번호가 중복 생성되거나
- 동일 상품이 두 번 출고되거나
- 후속 정산과 배송 데이터까지 연쇄적으로 꼬일 수 있다.
주문은 한 번만 만들어져야 하는 업무이므로
멱등성이 매우 중요한 대표 사례다.
2-3. 배치 재실행
새벽 배치가 중간에 실패했다.
운영자는 “그냥 다시 돌리면 되겠지”라고 생각할 수 있다.
하지만 멱등성이 없는 구조라면 재실행 시 이미 처리된 데이터까지 다시 처리되어
- 중복 정산
- 중복 알림 발송
- 중복 포인트 지급
- 중복 회계전표 생성
같은 문제가 생길 수 있다.
그래서 배치 재실행은 단순한 운영 액션이 아니라
항상 “이 배치는 다시 돌려도 안전한가?”를 함께 봐야 한다.
2-4. 외부 시스템 연동
예를 들어 주문 완료 후 외부 물류 시스템, ERP, 정산 시스템으로 메시지를 보내는 구조를 생각해보자.
네트워크 불안정이나 타임아웃 때문에 동일 이벤트가 여러 번 전송될 수 있다.
이때 수신 시스템이 멱등성을 고려하지 않으면 동일 주문이 두 번 반영될 수 있다.
즉, 멱등성은 내 시스템 안에서만의 문제가 아니라 시스템 간 연계에서도 매우 중요하다.
3. 사용을 안 했을 때 발생할 리스크
멱등성을 설계하지 않으면 단순 중복 처리 이상의 문제가 생긴다.
특히 IT기획자나 PM 입장에서는 다음 리스크를 정확히 인식해야 한다.
첫째, 금전 사고가 발생할 수 있다
중복 결제, 중복 환불, 중복 포인트 지급, 중복 정산은
단순 장애가 아니라 고객 신뢰와 직접 연결되는 사고다.
특히 결제 영역에서는 “일시적인 오류”로 끝나지 않고
고객 민원, 환불 비용, CS 대응 비용, 브랜드 신뢰 하락으로 이어질 수 있다.
둘째, 데이터 정합성이 무너진다
주문은 한 건인데 결제는 두 건,
주문은 존재하는데 정산 기록은 없음,
출고는 되었는데 ERP 반영은 두 번 됨.
이런 식으로 시스템별 데이터가 서로 다르게 남으면
나중에 어떤 데이터가 진실인지 판단하기 어려워진다.
이 시점부터는 단순 수정이 아니라
운영자 확인, 로그 분석, 수기 보정, 개발자 대응까지 필요해진다.
셋째, 장애 복구가 더 어려워진다
멱등성이 없는 시스템은 장애가 발생했을 때
“다시 실행하면 되는지”조차 확신할 수 없다.
즉, 재처리가 복구 수단이 아니라
오히려 추가 사고의 원인이 될 수 있다.
이건 운영 안정성 관점에서도 매우 큰 리스크다.
넷째, 시스템이 커질수록 문제는 더 커진다
초기에는 한 화면, 한 서버, 한 DB 수준이라 잘 안 보일 수 있다.
하지만 서비스가 커지고 MSA, 외부 연동, 메시지 큐, 배치, 재시도 로직이 많아질수록
중복 요청과 중복 처리 가능성은 훨씬 높아진다.
즉, 멱등성은 “대규모 시스템에서만 필요한 고급 기술”이 아니라
시스템이 커질수록 반드시 요구되는 기본 안전장치라고 보는 게 맞다.
4. 어떤 식으로 구현하면 되는지
이제 중요한 질문이 남는다.
그래서 멱등성은 실제로 어떻게 구현할까?
IT기획자나 PM이 여기서 모든 코드를 알아야 할 필요는 없다.
하지만 어떤 구조로 구현하는지 정도는 이해해야 개발팀과 제대로 대화할 수 있다.
가장 대표적인 방식은 Idempotency Key를 사용하는 구조다.
4-1. 기본 구조
클라이언트가 요청을 보낼 때,
요청마다 고유한 키(Idempotency Key) 를 함께 보낸다.
예를 들면 이런 식이다.
- 주문 생성 요청 1건
- 결제 승인 요청 1건
- 환불 요청 1건
이 요청마다 시스템이 식별할 수 있는 고유 키를 함께 전달한다.
서버는 요청을 받으면 먼저 이 키를 확인한다.
- 처음 들어온 키라면 정상 처리
- 이미 처리된 키라면 중복 요청으로 보고 재처리하지 않음
즉, 핵심은
**“이 요청을 처음 보는가, 이미 처리한 적 있는가”**를 서버가 판단할 수 있게 만드는 것이다.
4-2. 어떤 테이블로 관리할 수 있을까
실무에서는 보통 별도의 저장소나 테이블로 멱등성 키를 관리한다.
예를 들면 다음과 같은 컬럼 구성이 가능하다.
idempotency_key: 요청 고유 키request_hash: 실제 요청 본문이 같은지 비교하기 위한 해시resource_type: payment, order, refund 같은 업무 타입resource_id: 실제 생성/처리된 대상의 IDstatus: PROCESSING, SUCCEEDED, FAILEDresponse_code: 최초 처리 결과 코드response_body: 이미 처리된 경우 재사용할 응답created_at,expired_at: 유효기간 관리용 시간 정보
중요한 포인트는
키만 저장하는 것이 아니라 이 키가 어떤 요청이었고, 어떤 결과를 만들었는지까지 같이 관리해야 한다는 점이다.
4-3. 처리 흐름
실무적으로는 보통 이런 흐름으로 간다.
1단계. 요청이 들어온다
사용자는 결제 요청을 보낸다.
이때 요청 헤더나 바디에 idempotency key가 포함된다.
2단계. 서버가 키를 조회한다
서버는 이 키가 이미 처리된 적 있는지 DB나 Redis 같은 저장소에서 확인한다.
3단계. 처음 들어온 키라면 처리한다
아직 처리 이력이 없다면 실제 비즈니스 로직을 수행한다.
예를 들어 결제 승인, 주문 생성, 포인트 차감 등을 수행한다.
4단계. 처리 결과를 저장한다
이 키로 어떤 요청이 처리되었고, 결과가 무엇이었는지 저장한다.
5단계. 같은 키가 다시 들어오면 중복 처리하지 않는다
이후 동일한 키로 같은 요청이 다시 들어오면
새로 처리하지 않고 기존 결과를 반환하거나 중복 요청으로 차단한다.

4-4. 구현 시 같이 봐야 할 질문
여기서 PM/기획자가 개발팀과 꼭 같이 봐야 할 질문이 있다.
이 키는 누가 만들 것인가?
클라이언트가 만들지, 서버가 만들지 정해야 한다.
외부 API 연동이면 호출 주체와 생성 규칙도 중요하다.
키의 유효기간은 어떻게 할 것인가?
영원히 저장할 수는 없으니 일정 기간 후 만료 정책이 필요하다.
결제처럼 민감한 업무는 더 길게, 단순 요청은 짧게 둘 수 있다.
동일 요청의 기준은 무엇인가?
같은 키면 무조건 같은 요청으로 볼 것인지,
주문번호/회원번호/금액까지 함께 비교할 것인지 정해야 한다.
중복 요청이 오면 어떻게 응답할 것인가?
기존 성공 결과를 그대로 반환할지,
중복 요청이라는 에러를 줄지 정책이 필요하다.
분산 환경에서도 안전한가?
서버가 여러 대인 환경에서는
키 저장소가 중앙에서 일관되게 조회되어야 한다.
4-5. 이것만으로 끝이 아닌 이유
중요한 점은, 멱등성은 키 하나 넣는다고 끝나는 기능이 아니라는 점이다.
실제로는 이런 것들이 함께 고려되어야 한다.
- 중복 요청 식별 방식
- 응답 재사용 정책
- DB 트랜잭션 처리
- 메시지 재전송 대응
- 외부 시스템 중복 수신 대응
- 배치 재실행 정책
- 운영자 확인 및 복구 방법
즉, 멱등성은 코드 한 줄의 문제가 아니라
데이터와 프로세스를 어떻게 안전하게 설계할 것인가의 문제다.
5. 마무리
멱등성은 처음 들으면 기술적인 단어처럼 느껴진다.
하지만 실무에서 보면 이건 단순 기술 개념이 아니라
사고를 막기 위한 업무 설계의 핵심 원칙에 가깝다.
특히 IT기획자나 PM은 멱등성을 이런 관점에서 이해해야 한다.
- 어떤 업무는 반드시 한 번만 처리되어야 하는가
- 같은 요청이 여러 번 들어올 가능성은 없는가
- 재처리와 재시도가 가능한 구조인가
- 돈, 주문, 재고, 정산처럼 중복이 치명적인 영역은 무엇인가
- 장애가 났을 때 운영적으로 복구 가능한가
좋은 시스템은 “장애가 절대 없는 시스템”이 아니라
장애나 중복 요청이 와도 데이터가 쉽게 깨지지 않는 시스템이다.
그리고 그 지점을 만드는 데 멱등성은 아주 중요한 역할을 한다.
앞으로 개발팀이
“이건 멱등성 보장이 필요합니다”
또는
“이 요청은 idempotency key를 써야 합니다”
라고 말할 때,
이제는 단순히 기술 용어로 듣지 말고
왜 이게 비즈니스 사고를 막는 핵심 장치인지 같이 볼 수 있어야 한다.
그게 결국, 기술과 비즈니스를 함께 이해하는 IT기획자와 PM의 시야라고 생각한다.