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) 발생 시 자동으로 제재가 평가/적용됨(서버 기준)
제재가 있으면 확보가 제한되거나 유효시간이 단축됨
앱은 제재 사유/기간을 명확히 안내함
제재는 점진적이며 영구 차단이 기본값이 아님
오탐/중복 집계 안전장치가 있음