001. Domain Specification Document

001. Domain Specification Document

# LEGACY NOTICE

  • ??: Superseded
  • Superseded By: ADR-DS-010, ADR-DS-012, ADR-DS-064, ADR-DS-060~065
  • ??: ? ?? ?? ?? ?? ?? ??, ?? ?? ?? ADR ?? ????.

0. 문서 목적

이 문서는 다음을 명확히 정의한다:

  • 핵심 도메인 객체

  • 상태 정의

  • 상태 전이 규칙

  • 계산 규칙

  • 예외 처리 규칙

  • 동시성 원칙

이 문서는 기능 설명 문서가 아니다.
이 문서는 시스템의 행동을 고정하는 문서다.


1. 핵심 도메인 객체

1.1 User

속성

  • userId

  • createdAt

  • status (active | limited | suspended)

  • penaltyLevel

  • activeReservationId (nullable)

제약

  • 동시에 activeReservation은 1개만 허용

1.2 Merchant

속성

  • merchantId

  • subscriptionPlan

  • subscriptionStatus (active | past_due | canceled)

  • createdAt


1.3 Slot

슬롯은 “시간 기회”다.
상품이 아니다.

속성

  • slotId

  • merchantId

  • startAt

  • endAt

  • totalQuantity

  • remainingQuantity

  • benefitText

  • createdAt

  • status (issued | closed)

상태 설명

issued
→ 사용 가능 상태

closed
→ 시간 종료 또는 수동 종료


1.4 Reservation

속성

  • reservationId

  • slotId

  • userId

  • status

    • reserved

    • redeemed

    • expired

    • cancelled

  • reservedAt

  • expiresAt

  • redeemedAt (nullable)


1.5 Penalty

속성

  • userId

  • level (0,1,2,3)

  • activeUntil

  • reserveExpiresMinutesOverride (nullable)


2. 상태 정의


2.1 Slot 상태

상태의미
issued시간 범위 내, 발행 상태
closed시간 종료 또는 수량 소진

2.2 Reservation 상태

상태의미
reserved15분 임시 확보
redeemed사용 완료
expired유효시간 초과 자동 해제
cancelled사용자/정책 취소

3. 상태 전이 규칙


3.1 Reservation 전이

issued (slot) → reserved
reserved → redeemed
reserved → expired
reserved → cancelled

금지 전이:

  • expired → any

  • expired → redeemed

  • redeemed → any

  • cancelled → any


3.2 만료 규칙

조건:

if now > expiresAt AND status == reserved
→ expired

만료는 서버 기준 시간으로 처리한다.


4. 수량 차감 규칙

수량 차감은 다음 조건에서만 수행한다:

if reservation.status transitions to redeemed
AND slot.remainingQuantity > 0
→ remainingQuantity -= 1

reserved 상태에서는 수량 차감 금지

동시성 규칙:

  • 트랜잭션 내에서 remainingQuantity > 0 확인

  • 차감과 상태 변경을 원자적으로 수행


5. 발행 제한 계산 규칙


5.1 “월 20회” 정의

슬롯 1개 생성 = 1회

수량 10개여도 1회


5.2 동일 조건 재발행 정의

다음이 모두 동일하면 동일 조건으로 간주:

  • merchantId 동일

  • startAt 동일 시간대 범위

  • benefitText 동일

  • 업종 동일

재발행 최소 간격:

Basic: 4시간
Pro: 2시간
Premium: 1시간


6. 확보 규칙


6.1 activeReservation 제한

if user.activeReservation exists AND status == reserved
→ 신규 reserved 생성 불가


6.2 제재 적용

if penalty.activeUntil > now
→ reserved 생성 불가

if penalty.reserveExpiresMinutesOverride exists
→ expiresAt = reservedAt + overrideMinutes


7. 사용 확정 규칙

조건:

  • reservation.status == reserved

  • now <= expiresAt

  • distance(userLocation, merchantLocation) <= USAGE_VERIFY_RADIUS

  • locationAccuracy <= MAX_ALLOWED_ACCURACY

성공 시:

  • reservation.status → redeemed

  • slot.remainingQuantity -= 1


8. 동시성 원칙

  • 모든 상태 변경은 서버에서 수행

  • 수량 차감은 트랜잭션

  • 클라이언트는 상태를 “제안”할 수 있으나 “확정”하지 못한다


9. 예외 처리 원칙

  • 만료 직전 사용 확정 시 서버 기준 우선

  • 네트워크 실패 시 상태 재조회

  • 중복 요청은 idempotent 처리


10. 구조적 불변 조건 (Invariants)

다음은 항상 참이어야 한다:

  1. remainingQuantity ≥ 0

  2. 하나의 reservation은 동시에 두 상태를 가질 수 없다

  3. redeemed 수 ≤ totalQuantity

  4. redeemed 이후에는 expired가 발생할 수 없다

  5. user.activeReservation은 1개 이하


이 문서는 1차 버전이다.

다음 단계는 이 문서를 더 단단하게 만드는 것이다:

  • 상태 전이 표를 수학적으로 더 엄격히 만들기

  • 시간 경계 조건(동일 초 단위 등) 정의

  • 테스트 케이스 목록으로 변환


이제 묻겠다.

이 수준에서 더 깊이 파고들까?
아니면 발행 제한 수학부터 더 정밀하게 정의할까?