← 자료실/sprintsLOW

Sprint 04 (어픽스 풀) — 드라이런 리허설 (2026-04-21) · 축소판

sprints/sprint-04-dry-run-2026-04-21.md

Sprint 04 (어픽스 풀) — 드라이런 리허설 (2026-04-21) · 축소판

작성: 2026-04-21 (code-lead) · 대상: designs/affix_pool_README.md v1.0 APPROVED §6 code-lead 인계 체크리스트 6건 + §2~§4 스펙 문서 상태: v1.0 (축소판 재발주 — 이전 시도 타임아웃, Sp03 950라인 → 본 문서 목표 450~550라인) 목적: 2026-07-13 Sprint 04 킥오프 전 실행 시뮬레이션으로 어픽스 풀 + 3스택정책 + Mythic 재롤 경로 블로킹·회귀 리스크 선노출 범위: 시뮬레이션만. 코드 0줄 / Unity6/ 미수정 / Sp04 설계 변경 제안 0건 감사 기준: affix_pool_README.md v1.0 APPROVED (PD 5Q 결정) · affix_slot_rules.tsv authoritative · Sp03 Yellow(조건부) 기준 상대 평가 원칙: Sp04 설계 변경 제안 금지. 감지·권고만. Sp01-W1/Sp02-W1/Sp03 누적 회귀 4패턴 + R-DR-06 FP + R-DR-09 부분 FP 교훈 한 줄 반영 (실측 검증 원칙).

§0. TL;DR (PD 1분)

항목값
판정Yellow (킥오프 GO 권장. 사전 완화 3건 + Sp02 W2 AddPermanentPp(long) 음수 차감 경로 실측 선결)
TodoWrite 대상 태스크 수7건 (README §6 인계 6건 + §4.2 10빌드 자기검증 1건)
예상 공수 밴드12.0~15.5h (설계 인계 6건 ~9.0h + 10빌드 검증 2.0h + 회귀 패치 1.0~1.5h + Mythic 재롤 시그니처 drift 튜닝 0~1.5h)
최상위 리스크 3건R-DR-10 (3 스택정책 switch/enum 4종 누락) / R-DR-11 (Mythic 재롤 AddPermanentPp(-50) 음수 안전성 drift) / R-DR-12 (Importer 가 TSV prestige_overlap 컬럼 vs prestige_items.tsv stat_key 싱크 실패) — §0.2
Sp01-W1/Sp02-W1/Sp03 누적 회귀 4패턴 + Sp04 신규 2패턴 누적§7 매트릭스 (Grade enum 6단계 확장 / Range<float> 파서 Min/Max 역전)

§0.1 결론 한 줄

Sp04 TodoWrite 7건은 Happy Path에서 12.0~15.5h 밴드에서 완주 가능. Sp03(14.5~18.5h) 대비 공수 소폭 감소 — Sp04는 순수 데이터 Importer + Calculator 확장이라 MonoBehaviour singleton·OnApplicationPause 같은 플랫폼 리스크 無. 단 Sp03 Yellow 대비 Yellow 판정 유지: (1) 3 스택정책 enum은 어픽스마다 다름 → 30개 어픽스 × 4 policy 분기 = switch 누락 시 fall-through 로 최대 7배 폭주 가능(§5) (2) Mythic 재롤 50PP 차감은 Sp02 W2 AddPermanentPp(long) 시그니처에 음수 입력 허용 가정인데 실측 미검증(§6 R-DR-11) (3) TSV prestige_overlap:AttackPct 컬럼이 prestige_items.tsv stat_key 와 철자 일치하지 않으면 오버랩 필터 실패 → 프레스티지×어픽스 이중 적립 폭주(§0.2 R-DR-12). 세 축 모두 Edit Mode 테스트 #07(10빌드 자기검증) 에서 ±5% 이탈로 Red 노출 가능 → 자기검증 테스트가 사실상 유일한 방어선.

