Sprint 4 - 15분 타이머 _ 만료 처리 _ 동기화

Sprint 4 - 15분 타이머 _ 만료 처리 _ 동기화

목표
보증금 대신 “시간 설계”가 제대로 작동하는 것을 사용자에게 체감시키고, 운영 관점에서 사고(점유, 꼬임)를 막는다.
타이머는 클라이언트 기준이 아니라 서버 시간(expiresAt)을 기준으로 동작해야 한다.


S4-1 ReservedScreen 타이머 UI 확정

목적
사용자가 지금 해야 할 행동(도착/체크인)을 빠르게 이해한다.

작업

  • 표시 요소

    • 남은 시간(분:초)

    • “15분 내 도착 체크인 필요” 안내

    • 슬롯 요약(시간/혜택/매장/거리 최소)

  • 상태별 메시지

    • 남은 시간 충분

    • 5분 이하 임박(절제된 강조)

    • 만료됨(자동 해제 안내)

완료 조건

  • reservation만 있으면 UI가 즉시 렌더됨

  • 과장된 색/애니메이션 없이도 임박을 인지 가능


S4-2 서버 기준 남은 시간 계산 유틸 구현

목적
앱을 껐다 켜도, 백그라운드에 있어도 시간이 “정확히” 흐른다.

작업

  • 입력: expiresAt(ISO), now(클라이언트)

  • 출력: remainingSeconds (0 이하면 만료)

  • 서버 시간 오프셋 처리(선택)

    • 서버에서 반환한 serverNow를 받아 localNow와 차이를 offset으로 저장

    • remaining 계산 시 localNow + offset 사용

완료 조건

  • 동일 expiresAt에 대해 앱이 재실행되어도 남은 시간이 일관됨

  • 수동으로 클럭을 바꿔도(가능하면) 정책이 크게 흔들리지 않음(서버 offset 적용 시)


S4-3 타이머 실행(포그라운드) 및 리렌더 최소화

목적
매 초 UI 업데이트는 최소 비용으로 해야 한다.

작업

  • 1초 tick 타이머 구현

  • 상태 업데이트 최소화(remainingSeconds만 갱신)

  • 화면 이탈 시 타이머 정리

완료 조건

  • ReservedScreen에서 초 단위 카운트다운이 부드럽게 동작

  • 화면 이동 후 타이머가 중복 실행되지 않음


S4-4 백그라운드/복귀 시 동기화

목적
사용자가 앱을 나갔다 와도 “정확한 상태”를 본다.

작업

  • AppState 리스너(포그라운드 복귀 감지)

  • 복귀 시:

    • reservation 재조회 API 호출(getReservationById)

    • status 업데이트(reserved/redeemed/expired/cancelled 등)

    • expiresAt 재동기화

완료 조건

  • 백그라운드에 10분 있다 돌아와도 남은 시간이 정확히 반영

  • 이미 만료된 경우 자동으로 만료 상태 UI 표시


S4-5 만료 처리: 서버 상태 전환(Expired) 확정 방식 결정

목적
만료는 “클라이언트가 선언”하면 안 된다. 서버가 최종 결정해야 한다.

권장 방식(초기 현실적인 선택)

  • 서버에서 만료 판단을 일관되게 처리

    • 예약 생성 시 expiresAt 저장

    • 조회 시 now > expiresAt 이면 expired로 업데이트(서버 함수/트리거/Edge Function 또는 DB 작업)

Sprint 4에서는 아래 중 하나로 구현
A안: 조회 시점에 서버에서 expired로 전환(단순)
B안: 예약 생성 시 background job로 만료 처리(복잡, 후순위)

작업

  • reservation 조회 API에서 만료 상태가 올바르게 내려오도록 구현

  • 클라이언트는 remainingSeconds <= 0이면 “만료 확인”을 위해 refresh 호출

완료 조건

  • 만료는 서버 기준으로 확정되고, 앱은 이를 표시만 함

  • 만료 후 재확보가 가능하도록 흐름이 깨지지 않음


S4-6 만료 후 UX: 자동 해제 및 홈 복귀 흐름

목적
만료는 사용자에게 징벌처럼 보이면 안 된다. “자동 해제”로 안내한다.

작업

  • 만료 감지 시 화면 전환 정책

    • 만료 안내 상태를 2~3초 보여준 후 홈으로 이동

    • 또는 “홈으로” 버튼 제공(선택)

  • store.activeReservation 정리

  • 홈에서 자동 새로고침(선택)

완료 조건

  • 만료된 reservation이 store에 남아 다음 동작을 막지 않음

  • 홈 복귀 후 정상 탐색 가능


S4-7 네트워크 불안정 시 타이머/상태 처리 규칙

목적
오프라인/불안정 상태에서 “가짜 성공/가짜 만료”가 보이지 않게 한다.

작업

  • 예약 상태 조회 실패 시

    • 타이머는 expiresAt 기반으로 계속 표시하되,

    • 상태 확정(만료/체크인 가능)은 “서버 확인 필요”로 표시

  • 재시도 버튼 제공

  • 일정 횟수 실패 시 홈 복귀 유도

완료 조건

  • 네트워크 실패가 앱 크래시로 이어지지 않음

  • 만료/확정 상태는 서버 확인 없이는 단정하지 않음


S4-8 이벤트 로깅(타이머/만료)

목적
노쇼/정책 조정의 근거를 만든다.

로그 이벤트(최소)

  • reservation_timer_view

  • reservation_refresh_attempt

  • reservation_refresh_success

  • reservation_expired_view

  • reservation_expired_confirmed (서버 상태 포함)

완료 조건

  • 만료는 “클라 계산”과 “서버 확정”을 구분해 로그가 남음

  • later 분석 시 만료 원인(시간 경과 vs 상태 불일치) 파악 가능


Sprint 4 완료 정의

다음이 가능해야 한다.

  • 확보 후 ReservedScreen에서 서버 기준 타이머가 정확히 흐름

  • 앱 백그라운드/복귀 시 상태가 재동기화됨

  • 15분 경과 시 expired 상태가 서버 기준으로 확정되고 UX가 자연스럽게 처리됨

  • 만료 후 activeReservation이 정리되고 홈으로 복귀하여 재탐색 가능