ADR-DS-064_슬롯 수량 관리 및 동시성 제어 정책

ADR-DS-064_슬롯 수량 관리 및 동시성 제어 정책

1. 기본 정보

Conforms to: ADR-DS-000 v1 Effective from: ADR-DS-060+ If conflict: ADR-DS-000 wins. Deprecated terms in this scope: arrived, checkin/check_in.

  • ADR ID: ADR-DS-064
  • 제목: 슬롯 수량 관리 및 동시성 제어 정책
  • 상태: Accepted
  • 작성일: 2026-03-07
  • 작성자: YSY

관련 ADR

  • ADR-DS-060 : 선결제 기능 도입
  • ADR-DS-061 : 결제 중 슬롯 임시 확보 정책
  • ADR-DS-062 : PG 리다이렉트 결제 확인 정책
  • ADR-DS-063 : 선결제 픽업 슬롯 운영 정책

2. 배경 (Context)

플랫폼의 핵심 리소스는 슬롯(slot) 이다.

슬롯은 다음 특성을 가진다.

시간 기반
수량 제한
선착순 확보

18:00 ~ 18:15
수량 3

사용자는 동시에 슬롯을 확보하려 할 수 있다.

사용자 A
사용자 B
사용자 C

이때 다음 문제가 발생할 수 있다.

문제 1 — 중복 판매

슬롯 수량 = 1

동시에 두 요청이 들어올 경우

A reserved
B reserved

가 발생할 수 있다.


문제 2 — 결제 중 수량 불일치

결제 중 슬롯을 잠그지 않으면

슬롯 수량 초과 판매

문제가 발생한다.


문제 3 — 만료 복구 오류

예약 만료와 결제 실패가 동시에 발생할 경우

remaining 수량 오류

가 발생할 수 있다.


따라서 슬롯 수량을 안전하게 관리하는 동시성 제어 정책이 필요하다.


3. 결정 (Decision)

플랫폼은 예약 상태 기반 수량 관리 모델을 채택한다.

슬롯의 남은 수량은 remaining 컬럼을 직접 신뢰하지 않고 예약 상태를 기준으로 계산한다.


4. 슬롯 수량 정의

슬롯은 다음 속성을 가진다.

slot.quantity

quantity = 5

이는 최대 판매 가능 수량이다.


5. 활성 예약 정의

슬롯 수량 계산에서 **활성 예약(active reservation)**은 다음 상태를 의미한다.

reserved
paid
redeemed
no_show

이 상태는 슬롯을 점유한다.


6. 실제 남은 수량 계산

슬롯의 실제 남은 수량은 다음 방식으로 계산한다.

remaining =
slot.quantity
- capacity_consuming_count

capacity_consuming_count

status IN (reserved, paid, redeemed, no_show)

expired, payment_failed 상태는 수량 점유에서 제외한다.


7. 슬롯 확보 정책

사용자가 슬롯 확보 요청을 하면 다음 과정이 수행된다.

1 슬롯 조회
2 활성 예약 수 계산
3 수량 확인
4 reservation 생성
5 상태 reserved

이 과정은 트랜잭션으로 처리한다.


8. 결제 중 슬롯 잠금

선결제 슬롯에서는 결제 시작 시 슬롯이 잠긴다.

상태 전이

issued → reserved

reserved 상태는 슬롯 수량을 차감한 것으로 간주한다.


9. 예약 만료 정책

reserved 상태는 일정 시간이 지나면 자동 만료된다.

reserved TTL = 3분

만료 처리

reserved → expired

이 경우 슬롯 수량은 자동으로 복구된다.


10. 결제 성공 처리

결제 성공 시 상태 전이는 다음과 같다.

reserved → paid

paid 상태는 슬롯 확정 상태이다.


11. 결제 실패 처리

결제 실패 시

reserved → payment_failed

슬롯 수량은 자동으로 복구된다.


12. 최종 사용 처리

사용자가 매장에서 QR 인증을 하면

paid → redeemed

redeemed 상태는 슬롯 수량 점유를 유지한다.


13. 동시성 제어 정책

슬롯 확보 요청은 다음 조건을 만족해야 한다.

slot.quantity > capacity_consuming_count

이 조건을 만족하는 요청만 reservation 생성이 가능하다.

모든 예약 생성은 DB 트랜잭션으로 처리한다.


14. 결과 (Consequences)

긍정적 영향

  • 중복 판매 방지
  • 동시 결제 충돌 방지
  • 슬롯 수량 안정성 확보
  • 예약 시스템 확장성 확보

제한 사항

  • 예약 상태 계산 로직 필요
  • 만료 처리 배치 작업 필요
  • DB 트랜잭션 관리 필요

15. 구조적 의미

본 정책은 플랫폼의 핵심 리소스인 시간 슬롯의 무결성을 보장하기 위한 구조이다.

슬롯 시스템은 다음 원칙을 따른다.

슬롯은 제한된 자원이다
슬롯 수량은 정확해야 한다
동시 요청은 항상 발생한다

따라서 플랫폼은

예약 상태 기반 수량 관리 모델을 채택한다.

이 정책은 향후 다음 기능에도 동일하게 적용된다.

예약 서비스
클래스 예약
시간 기반 서비스


Template v2 Addendum

In Scope

  • Prepaid slot operations (reservation, payment confirmation, pickup, quantity, PG connection)

Out of Scope

  • Order brokering, settlement handling, refund amount calculation

Boundaries

  • Payment responsibility is on publisher. Time/state management is on platform.

Source of Truth (SoT)

  • Base: ADR-DS-060; Temporary hold: ADR-DS-061; Payment verification/reconcile: ADR-DS-062; Pickup ops: ADR-DS-063; Quantity/concurrency: ADR-DS-064; PG registration/secret handling: ADR-DS-065.

Validation

  • Detect state/constraint violations via tests and batch checks.
  • Recovery and reprocessing must be idempotent.

Revisit Conditions

  • KPI threshold breach (reservation failure, expiry ratio, payment confirmation failure)
  • External dependency change (PG, regulation, location API)

DS-000 v1 정합성 개정 (2026-03-08)

이 문서는 ADR-DS-000 v1에 정합되도록 다음 규칙을 우선 적용한다.

  1. Reservation 상태 집합은 reserved | redeemed | expired | cancelled만 사용한다.
  2. paid, payment_failed, no_show는 Reservation 상태로 사용하지 않는다.
  3. 결제 중 임시 점유는 Reservation 상태가 아니라 hold 도메인으로 분리한다.
  4. 수량 차감은 reserved -> redeemed 전이 트랜잭션에서만 수행한다.
  5. prepaid + verification_method=none은 결제 성공 시 즉시 redeemed 전이를 허용할 수 있다.
  6. prepaid + (location|qr)는 결제 성공 후 검증 성공 시 redeemed로 전이한다.
  7. 만료 시각은 운영 상한을 강제한다: expires_at <= store_close_at.

본 섹션과 기존 본문이 충돌하면 본 섹션(DS-000 정합성 개정)이 우선한다.