멱등 · 정합성 · 동시성: 지갑·결제 시스템의 핵심 개념

금융, 지갑, 포인트 시스템에서 꼭 알아야 할 멱등성, 정합성, 동시성 개념을 개발자 관점에서 쉽고 명확하게 설명합니다.
🔐 멱등 · 정합성 · 동시성
지갑·결제 시스템에서 꼭 알아야 할 핵심 개념 정리
금융, 지갑, 포인트처럼 돈이 오가는 시스템에서는 요청이 여러 번 오거나, 동시에 수정되거나, 데이터가 쌓일수록 결과가 안정적이고 정확하게 나오는 구조가 필수이다.
이 글에서는 그 핵심 개념인 멱등(Idempotency), 정합성(Consistency), **동시성(Concurrency)**을 개발자 관점에서 쉽고 명확하게 설명한다.
1. 🔁 멱등(Idempotency)

"같은 요청을 여러 번 보내도 결과는 단 한 번만 발생해야 한다."
예를 들어 유저가 결제 버튼을 눌렀을 때:
- 네트워크가 끊겼거나
- 앱이 멈춰서
- 요청이 두 번 전송되더라도
결제는 절대로 두 번 일어나면 안 된다.
✔ 왜 중요한가?
- 모바일 환경에서 동일 요청이 중복 전송되기 쉽기 때문
- Payment provider 웹훅이 재전송될 수 있음
- 네트워크 재시도 로직이 포함될 수 있음
✔ 실전 구현 방식
요청마다 Idempotency-Key(고유값)을 부여한다.
Idempotency-Key: abc123
서버는 다음처럼 처리한다:
- 이 키로 처리된 기록(
biz_tx.idempotency_key)이 있는지 확인 - 이미 있으면 → 이전 처리 결과 그대로 반환
- 없으면 → 새로 처리하고 DB에 기록
DB에서는 다음처럼 UNIQUE 제약을 건다:
ALTER TABLE biz_tx ADD UNIQUE (idempotency_key);
📌 핵심 정리
- 멱등은 "같은 요청은 한 번만" 처리하는 안전장치
- 중복 결제·중복 적립을 막는 가장 확실한 방법
2. 📊 정합성(Consistency)

"모든 장부와 잔액 데이터가 항상 정확하게 서로 일치해야 한다."
지갑 시스템에는 보통 데이터가 다음처럼 여러 곳에 존재한다.
| 용도 | 설명 |
|---|---|
biz_tx |
거래 내역(누적) |
biz_ledger.balance_after |
각 거래 후 잔액 |
biz_wallet.balance |
현재 지갑 잔액 |
✔ 왜 중요한가?
천천히 쌓이는 시스템이라도, 언젠가는 데이터가 틀어지는 순간이 온다.
예시:
- ledger 기록은 있는데 wallet 잔액이 오르지 않음
- wallet 잔액은 증가했는데 ledger 기록이 없음
- 장부 복원할 수 없으면 "돈이 사라진" 상황처럼 보이게 됨
금융·지갑 서비스에서 정합성 오류는 치명적이다.
✔ 어떻게 유지할까?
정기적인 헬스 체크 스크립트/배치가 필요하다.
예:
- wallet의
balance를 가져온다 - ledger를 순차적으로 누적해 최종 잔액을 계산한다
- wallet 값과 ledger 최종값을 비교한다
- 차이가 있으면 알람/슬랙/이메일 발송
이런 스크립트를 1분~5분 주기로 실행해 데이터 틀어짐을 조기 발견하는 것이 핵심이다.
📌 핵심 정리
- 정합성 = 실제 돈과 장부 기록이 하나도 틀리지 않는 상태
- 계속해서 점검하고 유지하는 작업이 필수
3. 🧵 동시성(Concurrency)

"여러 요청이 동시에 같은 지갑 잔액을 변경할 때 꼬이지 않도록 막는 것."
예시 상황:
- 요청 A: +100원
- 요청 B: -50원
두 요청이 거의 동시에 들어오면 둘 다 같은 "현재 잔액"을 읽고 각각 계산을 해버릴 수 있다.
결과적으로:
- A는 1000 → 1100으로 저장
- B는 1000 → 950으로 저장
마지막으로 저장한 요청이 나머지를 덮어써서 잔액이 완전히 꼬인다.
✔ 해결 방법: 조건부 업데이트(Optimistic Lock, Versioning)
지갑 테이블에 version 칼럼을 둔다:
wallet_id | balance | version
업데이트할 때는 다음처럼 한다:
UPDATE biz_wallet
SET balance = ?, version = version + 1
WHERE wallet_id = ? AND version = ?
- 현재
version이 일치하면 업데이트 성공 (1 row) - 누군가 먼저 업데이트했다면
version이 달라져서 실패 (0 row)
0 row면?
- 재시도 또는 실패 처리한다
이렇게 하면 동시 요청이 와도 서로 덮어쓰는 문제를 원천적으로 방지한다.
📌 핵심 정리
- 동시성 문제는 유저 수가 늘수록 반드시 발생
version기반 조건부 업데이트가 가장 일반적이고 안전한 해결책
🎯 한 눈에 보기: 개념 요약
| 개념 | 뜻 | 쉽게 말하면 | 구현 포인트 |
|---|---|---|---|
| 멱등 | 동일 요청 여러 번 와도 1번만 처리 | "버튼 두 번 눌러도 결제는 한 번만" | Idempotency-Key UNIQUE |
| 정합성 | 모든 장부/잔액이 정확히 일치 | "가계부·통장·앱 값이 다 같아야" | ledger vs wallet 주기적 검증 |
| 동시성 | 동시에 수정할 때 값 안 꼬이게 | "둘이 동시에 돈 만지면 충돌" | version 조건부 업데이트 |
🚀 마무리
멱등 · 정합성 · 동시성은 지갑·결제·포인트 시스템을 설계할 때 절대 빠질 수 없는 핵심 기둥이다.
- 멱등 → 중복 요청 방지
- 정합성 → 데이터 정확성 보장
- 동시성 → 동시에 업데이트해도 안전
이 세 가지를 제대로 갖춘 시스템은 오류가 발생해도 복구가 가능하고, 고객 신뢰를 유지하며, 확장성과 안정성까지 챙길 수 있다.
관련 추천글
댓글
댓글을 불러오는 중...