§0.2 최상위 리스크 3건

  1. R-DR-10 [High · 3 스택정책 switch/enum 4종 누락] — README §3.2 는 4가지 stack_policy 값(additive_crossAxis / additive_hardcap / exclusive_onlyOne / additive) 정의. Calculator 확장 시 switch(policy) 에서 한 case 누락되면 default fall-through → additive_crossAxis 로 처리 → exclusive_onlyOne 대상 6개 스탯(DropRatePct/GoldGainPct/ExpGainPct/IdleYieldPct/PpGainPct/EquipOptionAmp)이 프레스티지+어픽스 이중 덧셈. README §3.1 예시대로 IdleYieldPct 가 1.345배가 아닌 3.31배 방치 드립 폭주. 감지 방법: Unknown policy는 Fail-loud (throw new InvalidEnumArgumentException)로 강제. README §6-2 "Unknown policy 는 Fail-loud" 규약 준수 여부가 PR 리뷰 체크포인트. Edit Mode 테스트 #07 B10 경제특화 빌드(2.73x) 가 이중 적립 시 ~4.5x로 점프 → 자기검증 ±5% 이탈 Red.
  1. R-DR-11 [High · Mythic 재롤 50PP 차감 경로 PlayerPrestigeState.AddPermanentPp(-50) 시그니처 drift 가능성] — Sp02 W2 AddPermanentPp(long) / AddSeasonalPp(long) 는 적립 전용 목적으로 설계됨(README d8 §3 Sp02 W2 스케치). 음수 차감을 허용하는지 실측 미검증. Sp02 W2 내부 구현에 Assert.IsTrue(amount >= 0) 가드가 있을 경우 Mythic 재롤 시 AddPermanentPp(-50) 호출 = 런타임 Assertion Failure → Sp04 범위 내 재롤 시스템 전체 블록. 부분 FP 가능성: Sp03 R-DR-09 와 동일 패턴. Sp02 W2 APPROVED 문서 [sprint-02-w2-prestige-tech-sketch.md:193-194] public void AddPermanentPp(long) 시그니처 존재는 확인됨. 단 음수 처리 정책은 설계 문서에 명시 안 됨 → 사전 완화 B1: 2026-07-12 D-1에 Sp02 W2 실 PR에서 음수 처리 로직(가드 throw / clamp 0 / 정상 차감) 실측 필수. 없으면 Sp04 범위에 SpendPermanentPp(long amount) 별도 메서드 신설 0.5h 추가.
  1. R-DR-12 [Medium-High · Importer prestige_overlap 컬럼 vs prestige_items.tsv stat_key 싱크] — README §6-3 "prestige_overlap 컬럼 매핑 — prestige:AttackPowerPct 형식. Importer 가 prestige_items.tsv 의 stat_key 와 일치하는지 교차검증. 불일치 시 Editor Error". 위험: Sp02 W1 실증된 stat_key 철자(예: AttackPowerPct) 와 어픽스 TSV 에서 실수로 AttackPct 로 표기 시 교차검증 메서드 구현 여부에 따라 (a) 빌드타임 Editor Error 노출 OK (b) 미구현 시 런타임 silent miss → 이중 적립 폭주. 근본: Sp01 W1 Importer 는 stat_key 검증 로직 없음(단일 TSV 내부 검증만). Sp04 Importer 는 TSV 2개(어픽스 + 프레스티지) 교차검증 신규 로직 — 드라이런 시점 구현 패턴 미확정. 권고: 사전 완화 B2 — AffixImporter.ValidatePrestigeOverlap() Editor 전용 메서드 시그니처 사전 메모. D-1 에 prestige_items.tsv 30항목 중 어픽스와 중복되는 19개 stat_key 리스트 하드코딩 메모 준비.
[2026-04-21 교차 검증 해소 — Medium-High → Low-Medium 하향] PD 지시 설계 교차 검증 실측: affix_pool.tsv prestige_overlap 컬럼 30행 전수 grep → none 4건(AttackFlat/HpFlat/DefenseFlat/MoveSpeedPct, 어픽스 전용) + prestige:XXX 26건. 26건 전수 prestige_items.tsv stat_key와 일치 확인 (AttackPct→AttackPowerPct / CritDmgPct→CriticalPowerPct / CritRatePct→CriticalRatePct / DefensePct→DefensePowerPct / HpPct→MaxHpPct / CooldownReductionPct→SkillCoolDownPct 6쌍 축약형 매핑 + 20쌍 직통 매핑). TSV 단계에서 설계자가 이미 방어. 잔존 위험은 Importer 구현 시 prestige: 접두사 split + 파싱 에러로 한정 → 리스크 하향 Medium-High → Low-Medium. B2 체크리스트는 여전히 유효(구현 방어선).

