---
type: 기획서
project: 수상한잡화점
version: v1
status: 진행중
author: 기획팀장
date: 2026-04-17
scope: 어뷰징 판정 프레임워크 (설계 원칙 + 스키마 + 예시 틀)
related_rules: [C7, C11, C13, C23, P23]
related_docs:
  - 공유/소통/기획팀→PM/2026-04-17_Unity_MCP_시뮬레이션_기획검토_기획팀.md
  - 프로젝트/수상한잡화점/기획/Phase3_재개준비_체크리스트_v1.md
---

# 어뷰징 판정 솔루션 기획서 v1

## 요지

스테이지 클리어 보상·랭킹 등록·일일 미션에서 클라가 전송하는 데이터를 서버가 **"시뮬레이터 산정 이론 상한 경계값"** 기반으로 검증하여, 경계를 초과하는 요청을 어뷰저로 판정·차단한다. 기획팀은 경계값 도출 방법론과 테이블 스키마를 제공하고, 서버는 검증 로직을 탑재한다. 실제 수치는 Unity MCP 시뮬 가동 결과로 채워진다(본 기획서는 틀만 제공).

**재미 관점(C7)**: 어뷰징이 방치되면 랭킹·미션의 도전 가치가 붕괴되고, 정상 플레이어의 성취감이 훼손된다. 본 솔루션의 목표는 "정직한 플레이어의 재미를 보호"하는 것이지 선의의 실력자를 잡는 것이 아니다. 따라서 경계값은 **이론 상한에 안전 마진을 더한 값**으로 설정하여 false positive를 최소화한다.

---

## A. 문제 정의

### A-1. 전제
- 모든 보상(미션·스테이지·랭킹) = 재화 형태로 지급 확정 (2026-04-17 PD님 결정)
- 스테이지 클리어·랭킹 등록에서 서버는 클라 전송 데이터를 기반으로 보상을 산정/기록한다
- 클라를 무조건 신뢰하면 메모리 조작·패킷 위변조를 통한 재화 부당 획득이 가능하다

### A-2. 어뷰징 공격 벡터

| 벡터 ID | 대상 액션 | 조작 포인트 | 파급 위험 |
|--------|----------|-----------|---------|
| **AV-1** | 스테이지 클리어 완료 패킷 | 클리어타임 단축 (예: 0초·음수) | 시간 가속 보상 파밍 |
| **AV-2** | 스테이지 클리어 완료 패킷 | 획득 재화량 조작 (상한 초과) | 재화 무한 생성 |
| **AV-3** | 스테이지 클리어 완료 패킷 | 별(★) 개수 조작 (3/3 고정) | 미달성 보상 부당 수령 |
| **AV-4** | 스테이지 클리어 완료 패킷 | 소모 자원 0 보고 (물약·쉴드·HP) | ★조건 달성 위조 (C6 포션절제, N2 피격제한 등) |
| **AV-5** | 랭킹 등록 패킷 | 점수값 조작 (이론 상한 초과) | 랭킹 1위 탈취 |
| **AV-6** | 랭킹 등록 패킷 | 연관 메타값 조작 (사용 카드·편성 등 검증 소재) | 검증 회피 |
| **AV-7** | 일일 미션 카운트 | 카운트 중복 전송·상한 초과 | 일일 한도 초과 보상 수령 |
| **AV-8** | 리플레이/재접속 재전송 | 동일 클리어 결과 재제출 | 중복 보상 |
| **AV-9** | 스테이지 잠금 우회 | 언락 안 된 스테이지 완료 패킷 | 진행도 건너뛰기 |

### A-3. 판정 대상 범주 3종

1. **물리적 불가능** — 시뮬레이터로도 달성 불가능한 수치 (예: 클리어타임 0초, 점수 int.MaxValue)
2. **확률적 극단** — 이론상 가능하나 확률이 충분히 낮아 사실상 어뷰징으로 간주 (예: 운으로 1회 나올 수치의 연속 달성)
3. **논리적 모순** — 내부 값들이 서로 모순 (예: "피격 0회"인데 "HP 50% 소진")

---

## B. 경계값 도출 방법론

### B-1. 기본 공식

```
경계값 = 시뮬_이론_극값 × 안전마진계수
```

- `시뮬_이론_극값`: Unity MCP 시뮬을 N회(권장 N=1,000 이상) 수행하여 얻은 **최상위 극값** (최대/최소는 벡터에 따라 다름)
- `안전마진계수`: 벡터 특성에 따라 결정하는 완화 계수 (정상 플레이어 오차 허용)

