Sprint 6 - 사용 처리_Redeemed_ 최소 구현 _ 내 기록_History_

Sprint 6 - 사용 처리_Redeemed_ 최소 구현 _ 내 기록_History_

목표
결제/정산/매장 앱이 없어도, 상태 흐름(issued→reserved→redeemed/expired)을 운영 가능한 형태로 닫는다.
Sprint 6에서는 “redeemed의 완전한 진실”보다 “기록/운영 가능성”이 우선이다.

원칙

  • redeemed는 사용자 앱에서 임의로 누르지 않는다(부정 사용 위험).

  • MVP에서도 redeemed를 최종 확정 상태로 운영하며, 데이터 모델과 화면은 동일하게 유지한다.


S6-1 내 기록(History) 화면 데이터 모델 확정

목적
사용자 관점에서 “내가 확보한 것들이 어디로 갔는지”가 보이게 한다.

작업

  • HistoryItem 타입 정의

    • reservationId

    • slotSummary(시간/혜택/매장)

    • status(reserved/redeemed/expired/cancelled)

    • reservedAt, expiresAt, redeemedAt

  • 조회 API 계약

    • listMyReservations(limit, cursor?, statusFilter?)

완료 조건

  • HistoryScreen이 이 타입만 의존

  • 상태별로 표시가 안정적으로 분기됨


S6-2 HistoryScreen UI 구현(상태별 섹션 또는 필터)

목적
탐색을 길게 하지 않고, “현재 의미 있는 것”을 먼저 보여준다.

권장 구성(초기)

  • 상단: 진행 중(Reserved/Arrived)

  • 하단: 지난 기록(Expired/Redeemed)

작업

  • 상태별 배지/문구(절제)

  • 항목 클릭 시 SlotDetail 또는 ReservationDetail로 이동(선택)

  • 빈 상태 처리(기록 없음)

완료 조건

  • reserved가 항상 상단에 보임

  • expired/redeemed는 기록으로만 존재


S6-3 예약 상세(ReservationDetail) 최소 화면(선택)

목적
지원/운영 대응을 위해 “단일 예약”을 자세히 볼 수 있게 한다.

작업

  • reservationId 표시(짧은 형태)

  • 상태 타임라인(Reserved → Arrived → Redeemed/Expired)

  • 만료/도착 시각 표시

  • 문제 발생 시 “지원용 정보 복사” 버튼(선택)

완료 조건

  • 예약 하나를 열었을 때 상태와 시각이 확인 가능

S6-4 redeemed 전환 방식 결정(MVP 안전버전)

목적
부정 사용을 막으면서도 운영 가능성을 확보한다.

MVP 안전 선택지
A안: “매장 확인 코드(Staff PIN)” 입력으로 redeemed

  • 가맹점마다 PIN 1개 발급(관리자 페이지에서 설정)

  • 사용자가 결제 시 직원에게 보여주고 직원이 PIN을 입력(사용자 앱에서 입력)

  • PIN은 주기적 변경 가능(Phase 2)

B안: redeemed는 MVP에서 미구현(Arrived까지만)

  • 다만 DB/화면은 redeemed 상태를 표시 가능하게 준비

권장

  • 초기에는 B안으로 시작해도 된다(운영은 reserved/expired 흐름만으로도 충분히 검증 가능)

  • 단, “사용 완료”의 개념이 필요하면 A안이 가장 단순

이 스프린트에서는 우선 A/B 중 하나를 선택해 구현한다.
(이미 티켓화는 둘 다 포함하되, 실제 구현은 한 쪽만 진행)


S6-5 (A안 선택 시) redeemed API 계약 및 구현

목적
redeemed 전환도 서버에서 검증한다.

작업

  • 입력

    • reservationId

    • merchantPin

  • 검증

    • reservation.status == reserved

    • merchantPin 일치

    • 이미 redeemed면 idempotent 처리

  • 출력

    • updatedReservation(status=redeemed, redeemedAt)

완료 조건

  • reserved 상태에서만 redeemed 가능

  • PIN 틀리면 명확한 실패 reason 반환

  • 중복 호출에도 상태가 깨지지 않음


S6-6 (A안 선택 시) Arrived 화면에 “사용 확인” 진입 추가

목적
사용자에게 “이제 끝내는 단계”가 있음을 제공하되, 소비 유도 형태가 되지 않게 한다.

작업

  • Arrived 상태 화면에 작은 버튼:

    • “사용 확인(직원 요청 시)”
  • PIN 입력 UI(단순)

  • 성공 시 redeemed 완료 안내 + History로 이동

완료 조건

  • 사용 확인 흐름이 reserved 상태에서만 보임

  • 실패 시 재시도는 가능하되 과도한 안내/강조 없음


S6-7 (B안 선택 시) redeemed 미구현 플래그 및 UI 처리

목적
redeemed가 없어도 UX가 애매해지지 않게 한다.

작업

  • Arrived 상태 화면에:

    • “계산 시 이 화면을 보여주세요(임시)” 같은 최소 안내
  • 서버에서 redeemed 상태가 생기면 History에서 표시만 가능하도록 준비

완료 조건

  • redeemed가 없어도 사용자는 무엇을 하면 되는지 이해 가능

  • 앱이 “완료 버튼”을 강요하지 않음


S6-8 이벤트 로깅(히스토리/사용)

목적
운영 데이터가 이어지게 한다.

로그 이벤트(최소)

  • history_view

  • reservation_detail_view

  • redeem_attempt (A안일 때)

  • redeem_success / redeem_fail(reason)

완료 조건

  • 히스토리 조회가 로그로 남음

  • redeemed가 있으면 성공/실패가 남음


Sprint 6 완료 정의

다음이 가능해야 한다.

  • 사용자는 내 예약 기록(reserved/redeemed/expired/cancelled)을 확인 가능

  • 진행 중 예약이 상단에 보이며, 상태 흐름이 이해 가능

  • redeemed는

    • 안전한 방식으로 최소 구현(A안) 또는

    • MVP에선 제외(B안)하되 구조적으로 열어둠