§0.3 사전 완화 액션 3건 (버퍼 기간, 2026-07-12 이전)

  1. B1 [30분, D-1 2026-07-12] — Sp02 W2 AddPermanentPp(long) 음수 처리 실측: 실 PR 머지본에서 (a) if (amount < 0) throw 가드 존재 여부 (b) 가드 있으면 Sp04 Mythic 재롤 경로 SpendPermanentPp(long amount) 별도 메서드 신설 0.5h 추가 (c) 가드 없으면 AddPermanentPp(-50) 직접 호출 가능. 미완료 시 킥오프 GO/NO-GO 판정 재검토.
  1. B2 [25분, D-1] — Importer 교차검증 체크리스트 사전 메모: (1) prestige_items.tsv stat_key 30항목 전수 추출 → 어픽스와 중복되는 19개 별도 리스트 (2) Importer 에서 affix.prestige_overlap 컬럼 split 후 prestige:XXX 접두사 제거 → 19개 리스트와 대조 (3) 불일치 시 Debug.LogError($"Affix {id} prestige_overlap={overlap} mismatch. prestige_items.tsv not found") + Editor 빌드 중단. README §6-3 규약 정확 인용.
  1. B3 [20분, D-1] — Sp01-W1/Sp02-W1/Sp03 누적 회귀 4패턴 + Sp04 신규 2패턴 통합 체크리스트 v4: 기존 체크 4항목(Data 어셈블리 신규 SO / PpChannel Runtime / IdleTicker.cs 네임스페이스 / Tests.Editor asmdef 확장) + Sp04 신규 2항목 = (5) "⚠️ AffixDefinitionSO.Grade enum 은 6단계(Common=0 ~ Mythic=5) — Sp01 W2 Grade enum 과 동일 값 사용 강제. 신규 enum 생성 시 CS0579 중복 선언 재현 가능" (6) "⚠️ Range<float> 파서 Min/Max 역전(15-10) 감지 시 Editor Error — TSV 데이터 타입 오류 silent pass 방지".

§1. Sp04 TodoWrite 7건 재확인 표 (README §6 + §4.2)

원천: affix_pool_README.md §6 인계 6건 + §4.2 10빌드 자기검증 1건 = 7건. 1인 파트타임 11~15h 예산 기준, 합계 9.0h + 검증 2.0h = 11.0h.

주요 태스크 (11.0h)

#제목담당예상 공수선행CP 태그
#01AffixDefinitionSO.cs + AffixSlotRulesSO.cs + Range<float> 파서code-lead1.5h(없음)CP-A1 Range 역전 감지
#02AffixImporter.cs TSV 파서 (tier_1~tier_6 + affix_pool.tsv 30행 + affix_slot_rules.tsv 6행)code-lead2h#01CP-A2 파서 결정론
#03Importer prestige_overlap 교차검증 (prestige_items.tsv stat_key 일치)code-lead1h#02, Sp02 W1 prestige_itemsCP-A3 Editor Error + B2 체크리스트
#04StackPolicy enum 4종 + Calculator 확장 메서드 (CalcMultiplier(key, prestigeLv, affixSumPct))code-lead2h#02, Sp02 W2 CalculatorCP-A4 switch 4 case 전수 + Fail-loud default
#05AffixRoller.cs slot_weight 가중치 추첨 (Random.Range(0, totalWeight) 누적 선택)code-lead1.5h#02, #04CP-A5 System.Random 결정론
#06Mythic 재롤 경로 AffixReroller.RerollMythic + AddPermanentPp(-50) 경로 배선code-lead1h#05, Sp02 W2 AddPermanentPpCP-A6 음수 차감 실측 + B1 사전 완화
#07Edit-mode 자기검증 테스트 — affix_stack_matrix.tsv 10빌드 × Calculator ±5% 일치code-lead2h#01~#06CP-A7 10빌드 하드코딩 assert

