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

4 min read
-
#backend#payment#wallet#system-design#database
멱등 · 정합성 · 동시성: 지갑·결제 시스템의 핵심 개념

금융, 지갑, 포인트 시스템에서 꼭 알아야 할 멱등성, 정합성, 동시성 개념을 개발자 관점에서 쉽고 명확하게 설명합니다.

🔐 멱등 · 정합성 · 동시성

지갑·결제 시스템에서 꼭 알아야 할 핵심 개념 정리

금융, 지갑, 포인트처럼 돈이 오가는 시스템에서는 요청이 여러 번 오거나, 동시에 수정되거나, 데이터가 쌓일수록 결과가 안정적이고 정확하게 나오는 구조가 필수이다.

이 글에서는 그 핵심 개념인 멱등(Idempotency), 정합성(Consistency), **동시성(Concurrency)**을 개발자 관점에서 쉽고 명확하게 설명한다.


1. 🔁 멱등(Idempotency)

멱등성 개념 다이어그램

"같은 요청을 여러 번 보내도 결과는 단 한 번만 발생해야 한다."

예를 들어 유저가 결제 버튼을 눌렀을 때:

  • 네트워크가 끊겼거나
  • 앱이 멈춰서
  • 요청이 두 번 전송되더라도

결제는 절대로 두 번 일어나면 안 된다.

✔ 왜 중요한가?

  • 모바일 환경에서 동일 요청이 중복 전송되기 쉽기 때문
  • Payment provider 웹훅이 재전송될 수 있음
  • 네트워크 재시도 로직이 포함될 수 있음

✔ 실전 구현 방식

요청마다 Idempotency-Key(고유값)을 부여한다.

Idempotency-Key: abc123

서버는 다음처럼 처리한다:

  1. 이 키로 처리된 기록(biz_tx.idempotency_key)이 있는지 확인
  2. 이미 있으면 → 이전 처리 결과 그대로 반환
  3. 없으면 → 새로 처리하고 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 기록이 없음
  • 장부 복원할 수 없으면 "돈이 사라진" 상황처럼 보이게 됨

금융·지갑 서비스에서 정합성 오류는 치명적이다.

✔ 어떻게 유지할까?

정기적인 헬스 체크 스크립트/배치가 필요하다.

예:

  1. wallet의 balance를 가져온다
  2. ledger를 순차적으로 누적해 최종 잔액을 계산한다
  3. wallet 값과 ledger 최종값을 비교한다
  4. 차이가 있으면 알람/슬랙/이메일 발송

이런 스크립트를 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 조건부 업데이트

🚀 마무리

멱등 · 정합성 · 동시성은 지갑·결제·포인트 시스템을 설계할 때 절대 빠질 수 없는 핵심 기둥이다.

  • 멱등 → 중복 요청 방지
  • 정합성 → 데이터 정확성 보장
  • 동시성 → 동시에 업데이트해도 안전

이 세 가지를 제대로 갖춘 시스템은 오류가 발생해도 복구가 가능하고, 고객 신뢰를 유지하며, 확장성과 안정성까지 챙길 수 있다.

관련 추천글

댓글

댓글을 불러오는 중...