### B-2. 안전마진 설계 원칙

| 벡터 특성 | 마진 방향 | 계수 예시 | 근거 |
|---------|--------|---------|------|
| 클리어타임 (짧을수록 의심) | 하한 경계값 = 이론 최단 × **0.80** | 0.80 | 프레임 드랍·클라 시계 오차로 정상 유저도 5~15% 짧게 보고 가능 |
| 획득 재화 (많을수록 의심) | 상한 경계값 = 이론 최대 × **1.05** | 1.05 | 소숫점 반올림·버프 중첩 경계 케이스 흡수 |
| 랭킹 점수 (높을수록 의심) | 상한 경계값 = 이론 최대 × **1.10** | 1.10 | 신규 카드 출시 등 업데이트 이후 시뮬 갱신 전 과도기 흡수 |
| 피격 수 (적을수록 의심) | 하한 경계값 = 이론 최소 (= 0) | - | 0회도 이론상 가능, 음수만 차단 |
| 미션 카운트 | 상한 경계값 = 일일 최대 달성 가능치 × **1.00** | 1.00 | 마진 불필요 (정수 카운트) |

**주의**: 마진은 "정상 유저를 어뷰저로 오판정하지 않기 위한" 안전장치지, "어뷰저를 놓치는 관용"이 아니다. 극값의 80%~110% 범위는 경계이므로 이 범위 유저는 "**1차 통과 + 플래그 미부여**"로 처리한다.

### B-3. 업데이트 주기

1. **정기 갱신**: 밸런스 패치(카드 수치 변경·신규 몬스터 추가) 시 해당 영역 시뮬 재실행
2. **긴급 갱신**: 어뷰징 신고 접수 또는 랭킹 이상치 감지 시 즉시 시뮬 재실행·경계값 조정
3. **버전 관리**: 경계값 테이블은 C6에 따라 `.bak_{YYYYMMDD_HHMM}.json` 백업 후 교체
4. **C13 기록**: 경계값 변경은 PD 지시 로그·대화로그에 기각안 포함 기록 (P24)

### B-4. 시뮬레이터 입력 조건 (Unity MCP)

각 스테이지·각 벡터에 대해 다음 조건의 최극단 조합을 시뮬:
- 캐릭터: 최강 편성 (풀레벨·최적 카드)
- 적 패턴: 최선 운 (치명타 확률 최대·적 회피 최소)
- 플레이 입력: 완벽 입력 (반응시간 0·공백 없음)
- 물약·쉴드: 최대 활용 (획득 재화 벡터) / 미사용 (C6 조건 벡터)

**출력 수집**: 10,000회 반복하여 상위/하위 0.1% 값을 "이론 극값"으로 채택 (절대 최대/최소 아닌 이유 = 시뮬 자체 오차 흡수).

---

## C. 검증 계층 설계

### C-1. 2계층 검증 원칙

**1계층 (클라)** — 예방적 차단
- 목적: 악의적 조작이 아닌 **버그·의도치 않은 극값**을 클라 단에서 거르기
- 클라가 자체 생성한 결과값이 경계값을 초과하면 전송 보류 + 경고 로그 수집
- **클라 신뢰는 하지 않음** — 이 계층만으로는 판정 금지 (메모리 조작 시 이 계층 무력화 가능)

**2계층 (서버)** — 최종 판정
- 목적: 모든 어뷰징 판정의 **단일 결정권자**
- 서버가 경계값 테이블을 보유하고 수신 패킷 전량 검증
- 경계 초과 시: 거부 + 플래그 기록 + (심각도에 따라) 관리자 알림

### C-2. 검증 흐름 (서버)

```
[클라 패킷 수신]
  ↓
[Step 1] 기본 유효성 (음수·null·형식 오류) → 거부
  ↓
[Step 2] 스테이지 잠금 상태 확인 (AV-9 대응) → 거부
  ↓
[Step 3] 중복 제출 확인 (AV-8 대응, 같은 세션ID·클리어ID) → 거부
  ↓
[Step 4] 경계값 테이블 조회 → 각 필드 범위 검증
  ↓ (통과)
[Step 5] 논리 정합성 검증 (필드 간 모순, A-3-3 범주)
  ↓ (통과)
[정상 처리 + 보상 지급]

  ↓ (Step 4·5 실패 시)
[플래그 기록 + 보상 보류 + 심각도별 조치]
```