§1.1 순차 그래프

#01 ──> #02 ──┬──> #03 (prestige_overlap 검증)
              ├──> #04 (StackPolicy enum + Calculator 확장)
              │       │
              │       └──> #05 (AffixRoller) ──> #06 (Reroller + PP 차감)
              │                                        │
              └───────────────────────────────────────┴──> #07 (10빌드 자기검증)

§2. #04 StackPolicy enum + Calculator 확장 Phase 분해

R-DR-10 직결 — Sp04 최대 리스크.

§2.1 Phase 구조

Phase A (enum + 수식 1 policy): StackPolicy.AdditiveCrossAxis 1종 구현 (README §3.3 수식의 else 브랜치) — Sp02 W2 기존 CalcMultiplier(key, prestigeLv) 오버로드로 CalcMultiplier(key, prestigeLv, affixSumPct) 신설. 기존 시그니처 불변 (Sp02 W2 APPROVED 결정 준수). 30분.

Phase B (4 policy 분기 switch): switch(policy) 4 case + default: throw new InvalidEnumArgumentException($"Unknown StackPolicy: {policy}"). README §3.3 수식 정확 인용: additive_hardcap 시 1 + Math.Min(hardcap[stat], prestige + affixSum). 45분.

Phase C (hardcap 7 스탯 테이블): StatHardcapTable 정적 클래스에 CritRate 100% / Dodge 40% / Cooldown 80% / DamageReduction 60% / AttackSpeed 100% / MoveSpeed 30% / LifeSteal 15% 상수 7개 하드코딩. README §3.2 정확 인용. 30분.

Phase D (exclusive_onlyOne 로직): 1 + Math.Max(prestige, affixSum) — 6 스탯 대상. 단순하나 음수 시 Max(-0.1, 0.3) = 0.3 보장 확인. 15분.

§2.2 위험 포인트


§3. #05 AffixRoller 가중치 추첨 Phase 분해

§3.1 Phase 구조

Phase A (totalWeight 선계산): 어픽스 30개 slot_weight 합산. AffixDefinitionSO._cachedTotalWeight 필드로 Importer 시점 계산 (런타임 재계산 금지). 30분.

Phase B (누적 선택): rng.Next(0, totalWeight) → for (i=0..29) { accumulator += affixes[i].slot_weight; if (rnd < accumulator) return affixes[i]; }. List 인덱스 순 강제 (Sp03 CP-M19 결정론 원칙 계승). 45분.

Phase C (Prefix/Suffix 필터): README §2.2 — affix_type == Prefix 만 prefix 슬롯에 롤. Mythic 4:3 비대칭 = Prefix 1개 추가. 필터 후 재계산 totalWeight 필요 → Phase A 재활용 주의 (prefixTotal / suffixTotal 분리 캐시). 15분.

§3.2 위험 포인트


§4. #07 10빌드 자기검증 테스트 Phase 분해

§4.1 Phase 구조

Phase A (test fixture): AffixStackMatrixTests.cs Tests.Editor asmdef 하위. [TestCase] 10개 + 헬퍼 BuildStackFixture(string buildId) 로 affix_stack_matrix.tsv 10행 하드코딩 기대값 매핑. 45분.

Phase B (Calculator 호출 + ±5% assert): Assert.That(actualMult, Is.EqualTo(expectedMult).Within(0.05 * expectedMult)) — README §4.2 affix_stack_matrix.tsv 의 build B04 = 4.26x 타겟. 45분.

Phase C (overflow_alert 빌드 처리): B08 (6.39x) / B09 (7.46x) 는 warning_edge / overflow_alert — 테스트는 Green 유지(의도된 과성장). 단 Mythic 폭주 범위(2.5~3.0x) 가드는 README §5 Q5 (a) 허용 결정 반영 — 테스트는 기대값 그대로 assert. 30분.

§4.2 위험 포인트


§5. 스택 정책 4종 분기 점검 (README §3.2 대조, 2026-04-21 교차 검증 확정)

