Sprint 5 - 체크인 확정 _ 수량 차감

Sprint 5 - 체크인 확정 _ 수량 차감

목표
reserved는 임시 상태이며, 사용 확정은 redeemed에서만 성립한다.
수량 차감은 redeemed 전환 시점에만 발생해야 한다.
Sprint 5가 끝나면 MVP의 “신뢰 구조(사용 확정 기반)”가 완성된다.


S5-1 체크인 방식 A(위치 기반) 정책 고정

목적
초기 MVP에서 가장 단순하고 확장 가능한 체크인 기준을 확정한다.

정책(초기 권장)

  • 체크인 가능 반경: 80m (도시 환경 고려, 후에 조정)

  • 위치 정확도(accuracy)가 너무 나쁘면 체크인 불가(예: accuracy > 50m)

  • 체크인 가능 여부는 서버에서도 재확인(클라 단독 판단 금지)

작업

  • 상수 정의: CHECKIN_RADIUS_METERS, MAX_LOCATION_ACCURACY_METERS

  • 체크인 안내 문구 확정(차분하게)

완료 조건

  • 정책이 코드와 문서에 동시에 고정됨

  • 체크인 조건을 만족하지 않으면 UI에서 명확히 안내됨


S5-2 CheckinScreen(또는 ReservedScreen 내 체크인 섹션) UI 구현

목적
사용자가 “지금 해야 할 일”이 체크인임을 명확히 이해한다.

작업

  • UI 요소

    • “도착 확인” 버튼

    • 현재 거리/정확도 표시(최소)

    • 체크인 가능/불가 상태 메시지

  • 체크인 버튼 연타 방지 및 로딩 처리

완료 조건

  • 조건 충족 시 버튼 활성화

  • 조건 미충족 시 버튼 비활성화 + 이유 표시


S5-3 체크인 API 계약 확정 및 구현

목적
redeemed 전환과 수량 차감을 서버에서 원자적으로 처리한다.

API 입력(예시)

  • reservationId

  • userLocation(lat,lng,accuracy,timestamp)

API 출력

  • updatedReservation(status=redeemed, redeemedAt)

  • updatedSlot(remainingQty)

  • 실패 reason

실패 케이스(최소)

  • reservation_expired

  • reservation_not_found

  • not_within_radius

  • location_accuracy_too_low

  • slot_sold_out (동시성)

  • already_redeemed

  • user_penalized (예외 케이스)

완료 조건

  • 사용 확정 성공 시 reservation.status=redeemed로 변경

  • 동시에 slot.remainingQty가 감소

  • 실패 사유가 일관된 코드로 내려옴


S5-4 서버 측 원자성 확보(트랜잭션) 설계

목적
동시 체크인, 수량 경쟁에서 사고를 막는다.

작업(선택 가능한 구현 경로)

  • Postgres 함수(RPC)로 처리

    • 조건 검증(만료/반경/정확도)

    • remainingQty > 0 확인

    • reservation 업데이트 + slot 수량 차감 트랜잭션

  • RLS 정책과 RPC 실행 권한 정리

완료 조건

  • 동시에 여러 사용자가 체크인해도 remainingQty가 음수가 되지 않음

  • redeemed가 된 reservation은 재차감되지 않음(idempotent)


S5-5 체크인 성공 UX: Arrived 상태 화면 전환

목적
사용자는 “확정됐다”는 것을 즉시 이해해야 한다.

작업

  • 체크인 성공 시 상태 표시

    • “도착 확인 완료”

    • 사용 방법 안내(예: 계산 시 화면 제시 등, 아직 QR/리딤은 후순위)

  • 홈/히스토리로 이동 버튼 제공

  • store.activeReservation 업데이트(status=redeemed)

완료 조건

  • redeemed 상태가 앱 재시작/복귀 후에도 서버 기준으로 유지

  • 사용자에게 다음 행동이 안내됨


S5-6 체크인 실패 UX: 이유별 처리

목적
실패가 “버그처럼” 보이지 않게 한다.

작업

  • not_within_radius: “매장 근처에서 다시 시도”

  • accuracy_too_low: “위치 정확도가 낮아 확인이 어렵습니다. 잠시 후 재시도”

  • reservation_expired: 만료 UX로 전환(Sprint 4 흐름 재사용)

  • slot_sold_out: “마감됨” 안내 + 홈 복귀

완료 조건

  • 실패 사유에 따라 UI가 적절히 분기

  • 재시도 가능/불가가 명확히 구분됨


S5-7 위치 갱신/재시도 정책(체크인 순간)

목적
체크인 순간의 위치는 “가장 최근”이어야 한다.

작업

  • 체크인 버튼 탭 시:

    • 최신 위치 1회 갱신 시도

    • 갱신 실패 시 기존 위치로 시도 여부 정책 결정(권장: 실패 시 안내 후 재시도)

  • 연속 재시도 쿨다운(예: 3초)

완료 조건

  • 체크인 시도 시 최신 위치가 반영됨

  • 위치 갱신 폭주가 발생하지 않음


S5-8 이벤트 로깅(체크인/수량 차감)

목적
도착률, 실패 원인, 반경/정확도 정책 조정 근거 확보.

로그 이벤트(최소)

  • checkin_attempt (distance, accuracy 포함)

  • checkin_success

  • checkin_fail (reason)

  • slot_qty_decremented (before/after)

완료 조건

  • 성공/실패가 모두 로그로 남음

  • 실패 reason 분포를 나중에 집계 가능


Sprint 5 완료 정의

다음이 가능해야 한다.

  • reserved 상태에서 위치 기반 체크인 시도 가능

  • 조건 충족 시 redeemed로 전환되고 수량이 차감됨(서버 트랜잭션)

  • 실패 사유가 명확히 안내되고, 만료/마감 등 흐름이 자연스럽게 이어짐

  • redeemed 상태가 앱/서버 모두에서 일관됨