슬롯 수량 및 동시성 SoT 통합
ADR-020 슬롯 수량 및 동시성 SoT 통합
1. Metadata
- ADR ID: ADR-020
- Status: draft
- Date: 2026-03-09
- Owner: YSY
2. Domain Decision
슬롯 가용 수량 계산의 SoT를 서버로 고정한다.
- 가용 수량 계산:
total_quantity - active_hold - active_reserved active_hold:reservation_holds.status='active' and expires_at > now()active_reserved:reservations.status='reserved' and (expires_at is null or expires_at > now())- 가용 수량은 0 미만으로 내려가지 않도록
greatest(..., 0)적용 - 앱은 계산 결과를 표시만 하고 자체 계산으로 확정하지 않는다.
3. Product Decision
- 해당 없음
4. UX Decision
- 가용 수량/마감 상태를 탐색과 상세에서 동일하게 표기한다.
- Hold로 인한 일시 품절 가능성을 문구로 안내한다.
- 사용자 예약 가능 여부를 버튼 상태로 명확히 표시한다.
- 첫 예약 완료 직후 상세/탐색 수량을 서버 스냅샷 기준으로 즉시 갱신한다.
5. Tech Decision
- 수량 계산 SoT는 DB 함수/쿼리로 고정한다.
- 경합 구간은 트랜잭션/락 전략으로 보호한다.
- 클라이언트 계산값은 최종 판단에 사용하지 않는다.
6. Ops Decision
- 해당 없음
7. Implementation Contract (Optional)
7.1 API Contract
- 수량 조회 응답은
available_quantity,active_hold_count,active_reserved_count,snapshot_at_utc를 포함한다. - 상태 변경 전 서버 재계산 결과를 기준으로 최종 허용 여부를 판정한다.
- 상태 변경 성공 응답은
post_action_quantity_snapshot을 포함해 UI 즉시 동기화를 지원한다.
7.2 Data Contract
- 가용 수량은
total_quantity - active_hold - active_reserved공식으로만 계산한다. - 계산 기준 시각은 서버 UTC
now()로 고정한다.
7.3 Error/Observability Contract
- 수량 판정 실패는
CAPACITY_CALCULATION_FAILED코드로 반환한다. - 경합으로 인한 거부는
CAPACITY_CONFLICT코드로 분리 기록한다.
7.4 Test/Acceptance Contract
- 동시 요청 경합에서도 가용 수량은 음수가 되지 않아야 한다.
- 동일 슬롯의 탐색/상세 가용 표시가 일치해야 한다.
- 첫 예약 완료 후 1회 새로고침 내에 수량 스냅샷이 반영되어야 한다.
8. Validation
- Domain/Product/UX/Tech/Ops 결정이 충돌하지 않는다.
- 구현 기준은 SPEC과 정합성을 유지한다.
- 운영 절차는 RUNBOOK으로 연결된다.