Note: README §3.2 는 실제로는 4종 정책(additive_crossAxis / additive_hardcap / exclusive_onlyOne / additive)을 정의. Sp04 핵심 점검 지시에 "3 스택정책"으로 표기되었으나 README 가 authoritative 이므로 4종 전수 검증. [2026-04-21 교차 검증 실측 확정] affix_pool.tsv stack_policy 컬럼 30행 uniq -c 결과: additive 3 / additive_crossAxis 14 / additive_hardcap 7 / exclusive_onlyOne 6 = 총 30. 4종 분포 정확. 메모리 project_sprint04_affix_pool.md 는 2026-04-21 drift 정정 완료(3종 → 4종, additive 3건 추가). 본 §5 표 수치는 이미 4종 반영된 상태로 작성되어 있음.
policy대상 stat 수수식검증 빌드 (matrix)
additive_crossAxis14 (AttackPct / CritDmgPct / BossDmgPct / MaxHpPct ...)1 + prestige + affixSumB03~B07 전반
additive_hardcap7 (CritRate / Dodge / Cooldown / DR / AttackSpeed / MoveSpeed / LifeSteal)1 + min(hardcap, prestige + affixSum)B06 치명올인 (CritRate 하드캡 접근)
exclusive_onlyOne6 (DropRate / GoldGain / ExpGain / IdleYield / PpGain / EquipOptionAmp)1 + max(prestige, affixSum)B10 경제특화 핵심
additive3 (flatAttack / flatHp / flatDefense)1 + affixSum (프레스티지 미중복)B01 신규100F (베이스 스탯만)

감지 포인트:


§6. Mythic 재롤 50PP 차감 경로 (R-DR-09 유사 패턴)

§6.1 Sp03 R-DR-09 교훈 반영

Sp03 드라이런은 Sp02 W2 의존 4건에 대해 High 리스크로 블록 플래그 → 실측 후 부분 FP 확정 (설계 시그니처 전수 존재). 잔여 위험은 구현 drift (Low-Medium).

Sp04 R-DR-11 도 동일 패턴:

§6.2 경로 시나리오

// 어느 쪽으로 확정될지 실측 필요:

// Case 1: 음수 허용 (clamp 없음)
state.AddPermanentPp(-50);  // permanentPp -= 50, 가능한 경우 음수 도달

// Case 2: 음수 허용 + clamp 0
state.AddPermanentPp(-50);  // permanentPp = max(0, permanentPp - 50)

// Case 3: 음수 가드 throw
state.AddPermanentPp(-50);  // throw ArgumentOutOfRangeException

// Case 4: 적립 전용 설계 — 차감 전용 SpendPermanentPp 별도
state.SpendPermanentPp(50);  // 신설 필요

§6.3 권고 경로


§7. 회귀 4패턴 + Sp04 신규 2패턴 매트릭스

Sp01-W1/Sp02-W1/Sp03 누적 학습 + Sp04 신규
패턴재발 위험도 Sp04트리거 태스크완화
CS0579 Data 어셈블리 신규 SO 중복Medium#01 AffixDefinitionSO / AffixSlotRulesSO 2건 신규B3 체크리스트 #5 — Data asmdef 배치 경로 Assets/_Project/Scripts/Data/Affix/ 고정
CS0246 Tests.Editor asmdef references 누락Medium#07 AffixStackMatrixTestsTests.Editor asmdef 에 GodBlade.Runtime.Affix / GodBlade.Data.Affix 참조 추가
CS0246 namespace 오타 / 배치 오류Low#01 GodBlade.Runtime.Affix 네임스페이스Sp03 IdleTicker 교훈 — 네임스페이스 사전 고정 (B3 체크리스트)
JSON schemaVersion driftN/ASp04 범위 外Sp04는 Save 시스템 무관 (어픽스는 장비 인스턴스 저장 — Sp06+ 이월)
⭐ Sp04 신규 1: Grade enum 6단계 중복 선언Medium#01 Grade enum 사용Sp01 W2 Grade enum(Common=0 ~ Mythic=5) 재활용 강제. namespace GodBlade.Data.Common 하위 Grade 단일 원천. Sp04 에서 신규 Grade enum 생성 금지. CS0579 재발 트리거
⭐ Sp04 신규 2: Range<float> 파서 Min/Max 역전Medium#01 Range<float> struct + #02 TSV 파서TSV 값 "15-10" 같은 역전 입력 시 Editor Error throw. Silent pass 시 tier_3 롤 범위가 -5~+5 로 깨짐