### C-3. 역할 분담 원칙

| 주체 | 역할 | 금지 |
|-----|-----|-----|
| 클라 | 버그 조기 감지·UX 경고 | 최종 판정, 플래그 기록 |
| 서버 | 최종 판정, 플래그 DB 기록, 관리자 알림 | 클라 통과 가정·검증 생략 |
| 기획팀 | 경계값 테이블 공급 | 서버 검증 로직 직접 작성 |
| 인간 서버 개발자 | 검증 로직 구현·플래그 DB 스키마 | 경계값 자체 수정 (기획 승인 없이) |

---

## D. 어뷰저 플래그 체계

### D-1. 플래그 종류 3단계

| 단계 | 트리거 | 자동 조치 | 관리자 조치 |
|-----|-------|---------|-----------|
| **F1 경미** | 경계값의 +5%~+10% 범위 이내 초과 (마진 범위 경계) | 플래그 기록만 | 누적 3회 이상 시 F2 격상 |
| **F2 중대** | 경계값의 +10%~+50% 초과, 또는 F1 3회 누적 | 해당 보상 보류 + 관리자 알림 | 수동 검토 후 재화 회수·경고 |
| **F3 확정** | 경계값의 +50% 초과, 논리 모순 발생, 또는 F2 2회 누적 | 해당 보상 미지급 + 계정 플래그 | 계정 정지 검토 (랭킹 삭제 포함) |

### D-2. 플래그 누적 처리

- 플래그 DB: `{user_id, timestamp, vector_id, flag_level, raw_data, boundary_value, reason}`
- 기간 윈도우: 최근 30일 기준 누적 (기획팀 권고안, 서버측 조정 가능)
- 에스컬레이션: F1×3 → F2 / F2×2 → F3 / F3×1 → 즉시 계정 정지 검토 대상

### D-3. 기획팀 권고안 (PM 경유 운영팀 협의 필요)

- **F1**: 자동 회수 없음 (false positive 위험). 사용자에게 경고도 노출하지 않음 (어뷰저 학습 방지)
- **F2**: 해당 회차 보상만 회수. 사용자에게는 "서버 동기화 오류, 재시도" 메시지 노출
- **F3**: 계정 정지는 관리자 최종 판단. 랭킹 등록 데이터는 즉시 삭제

---

## E. 대상 액션별 구체 경계값 초안

> **주의**: 아래 수치는 모두 **플레이스홀더**. Unity MCP 시뮬 가동 후 확정. 실제 경계값 테이블은 별도 JSON으로 관리.

### E-1. 스테이지 클리어

| 필드 | 검증 규칙 | 경계값 예시 (Stage 1) |
|-----|---------|----------------------|
| `clearTime` | `sim_min × 0.80` 하한, `sim_max × 1.20` 상한 | 하한: 미확정(시뮬 후) / 상한: 미확정 |
| `goldEarned` | `sim_max × 1.05` 상한 | 상한: 미확정(시뮬 후) |
| `starsEarned` | 0~3 정수, ★조건 메타값과 교차 검증 | 0~3 |
| `hpRemaining` | `0 ≤ hp ≤ maxHp` | 캐릭터 maxHp 기반 |
| `potionUsed` | 0 이상 정수, 소지 한도 이하 | 캐릭터 포션 한도 |
| `shieldRemaining` | `0 ≤ shield ≤ maxShield` | 캐릭터 maxShield 기반 |
| `hitsTaken` | 0 이상 정수, `sim_max × 1.20` 상한 | 상한: 미확정(시뮬 후) |

### E-2. 랭킹 등록

| 필드 | 검증 규칙 | 경계값 예시 |
|-----|---------|----------|
| `score` | `sim_max × 1.10` 상한 | 상한: 미확정(시뮬 후) |
| `clearTime` | 동일 스테이지 E-1 규칙 적용 | - |
| `deckComposition` | 소유 카드 목록과 교차 검증 | - |
| `stageId` | 유효 스테이지 ID (잠금 해제 상태) | - |

### E-3. 일일 미션

| 필드 | 검증 규칙 | 경계값 예시 |
|-----|---------|----------|
| `missionId` | 유효 미션 ID + 당일 활성 | - |
| `currentCount` | `missionMaxCount` 상한 | 미션별 상한 |
| `incrementDelta` | 단일 트리거로 1 증가만 허용 | 1 |
| `completionTimestamp` | 일일 리셋 시각 이후 ~ 현재 | - |

