Sprint 7 - 반복 미도착 사용자 제한_제재_

Sprint 7 - 반복 미도착 사용자 제한_제재_

목표
보증금 없이도 시스템이 스스로를 보호한다.
제재는 운영자가 수동으로 집행하지 않고, 규칙에 따라 자동 적용된다.
영구 차단은 기본 정책이 아니다.

원칙

  • 제재는 “벌”이 아니라 “신뢰 회복을 위한 제한”으로 표현한다.

  • 제재 기준과 해제 조건은 투명해야 한다.

  • 발행자 개입은 없다.


S7-1 제재 정책(규칙) v1 고정

목적
지금 당장 구현 가능한 단순 규칙으로 시작한다(정교화는 Phase 3에서).

권장 v1 규칙(예시)

  • 관측 기간: 최근 7일

  • expired(미도착 만료) 횟수 기준

    • 1회: 경고(제재 없음)

    • 2회: 확보 유효시간 15 → 10분

    • 3회: 24시간 확보 금지

  • 해제 조건

    • 제한 기간 경과 또는

    • 일정 기간(예: 7일) expired 추가 발생 없음

추가 제한(선택)

  • active reservation 동시 1개 고정(이미 적용 중)

완료 조건

  • 규칙이 문서/코드 상수로 고정됨

  • “숫자 조정”만으로 정책 튜닝 가능하게 분리


S7-2 데이터 모델: penalties(또는 user_limits) 테이블 설계

목적
제재를 서버 기준으로 적용하고, 앱은 표시만 한다.

필드 제안

  • userId

  • level (0/1/2 등)

  • reason (repeated_no_show)

  • activeUntil (datetime)

  • overrides

    • maxActiveReservations (int)

    • reserveExpiresMinutes (int)

  • createdAt, updatedAt

완료 조건

  • userId 기준으로 현재 제재 상태를 조회할 수 있음

  • 제재가 없으면 레코드가 없거나 level=0


S7-3 제재 평가 로직(서버) 구현

목적
사용자 행동(expired 발생)을 기반으로 자동 적용한다.

트리거 포인트(권장)

  • reservation이 expired로 확정되는 시점에 평가 함수 호출

    • expired가 서버에서 확정되는 흐름(Sprint 4)과 연결

작업

  • 최근 7일 expired 횟수 계산

  • 정책에 따라 penalties upsert

  • activeUntil 계산

  • 이미 더 높은 제재가 활성인 경우의 우선순위 규칙 정의

    • 높은 레벨이 우선

    • activeUntil은 max로 유지

완료 조건

  • expired 이벤트가 발생하면 자동으로 제재가 갱신됨

  • 수동 개입 없이 일관되게 적용됨


S7-4 확보(Reserved 생성) 시 제재 검사 및 실패 처리

목적
제재가 있어도 사용자는 “왜 안 되는지”를 이해해야 한다.

작업

  • createReservation RPC/API에서

    • penalties 조회

    • 확보 금지(activeUntil > now)면 거절

    • reserveExpiresMinutes override가 있으면 expiresAt에 반영

    • maxActiveReservations override 검사

  • 실패 reason 정의

    • user_temporarily_blocked (until 포함)

    • reserve_limit_reached

    • reserve_expiry_shortened (성공이지만 안내 필요)

완료 조건

  • 제재 사용자에게 확보가 서버에서 차단됨

  • 제재가 있는 경우 expiresAt이 정책대로 짧아짐(예: 10분)


S7-5 앱 UI: 제재 안내 화면/모달 구현

목적
제재를 “이해 가능한 안내”로 표현한다.

작업

  • 확보 시도 시 서버가 제재로 거절하면

    • 제한 사유(반복 미도착)

    • 해제 시각(activeUntil)

    • 이후 권장 행동(시간 준수, 체크인 필요)

  • 제재가 강하지 않은 경우(10분 단축 등)

    • 확보 성공 후 ReservedScreen에서 “유효시간 10분 적용” 안내(짧게)

완료 조건

  • 사용자는 왜 제한됐는지, 언제 풀리는지 안다

  • 문구는 비난/감정 표현 없이 차분함 유지


S7-6 제재 상태 조회 및 프로필/설정 위치(선택)

목적
사용자가 “내 상태”를 확인할 수 있게 한다(분쟁 감소).

작업

  • 내 정보(또는 설정) 화면에

    • 현재 제한 여부

    • 남은 기간

    • 제한 내용(예: 확보 유효시간 10분)

  • 최소 구현이면 History 화면 상단에 작은 배너 형태로도 가능(과장 없이)

완료 조건

  • 제재 상태를 사용자가 언제든 확인 가능

S7-7 오탐/중복 만료 방지 안전장치

목적
제재의 신뢰성은 “오탐률”에서 무너진다.

작업

  • expired 판정은 server-confirmed만 카운트

  • 동일 reservation이 중복 expired 처리되지 않도록 idempotent 보장

  • 테스트 케이스

    • 이미 redeemed면 expired로 바뀌지 않도록 보장

    • 네트워크 문제로 클라가 만료로 보더라도 서버 확정 없으면 카운트 금지

완료 조건

  • expired 카운트가 안정적이며 중복되지 않음

  • redeemed 이후에는 expired로 집계되지 않음


S7-8 이벤트 로깅(제재)

목적
정책 조정 및 사용자 CS 대응 근거 확보.

로그 이벤트(최소)

  • penalty_evaluated (expiredCount, period)

  • penalty_applied (level, until, overrides)

  • penalty_blocked_reservation_attempt

  • penalty_override_applied (reserveExpiresMinutes 변경 등)

  • penalty_cleared

완료 조건

  • 제재 적용/해제가 모두 로그로 남음

  • 이후 정책 튜닝 시 근거 데이터가 확보됨


Sprint 7 완료 정의

다음이 가능해야 한다.

  • 반복 미도착(Expired) 발생 시 자동으로 제재가 평가/적용됨(서버 기준)

  • 제재가 있으면 확보가 제한되거나 유효시간이 단축됨

  • 앱은 제재 사유/기간을 명확히 안내함

  • 제재는 점진적이며 영구 차단이 기본값이 아님

  • 오탐/중복 집계 안전장치가 있음