§8. 실측 검증 FP 가능성 후보 표 (R-DR-06 / R-DR-09 교훈)

후보드라이런 추정실측 확인 시점FP 가능성
R-DR-11 Mythic 재롤 음수 차감High2026-07-12 D-1 실 PR 머지 확인부분 FP 가능성 높음 — 설계 시그니처 public void AddPermanentPp(long) 존재 확인. 음수 처리 정책만 미검증. Case 1/2 시 즉시 Low 강등
R-DR-12 Importer 교차검증 미구현Medium-High2026-07-12 D-1 prestige_items.tsv 재확인Low FP 가능성 — Sp02 W1 에서 TSV 교차검증 패턴이 없으므로 Sp04 신규 구현 확실히 필요. 단 어픽스↔프레스티지 중복 19개 리스트는 실측 정확값 확인 가능
R-DR-10 switch 4 case 누락High#07 Edit Mode 테스트 시점FP 불가능 — 순전히 구현 주의 리스크. 테스트 Green 이 유일 검증
Range<float> 역전 감지MediumSp04 신규 — 실측 불필요선결 구현 사안
Grade enum 중복 선언Medium2026-07-12 D-1 Sp01 W2 머지본에서 Grade 실 정의 위치 확인중간 FP 가능성 — Sp01 W2 실 Grade 가 namespace GodBlade.Data.Common 에 있으면 Sp04 재활용 가능. 다른 곳이면 추가 이동 공수 0.3h

§9. 사전 완화 액션 3건 상세

B1 [30분, D-1] — Sp02 W2 AddPermanentPp(long) 음수 처리 실측

  public void AddPermanentPp(long amount) {
    // A: if (amount < 0) throw ...   → 가드 존재
    // B: permanentPp = Math.Max(0, permanentPp + amount);  → clamp
    // C: permanentPp += amount;  → 허용
  }

B2 [25분, D-1] — Importer 교차검증 체크리스트 메모

  AttackPct, CritRatePct, CritDmgPct, BossDmgPct, PackDmgPct, MaxHpPct, 
  DefensePct, DropRatePct, GoldGainPct, ExpGainPct, IdleYieldPct, 
  PpGainPct, GuardianAtkPct, EquipOptionAmp, MagicFindPct, LifeStealPct,
  CooldownReductionPct, DodgeRatePct, AttackSpeedPct
  foreach (var affix in affixes) {
    foreach (var overlap in affix.prestigeOverlap.Split(',')) {
      var statKey = overlap.Replace("prestige:", "").Trim();
      if (!prestigeStatKeys.Contains(statKey)) {
        Debug.LogError($"Affix {affix.id} prestige_overlap={statKey} not in prestige_items.tsv");
        EditorApplication.isPlaying = false;  // 빌드 중단
      }
    }
  }

B3 [20분, D-1] — 체크리스트 v4 (신규 2항목 추가)

[ ] Sprint 01 W1: Data 어셈블리 신규 SO 경로 `Assets/_Project/Scripts/Data/<Topic>/`
[ ] Sprint 02 W2: PpChannel Runtime 배치
[ ] Sprint 03: IdleTicker.cs `GodBlade.Runtime.Idle` 네임스페이스
[ ] Sprint 03: Tests.Editor asmdef 확장
[ ] ⭐ Sprint 04: Grade enum 6단계 Sp01 W2 재활용 강제 (신규 선언 금지)
[ ] ⭐ Sprint 04: Range<float> Min/Max 역전 감지 Editor Error throw

§10. 메타정보


§11. 판정 요약

2026-07-13 Sprint 04 킥오프 → GO (Yellow)


(끝 — v1.0 축소판, 2026-04-21 code-lead 작성)