### E-4. ★조건 교차 검증 (P17 연계)

각 스테이지의 활성 ★조건(C1~C9, N1~N6)과 클리어 결과 필드가 정합해야 한다. 예:
- **C6 (포션 절제)**: `potionUsed == 0` 인지 확인
- **N2 (피격 제한)**: `hitsTaken ≤ 서브맵수 × 1` 인지 확인
- **N4 (쉴드 하한 30%)**: `shieldRemaining ≥ maxShield × 0.30` 인지 확인

★조건 통과 보고와 필드 값이 모순되면 **F3 확정 플래그** (논리 모순).

---

## F. 서버 측 요구사항 (개발팀 인계용)

### F-1. 기획팀 공급 산출물

1. **경계값 테이블** — JSON 파일 (Unity MCP 시뮬 결과 반영)
2. **★조건 검증 규칙** — 스테이지별 활성 조건 + 판정 로직
3. **플래그 기준** — F1/F2/F3 경계 정의
4. **갱신 공지** — 경계값 변경 시 개발팀에 PR 또는 소통 채널 통지

### F-2. 경계값 테이블 스키마 (JSON 예시)

```json
{
  "version": "1.0.0",
  "generatedAt": "2026-04-17T00:00:00Z",
  "simulationRuns": 10000,
  "stages": {
    "stage_01": {
      "clearTime": {
        "min": 42.3,
        "max": 180.0,
        "marginLow": 0.80,
        "marginHigh": 1.20,
        "boundaryMin": 33.84,
        "boundaryMax": 216.0
      },
      "goldEarned": {
        "max": 250,
        "marginHigh": 1.05,
        "boundaryMax": 263
      },
      "hitsTaken": {
        "min": 0,
        "max": 8,
        "marginHigh": 1.20,
        "boundaryMax": 10
      },
      "starConditions": {
        "C2": { "field": "hitsTaken", "operator": "==", "value": 0 },
        "C6": { "field": "potionUsed", "operator": "==", "value": 0 },
        "N2": { "field": "hitsTaken", "operator": "<=", "formula": "subMapCount * 1" }
      }
    }
  },
  "ranking": {
    "stage_01": {
      "score": { "max": 12500, "marginHigh": 1.10, "boundaryMax": 13750 }
    }
  },
  "dailyMissions": {
    "login": { "maxCount": 1 },
    "clear_any_stage": { "maxCount": 10 }
  }
}
```

### F-3. 검증 API 호출 흐름 (서버 내부)

```
수신: POST /api/stage/complete
  body: { userId, stageId, clearTime, goldEarned, starsEarned, hitsTaken, potionUsed, ... }

서버 처리:
  1. AbuseValidator.validate(userId, stageId, body)
     → boundaries = BoundaryTable.get(stageId)
     → for each field: 경계값 비교
     → starCondition 교차 검증
     → 중복 제출 체크
  2. ValidationResult:
     - PASS: 보상 지급 처리
     - F1: 보상 지급 + 플래그 기록
     - F2: 보상 보류 + 플래그 기록 + 관리자 알림
     - F3: 보상 미지급 + 플래그 기록 + 계정 플래그
  3. 응답:
     - PASS/F1: { status: "success", rewards: [...] }
     - F2: { status: "pending", message: "서버 동기화 오류, 재시도 바랍니다" }
     - F3: { status: "blocked" }  (어뷰저 학습 방지 위해 구체 사유 미노출)
```

### F-4. 위반 응답 포맷 (권고)

어뷰저 학습 방지를 위해 구체 수치·사유를 클라에 노출하지 않는다:

```json
// F1 (경미)
{ "status": "success", "rewards": [...] }  // 플래그는 서버 내부만, 클라 무감지

// F2 (중대)
{ "status": "pending", "message": "서버 동기화 오류, 잠시 후 재시도" }

// F3 (확정)
{ "status": "blocked" }
```

### F-5. 플래그 DB 스키마 (서버 구현 시 참조)

```
AbuseFlag:
  - id: UUID
  - userId: string
  - timestamp: datetime
  - vectorId: enum (AV-1 ~ AV-9)
  - flagLevel: enum (F1, F2, F3)
  - stageId: string (nullable)
  - fieldName: string
  - rawValue: json
  - boundaryValue: json
  - exceedRate: float  // (rawValue - boundary) / boundary
  - reason: string
  - reviewedBy: string (nullable)
  - reviewedAt: datetime (nullable)
  - resolution: enum (pending, confirmed_abuse, false_positive, pardoned)
```

