SPEC-000_통합 구현 기준
SPEC-000_통합 구현 기준
SPEC-000 통합 구현 기준
1. Metadata
- Status: draft
- Date: 2026-03-09
- Owner: YSY
- Source ADRs: ADR-000/010/020/030/040/050/060/070/080/090/100/110/120/130/140/150/160/170/180/190/200/210/220/230/240/250/260/270/280
2. Scope
이 문서는 현재 서비스 구현 기준(정책, UX, API, 데이터, 보안)을 단일 기준으로 정의한다.
3. 핵심 용어 및 상태 고정값
slots.status:issued|closedreservations.status:hold|reserved|redeemed|expired|cancelledverification_method:none|location|qrpayment_method:on_site|prepaid- 시간 판정(만료/한도/제재)은 서버 UTC를 기준으로 처리한다.
4. 사용자/파트너 정책 기준
- 탐색/상세는 비로그인 접근을 허용한다.
- 상태 변경 액션(예약/취소/구독변경 등)에서만 로그인 인터셉트를 적용한다.
- 전화 인증(OTP) 완료 전에는 상태 변경 액션을 허용하지 않는다.
- Hold는 결제 진행 중 임시 점유로만 사용한다.
- Hold 기본 만료 90초, 최대 180초, 결제 재시도 기본 2회를 사용한다.
prepaid결제 성공 시 상태는 우선reserved로 확정한다.verification_method=none이면reserved -> redeemed를 즉시 수행한다. (prepaid/on_site공통)verification_method=location이면 위치 검증 성공 시redeemed로 전이한다.verification_method=qr이면 QR 검증 성공 시redeemed로 전이한다.on_site+location검증은 주기 검증이 아니라 사용/수령 이벤트 시점 검증으로 처리한다.- 위치 검증 실패 시 만료 전까지 QR 폴백을 제공하고, 만료 시
expired로 종료한다. - 취소는
cancel_reason저장을 필수로 한다. - 파트너 상태는
partner_registered|partner_active|partner_suspended모델을 유지한다. - 슬롯 발행 권한은 구독 활성 상태(
partner_active)에서만 허용한다. - 발행 제한은 플랜 한도 정책을 서버에서 강제한다.
- 반복 미이행(
expired/cancelled)은 제재 정책과 연동한다. - 선결제 분쟁은 발행자-사용자 직접 해결을 기본으로 하고 플랫폼은 근거 로그 제공을 담당한다.
expired|cancelled결과 응답은refund=false를 기본 정책 플래그로 포함한다.- 취소 요청은
cancel_reason없이 처리할 수 없다. - 취소 사유 기본값은
user_cancelled|partner_cancelled|system_cancelled로 제한한다. - 만료 판정은
expires_at_utc로 수행하고 사용자 표시는 로컬 시간으로 변환한다. - 구독 플랜 카탈로그와 발행 권한 파라미터(entitlement)는 ADR-270 기준으로 버전 관리한다.
- Add-on은 다중 선택 가능하며
basic에서 3개 이상 선택 시plus전환을 유도한다.pre_paid권한은prepaid_unlock또는 상위 플랜 기본 권한에서만 활성화한다. - 쿠폰 적용 시 유효 권한은 쿠폰 세그먼트가 우선하며, 종료 후 기본 구독 권한으로 자동 복귀한다.
5. UX 기준
UX 관련 단일 SoT는 본 섹션이며, ADR/SCENARIO/RUNBOOK은 아래 Rule ID를 참조만 한다.
5.1 UX Rule Catalog (SoT)
UX-R-001: 진행형 플로우는 상단 단계(hold/결제/검증/완료)를 고정 노출한다.UX-R-002: 단계 화면은 Primary CTA 1개를 중심으로 구성한다.UX-R-003: 실패 화면은 기본 다음 행동 1개만 제시한다.UX-R-004: 결제/예약 확정 직후에는reserved상태와 다음 필수 단계를 먼저 안내한다.UX-R-005:verification_method=none은 즉시 완료 화면으로 연결한다.UX-R-006:location검증은 이벤트 시점으로 처리하며 실패 시 만료 전 QR 폴백을 제공한다.UX-R-007:qr검증 화면은 스캔 안내, 재시도 조건, 종료 조건을 명시한다.UX-R-008: 취소 확인 단계는환불 없음정책과 취소 결과(cancelled)를 확정 전 노출한다.UX-R-009: 취소/만료 결과 화면은final_status, 처리 시각,refund=false, 다음 행동 CTA를 함께 제공한다.UX-R-010: 권한 거부(AUTH_TRANSITION_DENIED) 화면은 차단 사유와 복구 CTA를 함께 제공한다.UX-R-011: 시간 표시는 로컬 기준으로 일관되게 제공하고 판정 기준은 서버 UTC로 설명한다.UX-R-012: 멱등 재요청 시 동일 결과 화면을 재노출한다.UX-R-013: 선결제 분쟁 안내의 기본 경로는 발행자 직접 해결이며 플랫폼은 증적 안내를 보조한다.UX-R-014: 반복 미이행 가능 사용자에게 예약 시도 단계에서 경고/제재 안내를 제공한다.UX-R-015: 최초 실행 라우팅은유지보수 -> 강제업데이트 -> 세션복원 -> 기본 탐색순서를 따른다.UX-R-016: 최초 실행 빈 상태는권한 미허용|오프라인|초기 데이터 없음으로 분기한다.UX-R-017: 앱 기본 진입 화면은 탐색 화면으로 고정한다.UX-R-018: 로그인 인터셉트 후 원래 액션으로 복귀하며 복귀 토큰 만료 시 안전 화면으로 복귀한다.UX-R-019: 탐색/상세의 수량/마감 표시는 동일 규칙으로 노출한다.UX-R-020: 빈 상태는 원인별(반경/필터/권한/오류)로 분기하고 즉시 다음 행동 CTA를 제공한다.UX-R-021: 관심상점/관심업종은 즉시 등록/해제 가능하며 예약 보장이 아님을 명시한다.UX-R-022: 예약 완료 직후 수량/상태 스냅샷을 즉시 반영한다.
6. API 계약 기준
- 상태 변경 API는
idempotency_key를 필수로 받는다. - 권한 밖 전이는 표준 실패 코드로 거부한다.
- 전이 실패 시 부분 반영 없이 원자적으로 롤백한다.
- 성공 응답은 최종 상태 스냅샷을 반환한다.
- 에러 응답은
domain_code와retryable을 포함한다. - 정책 오류와 시스템 오류를 구분해 반환한다.
- 취소/만료 결과 응답은
refund,cancel_reason(해당 시),final_status를 포함한다. - 취소 요청 권한 부족은
AUTH_TRANSITION_DENIED로 반환한다. - 취소 사유 누락은
CANCEL_REASON_REQUIRED로 반환한다. - 시간 관련 응답은
server_time_utc,expires_at_utc를 함께 반환한다.
6.1 상태 전이 명령 표준
| Command | Actor | Preconditions | Result |
|---|---|---|---|
| Hold 생성 | user | 인증 완료, 활성 hold 중복 없음, 수량/한도 충족 | hold 생성 |
| 결제 확정(prepaid) | system/payment | 유효 hold, 결제 성공 | reserved 확정 |
| 예약 확정(on_site) | user/system | 유효 hold, on_site 정책 충족 | reserved 확정 |
| 자동 완료(none) | system | reserved + verification_method=none | redeemed |
| 위치 검증 완료 | partner/system | reserved + verification_method=location | redeemed |
| QR 검증 완료 | partner/system | reserved + verification_method=qr | redeemed |
| 위치 검증 실패 | partner/system | reserved + verification_method=location + 미만료 | fallback=qr 안내 |
| 예약 취소 | user/system | reserved, cancel_reason 존재, 권한 검증 통과 | cancelled, refund=false |
| 결제 실패/타임아웃 | system/payment | 유효 hold | expired 또는 cancelled |
| 만료 처리 | scheduler/system | `hold | reserved` 만료시각 초과 |
| 첫 예약 완료 응답 | system | 상태 확정 성공 | final_status, next_actions, post_action_quantity_snapshot 반환 |
7. 데이터 기준
- 핵심 엔터티는
slots,reservations,reservation_holds,penalties,audit_logs,user_favorite_store,user_interest_category,partner_pg_config로 고정한다. - 가용 수량 SoT:
total_quantity - active_hold - active_reserved. - 가용 수량 하한은
0으로 고정한다. - 동일 사용자+슬롯의 활성 hold 중복 생성은 금지한다.
- 관심상점 유니크 키:
(user_id, store_id). - 관심업종 유니크 키:
(user_id, category_id). - hold-reservation 참조 무결성을 강제한다.
- 불변조건 위반 시 데이터 변경을 중단하고 오류를 반환한다.
- 개인정보/거래/감사 데이터의 보존 정책을 분리 적용한다.
- 삭제 요청은 삭제 배치와 익명화 배치를 분리해 재실행 가능하게 처리한다.
cancelled레코드는cancel_reason,cancelled_at_utc를 필수로 저장한다.expired|cancelled레코드는 환불 정책 플래그(refund=false)를 함께 저장한다.- 시간 표시용 로컬 값은 파생 필드로만 사용하고 판정 필드는 UTC를 사용한다.
8. 보안 및 감사 기준
- 권한 검증은
RLS + RPC이중 경계로 적용한다. - 역할별 상태 전이 허용 목록은 서버에서 강제한다.
- 클라이언트 권한 체크는 UX 보조이며 보안 근거로 사용하지 않는다.
- 시크릿 원문 저장을 금지하고 참조키만 저장한다.
- 핵심 상태 전이/권한 변경/수동 조치/제재는 감사로그에 동일 포맷으로 기록한다.
- 감사로그 최소 필드는
actor,target,action,timestamp,result_code로 고정한다. - 중요 오류 코드는 알람/온콜 기준으로 운영한다.
9. Validation
- 본 문서의 상태/전이/권한 규칙이 ADR-010~260과 충돌하지 않는다.
- API/DB/UX 구현이 본 문서 기준과 일치한다.
- 실패 코드, 감사로그, 보존/삭제 처리 경로가 운영 점검 가능하다.
- 정책 파라미터(Hold TTL, 재시도, 발행 제한)가 서버 설정으로 일원화되어 있다.