BurningTimesAi/공유/소통/완료/2026-04-17_어뷰징판정_솔루션_기획서_v1.md

18 KiB
Raw Blame History

type project version status author date scope related_rules related_docs
기획서 수상한잡화점 v1 진행중 기획팀장 2026-04-17 어뷰징 판정 프레임워크 (설계 원칙 + 스키마 + 예시 틀)
C7
C11
C13
C23
P23
공유/소통/기획팀→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 예시)

{
  "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. 위반 응답 포맷 (권고)

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

// 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 지시 로그)