---

## G. 기각안

### G-1. 서버 단독 시뮬 재현 검증 (채택 안 함)

- **안**: 서버가 클라 입력(키·타이밍)을 받아 서버에서 전투를 재시뮬하여 결과 일치 여부 검증
- **기각 사유**: (1) 서버 CPU 비용 폭증 — 1회 재시뮬 ≈ 1개 전투 전체 연산 (2) 동기화 이슈 (난수 시드·부동소수점) (3) 현 프로젝트가 실시간 멀티플레이가 아닌 싱글 플레이 구조라 과잉 투자. **채택 안**인 "경계값 기반 통계적 검증"이 비용·구현 난이도·효과 3축에서 우수.

### G-2. 머신러닝 기반 이상치 탐지 (채택 안 함)

- **안**: 유저 플레이 데이터를 수집하여 ML 모델로 어뷰저 이상치 자동 탐지
- **기각 사유**: (1) 학습 데이터 축적에 운영 기간 필요 — 초기 출시 대응 불가 (2) false positive 조정 난해 (3) 인간 서버 개발자 부담 가중. 장기적 보조 수단으로는 고려 가치 있으나 v1 범위에서 제외. 본 기획서는 시뮬 경계값으로 출시 대응 + 운영 후 데이터 축적 → 차후 ML 도입 여지 유지.

### G-3. 클라 단독 판정 (채택 안 함)

- **안**: 클라가 자체 검증 후 서버에는 결과만 전송
- **기각 사유**: 메모리 조작·패킷 위변조로 무력화됨. 어뷰징 방지 근본 목적 미달성. **원천적으로 고려 대상 아님**.

### G-4. 전체 플레이 로그 전송·서버 기록 (채택 안 함)

- **안**: 매 프레임 입력 로그 전체를 서버로 전송하여 서버가 사후 감사
- **기각 사유**: (1) 네트워크 비용 과도 (2) 저장소 비용 (3) G-1과 유사하게 오버엔지니어링. F3 확정 플래그 시점에 사후 감사용으로 마지막 30초~60초 정도만 보관하는 방안은 서버측 재량.

### G-5. 안전 마진 0% 엄격 검증 (채택 안 함)

- **안**: 시뮬 극값을 그대로 경계값으로 사용하여 극한 배제
- **기각 사유**: false positive 폭발. 프레임 드랍·반올림 오차로 정상 유저도 매번 플래그됨. **C7 재미 우선 원칙 위반** — 정상 플레이어 경험 훼손. 5%~20% 마진 보정 필수.

---

## 후속 작업 (Unity MCP 시뮬 가동 후 수행)

1. 각 스테이지·각 벡터별 시뮬 10,000회 실행
2. 경계값 테이블 JSON 1차 산출 (v1.0.0)
3. balance-designer 검토 → 재미 관점 마진 재조정
4. 개발팀과 스키마·API 계약 확정 (`공유/소통/기획팀→개발팀/` 발행)
5. 플래그 DB 스키마 서버팀 리뷰·구현
6. 통합 QA 시 어뷰저 시뮬 툴로 F1/F2/F3 각각 검증 케이스 생성

## 연관 규칙·문서

- **C7**: 재미 우선 — 정상 플레이어 보호를 위한 마진 설계 근거
- **C11**: 개발 관점 — 서버 자원 효율 고려하여 재시뮬 대신 경계값 비교 채택 (G-1 기각 근거)
- **C13**: PD 지시 트래킹 — 본 기획 등록 및 경계값 변경 이력 관리
- **C23**: 허위 보고 금지 — 본 기획서는 실제 시뮬 가동 전이므로 수치는 모두 플레이스홀더 명시
- **P17**: ★조건 배타 배치 — E-4 ★조건 교차 검증과 연계
- **P23**: 기획 결정 재량 — 본 기획은 기획팀장 재량 범위(신규 시스템 제안은 PM 확인 필요 → 본 기획서 발행으로 PM 확인 경유)

---

**기획팀장 발의**
**PM 검토 요청**: 본 기획서 스키마·프레임워크 승인 → 개발팀 F 섹션 인계 트리거
**승인 후 착수**: Unity MCP 시뮬 가동 (별도 PD 지시 로그)
