Sprint 02 W1 — 드라이런 리허설 (2026-04-21)
작성: 2026-04-21 (code-lead) · 대상: Sprint 02 W1 예상 태스크 (설계 문서 비추정 상태, 본 드라이런이 최초 도출) 문서 상태: v1.0 목적: 2026-05-18 Sprint 02 W1 실제 킥오프 전 실행 시뮬레이션으로 블로킹·회귀 리스크 사전 노출 범위: 실행 시뮬레이션만. 실제 코드 0줄 (Unity6/건드리지 않음). 문서만 작성 감사 기준:sprint-02-w2-prestige-tech-sketch.mdv1.0 APPROVED ·prestige_items_README.mdv1.0 APPROVED ·shared-checkpoints.mdv1.0 ·d8-stat-key-validation-2026-04-21.mdv1.0 APPROVED ·sprint-01-dry-run-2026-04-21.mdv1.0 원칙: Sp02 설계 결정 변경 제안 금지 (v1.0 APPROVED 고정). 감지·권고만. PM의 W1 태스크 추정 플래그 해소 기여 필수.
§0. TL;DR (PD 1분)
| 항목 | 값 |
|---|---|
| 판정 | Yellow (킥오프 GO 권장. 단 사전 완화 3건 + 태스크 순서 엄수 조건부) |
| Sp02 W1 태스크 도출 수 | 7건 (#T01~#T07) |
| 예상 공수 합계 (도출 기준) | 13.0h (로드맵 §5 "12~15h" 밴드와 정합) |
| 실공수 예상 밴드 | 13.5~17.0h (회귀 패치 1.0~2.0h + TsvReader 리팩터 오버런 0.5~2.0h) |
| 최상위 리스크 3건 | R-DR-04 / R-DR-05 / R-DR-06 (§0.2) |
| Sp00+Sp01 회귀 3패턴 재현 확률 | Low (CS0246) / Medium (CS0579) / Medium (TSV 경로 drift) / Low (네임스페이스) — §10 상세 |
| 패턴 충돌 리스크 | Medium — SO 카탈로그(Sp01 W2 DQ1 옵션A) vs struct+List hot path(Sp02 W2 Q1 옵션B) 의도적 분기, 단 1주 간격으로 동일 개발자가 두 패턴을 연속 작성 → 혼동 유발 여지 (§13 특수 리스크) |
§0.1 결론 한 줄
Sp02 W1 태스크 #T01~#T07은 Happy Path에서 13.5~17.0h 구간 내 완주 가능. 최대 블로킹 축은 #T01 TsvReader 공통화 시 Sp01 DropRateTableImporter / MilestoneRewardImporter / AffixPoolImporter 3종의 "이미 머지된 코드" 를 역으로 개편하는 리팩터 범위(설계상 TsvReader 공통화는 Sp01 W2 DQ3 이월 결정 = Sp02 W1 첫 과제). 나머지 #T02~#T06는 Sp01 W1 드라이런 경험칙(SO+Importer 쌍) 1:1 재활용으로 리스크 Medium 수준. #T07 stat_key 매핑 사전 검증은 Sprint 03 IdleRateMul 필드명 연동 첫 테스트로 반드시 #T06 테스트 직전 수행.
§0.2 최상위 리스크 3건
- R-DR-04 [High · TsvReader 공통화 범위 오버런] — Sp01 W2에서
DropRateTableImporter/MilestoneRewardImporter/AffixPoolImporter3종 각자File.ReadAllLines+ BOM trim +Split('\t')복제로 이미 Green 으로 머지됨. Sp02 W1 #T01 에서TsvReader.cs를Editor/Importers/Shared/에 추출하면 Sp00TranscendentStageImporter.cs포함 4개 Importer의 Read 로직을 전부 호출부로 전환해야 함. 설계 §2.5 "Sprint 00 Importer는 동작 불변 — 새 공통 모듈을 호출하도록 최소 편집" 명시되어 있으나, 실측 시 diff 범위 4 파일 × 평균 20 lines = 80 lines + 각 Importer의Row/ReadTsv/ValidateHeader중복 제거. 리팩터 중 회귀 0건 유지 난이도 High. #T01 단독 PR 권장 + 회귀 테스트 실행 전제.
- R-DR-05 [Medium ·
PrestigeItemCatalogSO14컬럼 TSV 파싱 피로도] —prestige_items.tsv헤더 실측 = 14 컬럼 (item_id / tab / display_name_kr / display_name_en / effect_type / stat_key / curve_id / base_value / per_level_value / softcap_level / post_softcap_diminish / description / origin / notes). Sp01 W1 Drop=6열·Milestone=7열·Affix=9열과 비교해 최다 컬럼.PrestigeItemRowstruct 설계문 §2.3 은 9개 필드만 명시 — 설계상display_name_en/curve_id/description/origin/notes5개 컬럼을 SO에 어떻게 흡수할지 명시 없음. 설계 준수 시 TSV 14열 중 9열만 SO 반영 + 5열은 Importer 시점 로그만. 이 결정 자체가 W1 중 PR 리뷰 포인트.
- R-DR-06 [Medium ·
pp_cost.tsv별도 SO 이중화 우려] —prestige_pp_cost.tsv61행(헤더 제외 60행, PD README §9 "Lv100까지 샘플링"). 설계 §2.2는prestige_items.tsv만 Importer 대상으로 명시,prestige_pp_cost.tsv는 README 에서PrestigeCalculator.GetCostForLevel(int level)소비로만 언급 → W1에 SO화할지 W2에 Calculator 내장할지 결정 미명시. 기본 해석: W1 =PrestigePpCostTableSO(또는 정적 배열) 별도 Importer. 이 결정을 W1 중 발화 없이 진행하면 W2 Calculator 구현 시 병목 재발 위험. 킥오프 D-2에 PD 1줄 확인 필수.
[2026-04-21 해소] PD A2 결정 완료: (A2-1) = (a) 별도PrestigePpCostTableSO유지 (Sp01 개별 SO 패턴 계승). (A2-2 행수 gap) = False Positive. 실사 결과 TSV 데이터 행 = 61 (Lv1~50 선형 50 + Lv51 전환 마커 1 + Lv55·60·65·70·75·80·85·90·95·100 = 10 보존 레벨).prestige_items_README.md:232은 이미 "중간 레벨(51,55,60..95) 생략행" 으로 11 보존 레벨 명시하여 TSV와 일관. 본 드라이런 "헤더 제외 60행" 은 code-lead 오계수. README 수정 불필요 / TSV 수정 불필요 / T04 스코프 (a) 확정.
§0.3 사전 완화 액션 3건 (버퍼 기간, 2026-05-17 이전)
- A1 [30분, 버퍼 D-1 2026-05-17] — Sp01 W2 최종 머지된 3 Importer 의
ReadTsv/ BOM trim /Split('\t')라인 정확 좌표(파일·라인 번호) 메모 확보. #T01 리팩터 diff 사전 스케치. 코드 0줄 원칙 준수 → 메모만. - A2 [15분, 버퍼 D-1] — PD에게 1줄 질의: "
prestige_pp_cost.tsv는 (a) 별도PrestigePpCostTableSO+ Importer 인가 (b)PrestigeCalculator내장 정적 배열인가 (c)PrestigeItemCatalogSO의 보조 필드인가". 1줄 답 받으면 #T04 스코프 확정. 현 드라이런은 (a) 가정 (가장 방어적). - A3 [20분, 버퍼 D-1] —
d8-stat-key-validation-2026-04-21.mdImporter 매핑표(6행) 인쇄/고정. #T07 테스트 작성 시IdleYieldPct→IdleRateMul매핑 누락 감지 레일. Sp01 드라이런 A3(Data 어셈블리 신규 파일 체크리스트) 재활용 + 1항목 추가.
§1. Sprint 02 W1 태스크 도출 (PM 추정 공백 해소)
§1.1 도출 근거
- 로드맵 §5 W5 (2026-05-18): "프레스티지 30항목 수치 시트 + TsvReader 공통화" — 2축 명시.
- Sp02 W2 tech-sketch §2.5 : "Sprint 02 W1 PR 순서: 1.
TsvReader.cs공통화 / 2.PrestigeItemImporter.cs신규" — 2축 순서 확정. - prestige_items_README.md §1:
prestige_items.tsv+prestige_pp_cost.tsv+prestige_effect_matrix.tsv3개 TSV 중 앞 2개가 code-lead 소비, 3번째는 game-designer 검증용. - d8 stat_key validation: Importer 매핑 +
GetIdleCapHours헬퍼 스펙 확정 → W1/W2 어느 단계에 구현할지 미명시. - game-designer 수치 시트: Sprint 02 W1 시작 시점에 이미 TSV 3종 APPROVED (2026-04-21 PD 승인). W1 중 game-designer 는 다음 스프린트(Sp03) 선행 작업 가능 상태.
§1.2 Sp02 W1 태스크 7건 추정 테이블
| # | 제목 | 담당 | 예상 공수 | 선행 | 산출물 |
|---|---|---|---|---|---|
| #T01 | TsvReader.cs 공통화 + Sp01/Sp00 Importer 4종 호출 전환 (회귀 0 유지) | code-lead | 3.0h | (없음) | Editor/Importers/Shared/TsvReader.cs 1개 신규 + TranscendentStageImporter.cs / DropRateTableImporter.cs / MilestoneRewardImporter.cs / AffixPoolImporter.cs 4 파일 minimal diff |
| #T02 | PrestigeTab / PrestigeCurveId / PrestigeEffectType / PpChannel enum 4종 선언 | code-lead | 0.75h | (없음) | Assets/_Project/Scripts/Data/Prestige/PrestigeEnums.cs 1개 (또는 분할 2파일) |
| #T03 | PrestigeItemCatalogSO + PrestigeItemRow struct (30 row 저장용) | code-lead | 1.5h | #T02 | Assets/_Project/Scripts/Data/Prestige/PrestigeItemCatalogSO.cs 1개 + .asset 1개 (Import 후) |
| #T04 | PrestigePpCostTableSO 별도 SO + 60 row 저장 또는 PrestigeCalculator 정적 배열 (A2 결정 대기) | code-lead | 1.5h | #T02 (enum) | SO 1개 + .asset 1개 또는 정적 상수 1개 (결정 결과에 따라 가변) |
| #T05 | PrestigeItemImporter.cs — 30행 Import + §6 5개 자기검증 CP-T1~T5 | code-lead | 2.5h | #T01, #T02, #T03 | Assets/Editor/Importers/PrestigeItemImporter.cs 1개 + 30 row .asset 주입 + Addressables Prestige/ItemCatalog 등록 |
| #T06 | PrestigePpCostImporter.cs (A2 결정이 (a) 일 때만) — 60 row Import + 단조 증가 자기검증 | code-lead | 1.0h | #T01, #T02, #T04 | Assets/Editor/Importers/PrestigePpCostImporter.cs 1개 + .asset + Addressables Prestige/PpCostTable |
| #T07 | GodBlade/Data/Import ALL 메뉴 확장 (Sp01 W1 #05 재편집) + stat_key 매핑 상수 사전 배치 | code-lead | 0.75h | #T05, #T06 | RewardImportAll.cs minimal edit + PrestigeStatKeyMap.cs 1개 (d8 매핑 6행 하드코딩) |
| (참고) | Sp02 W1 테스트 작성은 W2 이월 — 테스트 asmdef GodBlade.Tests.Editor 는 Sp01 W2 신설 완료, W2에서 PrestigeCalculator 등장 후 테스트 묶음 7건 작성 | — | — | — |
총 공수: 11.0h (A2=(b) 시) ~ 13.0h (A2=(a) 시)
로드맵 §5 추정 12~15h 밴드와 정합: #T04 결정이 (a) 이면 13.0h (밴드 하한 근처), (b) 이면 11.0h (밴드 미달 → W1 여유 발생, W2 선행 가능).
§1.3 태스크 순차 그래프
#T01 (TsvReader 공통화) ──┐
├──> #T05 (PrestigeItemImporter) ─┐
#T02 (enum 4종) ──> #T03 (CatalogSO) ──┘ │
├──> #T07 (ALL 메뉴 + stat_key 매핑)
#T02 ──> #T04 (PpCostTableSO) ──> #T06 ──┘
- #T01 은 반드시 첫 날 단독 PR. #T02~#T06 는 #T01 머지 이후 병렬 작성 가능하지만 1인 파트타임 환경상 순차 권장.
- #T04 / #T06 은 A2 결정에 따라 축소 가능 — (b) 채택 시 #T04 = 0.5h (정적 배열만) / #T06 = 제외.
§1.4 TSV 실사 행수 대조 (2026-04-21 시점)
| TSV | 헤더 포함 행수 | 데이터 행수 | 설계 기대 | Gap |
|---|---|---|---|---|
prestige_items.tsv | 31 | 30 | 30행 (Offense 10 + Defense 10 + Utility 10) | ✅ |
prestige_pp_cost.tsv | 62 | 61 | 60행 (Lv1~100 비선형 샘플링) | ⚠️ +1 |
prestige_effect_matrix.tsv | 11 | 10 | 빌드 시뮬 (PD 검증, code-lead 소비 안 함) | N/A |
⚠️ prestige_pp_cost.tsv 61 데이터행 vs README §0 TL;DR "Lv100 누적 102,500 PP" 단일 언급. README §9 ASCII 그래프는 Lv1/5/10/20/28/50/65/85/100 등 비선형 샘플링 지시 → 60행이 정상이나 61행 관찰. 드라이런 시점 추가 확인 불가(코드 0줄 원칙). #T04/#T06 착수 시 TSV 원본 첫 검증에서 행 수 기대값 재확정 필요 — game-designer 1줄 확인 + 설계 기대값 명시 (A2 의사결정과 동반).
§2. 태스크 #T01 — TsvReader.cs 공통화
§2.1 예상 Happy Path (30~60분 단위)
- [20분] Sp01 W2 최종 머지 상태 4 Importer 열람 (
TranscendentStageImporter.cs/DropRateTableImporter.cs/MilestoneRewardImporter.cs/AffixPoolImporter.cs). 각자private struct Row/ReadTsv/ValidateHeader3개 중복 함수 좌표 기록. - [30분]
Editor/Importers/Shared/TsvReader.cs신규 생성.namespace GodBlade.EditorTools(Sp01 W1 네임스페이스 컨벤션 재사용).public static class TsvReader정의 — 설계 §2.5 시그니처 준수:
public struct Row { string Get(string k); int I(string k); float F(string k); double D(string k); bool TryGet(string k, out string v); }
public static List<Row> Read(string path, string[] expectedHeaders); // BOM trim + ValidateHeader 포함
- [15분]
Row내부는Dictionary<string, string>+ 생성자에서 헤더 index 매핑.F는float.Parse(v, CultureInfo.InvariantCulture)강제. - [15분]
TsvReader.ReadInternal—File.ReadAllLines+\uFEFFBOM trim(첫 행만) + 빈 행 skip +Split('\t')+cells[c].Trim()+ 헤더 개수 검증. - [30분]
TranscendentStageImporter.cs편집: 내부Row/ReadTsv/ValidateHeader3개 메서드 삭제, 호출부를TsvReader.Read(path, expectedHeaders)로 변경. 모든 로직 나머지 불변. - [30분] 동일 편집을
DropRateTableImporter.cs/MilestoneRewardImporter.cs/AffixPoolImporter.cs3 파일에 순차 반복. 각각 5~10분. - [15분] Unity 에디터 포커스 복귀 → Console 에러 0 확인 + 4 Importer 순차 실행 → 4개
.assetInspector 재생성 (이전과 동일한 row 수 + 동일 합 검증). - [15분]
GodBlade.Tests.Editor에TsvReaderTests.cs4개 assert 작성 —Row.Get,Row.I,Row.F, BOM 트림 1회만 수행.
총 2.8h 예상 (설계 3.0h 추정과 정합).
§2.2 예상 블로킹·회귀 리스크
| 리스크 | 심각도 | 근본 원인 | 재현 조건 | 대응 |
|---|---|---|---|---|
| ⭐ 4 Importer 전체 회귀 발생 | High | 중복 제거 과정에서 ReadTsv 내부 Trim / Split 미묘한 동작차 (특히 Sp00 Importer의 ResolveTsvPath 절대경로 해석) | 복제 시 세부 라인 누락 | #T01 단독 PR + 실행 로그 4건 비교 (row 개수 + Addressables 엔트리 변경 없음). 개별 Importer 별 git diff minimal 유지 |
Row 타입 asmdef 경계 | Low | TsvReader.Row 는 Editor 어셈블리 public struct. Runtime asmdef에서 참조 시 CS0234 | 설계상 Runtime 접근 없음 | Sp02 W2 Calculator는 TsvReader 소비 안 함 (Row 타입은 Editor 전용). 룰 유지 |
float.Parse 로케일 중복 처리 | Medium | Sp00 ~ Sp01 Importer 각자 CultureInfo.InvariantCulture 부여 — 공통화 후 Row.F 에 흡수되면 기존 Importer의 float.Parse 호출부가 정리되어야 함 | 호출부 덜 정리 | Sp01 드라이런 §3.2 경고 재활용. Row.F 내부만 invariant. 호출부의 float.Parse 모두 제거 검증 (grep float.Parse → Shared/TsvReader.cs 1건만 잔존) |
ValidateHeader 커스터마이즈 포기 우려 | Low-Medium | Sp01 3 Importer 각자 헤더 이름·개수 다름(Drop=6, Milestone=7, Affix=9). 공통 expectedHeaders: string[] 매개화로 흡수 가능하나 헤더 검증 실패 시 오류 메시지 Importer별 컨텍스트 유지 어려움 | 일반화 과도 | Read 반환 전 헤더 미스매치 발견 시 ArgumentException 에 TSV 파일명 + expected/actual 포함 메시지. Importer 호출부에서 try/catch + DisplayDialog 처리 |
| CS0579 / InternalsVisibleTo | Zero | TsvReader 는 Editor asmdef, Data asmdef 건드리지 않음 | — | 리스크 없음 |
Unity.ResourceManager 참조 | Zero | Addressables API 미사용 | — | 리스크 없음 |
Sp00+Sp01 회귀 3패턴 재현 가능성:
- CS0246 (Unity.ResourceManager): Zero (TsvReader 는 Unity 표준
System.IO.File만 사용) - CS0579/CS1061 (InternalsVisibleTo 중복): Zero (신규 SO 없음)
- TSV 경로 drift: Low (경로 해석 로직은 호출부에 잔존, TsvReader 는 path 인자만 받음)
§2.3 선결 조건 체크
- Sp01 W2 최종 머지 상태 실측:
DropRateTableImporter.cs/MilestoneRewardImporter.cs/AffixPoolImporter.cs3 파일 Green 확인 - Sp00
TranscendentStageImporter.cs:156ReadTsv메서드 존재 확인 (이미 Sp01 드라이런 §3.1 확인됨) Editor/Importers/Shared/폴더 미존재 →Directory.CreateDirectory불필요 (Unity가.meta생성)GodBlade.Editor.asmdefreferences 배열 변경 없음 (TsvReader 는 기존 asmdef 소속)GodBlade.Tests.Editorreferences 에GodBlade.Editor추가되어 있는지 확인 (TsvReaderTests.cs 가 TsvReader 호출)
§2.4 Rollback 지점
- git commit 단위: #T01 단독 PR 강제. Phase 1 (TsvReader 신규 생성) 1커밋 → Phase 2 (4 Importer 순차 호출부 전환) 4커밋 (Importer별 1커밋) → 전체 PR. 5커밋 체인 권장.
- 파일 단위: 실패 시
TsvReader.cs삭제 + 4 Importer 각자 이전 상태 복원 — git revert 5개 필요. 따라서 PR 머지 전 4 Importer 실행 결과 재검증 반드시. - 완료 체크 수준: Unity 에디터
GodBlade > Data > Import ALL메뉴 1회 실행 → Sp01 W1 #05RewardImportAll.ImportAll()가 4 Importer 전부 실행 → 4개.asset(TranscendentStageCatalog / DropRateTable / MilestoneRewardCatalog / AffixPool) 이전과 동일한 row 수 + 동일 내용 유지. Console sum=1.000 로그 + 22 row + 6 row 로그 재확인.
§3. 태스크 #T02 — Prestige enum 4종 선언
§3.1 예상 Happy Path
- [15분]
Assets/_Project/Scripts/Data/Prestige/폴더 신규 생성 (Unity Project 창 또는 파일 시스템). - [10분]
PrestigeEnums.cs신규 생성.namespace GodBlade.Data.Prestige명시 (설계 §2.3 + CP-M06). - [15분] enum 4종 선언:
PrestigeTab : byte { Offense = 0, Defense = 1, Utility = 2 }PrestigeCurveId : byte { LinearThenLog = 0, FlatCapped = 1, FlatSteps = 2 }(README §3.1 3갈래)PrestigeEffectType : byte { PercentStat = 0, Multiplier = 1, FlatStat = 2 }(README §3.3 3분기)PpChannel : byte { Permanent = 0, Seasonal = 1 }— ★ 주의: 설계 §1.3은PpChannel을GodBlade.Runtime.Prestige에 배치. Data 어셈블리에 둘 수 없음 (CP-M13 위반) → PrestigeEnums.cs에서 제외, 별도 파일Assets/_Project/Scripts/Runtime/Prestige/PpChannel.cs에 분리. 단순 enum 선언도 asmdef 경계 위반 시 CS0246.
§3.2 예상 블로킹·회귀 리스크
| 리스크 | 심각도 | 근본 원인 | 재현 조건 | 대응 |
|---|---|---|---|---|
⭐ PpChannel asmdef 경계 위반 | Medium | 설계 §1.3 PpChannel = GodBlade.Runtime.Prestige, PrestigeItemRow = GodBlade.Data.Prestige. 관성적으로 PrestigeEnums.cs에 4개 다 선언 시 CP-M13 위반 | 첫 작성 때 한 파일 몰아넣기 유혹 | A3 체크리스트 1항목 추가: "⚠️ PpChannel 은 Data asmdef에 두지 말 것. Runtime/Prestige/PpChannel.cs 별도 파일" |
| CS0579 재발 (신규 Data 파일) | Medium | PrestigeEnums.cs 가 Data asmdef 2번째 파일. Sp01 W1 #02 DropRateTableSO.cs 에 이어 CP-M02 관성 위반 여지 | InternalsVisibleTo 복제 유혹 | CP-M02 최상위. 신규 Data 파일에 [assembly: InternalsVisibleTo(...)] 절대 금지 |
PrestigeEffectType vs PrestigeCurveId 혼동 | Low-Medium | README TSV: effect_type = PercentStat/FlatStat/Multiplier (3종) / curve_id = LinearThenLog/FlatCapped/FlatSteps (3종). 2축 구분. 한 enum에 섞으면 Importer 파싱 실패 | 휴먼 에러 | d8 §1.1 검증표 확인 — effect_type 분포 28/2/1, curve_id 는 README §3.1 공식 3종과 1:1 매핑 |
| rootNamespace drift | Low | Data asmdef rootNamespace = GodBlade.Data. 파일 최상단 namespace GodBlade.Data.Prestige 명시 필수 | Unity 자동 생성 네임스페이스에 의존 | 수동 namespace 선언 — 설계 §2.3 명시. CP-M06 |
Sp00+Sp01 회귀 3패턴 재현 가능성:
- CS0246: Zero (Addressables 미사용)
- CS0579 (Data 2번째 파일): Medium (InternalsVisibleTo 복제 함정)
- TSV 경로 drift: Zero (파일 I/O 없음)
- 네임스페이스 혼동: Low —
namespace GodBlade.Data.Prestige명시 +PpChannel은 Runtime 측 별도 선언 필요 (2곳 네임스페이스 구분 필수)
§3.3 선결 조건 체크
GodBlade.Data.asmdefreferences[]빈 배열 유지 확인 (enum은 다른 어셈블리 의존 없음)GodBlade.Runtime.asmdef존재 여부 확인 — Sp01 W2에서 신설되어 있어야 함 (Sp01 W2 설계 §2.3 / 드라이런 §2.2 확인). Sp01 W2 드라이런 대상 아니므로 본 드라이런 시점에 확인 불가 → A1 사전 점검 A1에 "GodBlade.Runtime.asmdef 존재 여부" 1줄 추가 필수Assets/_Project/Scripts/Runtime/폴더 존재 확인 (Sp01 W2 산출)- CP-M02 Data asmdef InternalsVisibleTo grep → 1건 유지
§3.4 Rollback 지점
- git commit 단위: 1커밋 (
feat(sp02-w1): add Prestige enum set (Tab/CurveId/EffectType) + PpChannel in Runtime). Data/Runtime 두 파일이나 의미 단위 1개로 묶음. - 파일 단위: 실패 시
PrestigeEnums.cs+PpChannel.cs2개 삭제. - 완료 체크 수준: Console 에러 0 + 4 enum 정의 Grep으로 확인.
§4. 태스크 #T03 — PrestigeItemCatalogSO + PrestigeItemRow struct
§4.1 예상 Happy Path
- [20분]
PrestigeItemCatalogSO.cs신규 생성.namespace GodBlade.Data.Prestige.[CreateAssetMenu(fileName="PrestigeItemCatalog", menuName="GodBlade/Data/Prestige Item Catalog")]. - [25분]
[System.Serializable] struct PrestigeItemRow정의 — 설계 §2.3 필드 9개 + TSV 14컬럼 중 R-DR-05 대응:
- 반영:
itemId(ushort) /tab(PrestigeTab) /name(string=display_name_kr) /statKey(string) /effectType(PrestigeEffectType) /curveId(PrestigeCurveId) /baseValue(float) /perLevelValue(float) /softCap(byte) /postSoftCapDiminish(float) - 미반영 (로그만):
display_name_en/description/origin/notes— Importer 로그에 단서 남기되 SO에는 저장 안 함 (Sprint 04 로컬라이즈에서 재도입 예정). 이 결정을 PR 본문에 명시.
- [15분]
readonly struct PrestigeItemKey : IEquatable<PrestigeItemKey>(tab + itemId 조합) — 선택. 설계 §2.3Get(ushort itemId)만 있어도 충분 — 단순화. - [20분]
[SerializeField] List<PrestigeItemRow> rows = new()+[NonSerialized] Dictionary<ushort, int> _byItemId+[NonSerialized] List<PrestigeItemRow>[] _byTab+OnEnablelazy build. - [10분]
public int Count / PrestigeItemRow Get(ushort) / IReadOnlyList<PrestigeItemRow> GetByTab(PrestigeTab)공개 API 3개 구현. - [10분] 저장 + Unity 에디터 포커스 복귀 → Console 에러 0 확인.
- [10분] 메뉴
Create > GodBlade/Data/Prestige Item Catalog실행 → 빈 SO 생성 → Inspector 열어rows: []확인 (CP-M14 기본값 초기화 검증).
§4.2 예상 블로킹·회귀 리스크
| 리스크 | 심각도 | 근본 원인 | 재현 조건 | 대응 |
|---|---|---|---|---|
| ⭐ CS0579 재발 (Data 3번째 파일) | Medium | Sp02 W1 Data asmdef 3번째 신규 SO (Sp01 W1 3개 + PrestigeEnums + 본 파일). 피로도 누적. CP-M02 최우선 | InternalsVisibleTo 복제 | A3 체크리스트 매 신규 파일 확인. Grep 1회 유지 |
_byItemId Dictionary NRE (CP-M14) | Medium | rows 가 null 인 상태로 Inspector 열면 OnEnable 에서 rows.Count NRE | List<PrestigeItemRow> rows; 기본값 미지정 | = new() 필수. CP-M14 명시 |
| TSV 14컬럼 vs SO 10필드 결정 공백 | Medium (R-DR-05) | 설계 §2.3 필드 9개 예시만. 14컬럼 중 5컬럼 (display_name_en/description/origin/notes) 흡수 정책 미정 | 독단 결정 시 PR 리뷰 충돌 | 본 드라이런이 제안: SO에 미저장 + Importer 로그만. Sprint 04 로컬라이즈 시 PrestigeItemLocalizationSO 별도 신설. PR 본문에 결정 1줄 |
PrestigeItemRow blittable 검증 | Low | string name / string statKey 포함 → blittable 아님 (string은 managed). 설계 §1.3은 PrestigeSlot 만 blittable 요구. PrestigeItemRow 는 SO 저장용 → blittable 불필요. 혼동 주의 | 설계 재독해 필요 | DOTS 전환 시 Catalog는 string → FixedString64Bytes 전환 예정 (Sp03+), 현 W1 범위 밖 |
softcap_level = 5 고정 vs byte 변수 | Low | README §2 "일률 Lv5" 결정 + 설계 §2.3 softCap byte. TSV 값이 다른 행이 있으면 CP-T3 경고 로그 | game-designer 튜닝 시 일부만 변경 | Importer CP-T3 (경고 수준) 로 흡수. SO 필드는 byte 유지 |
Sp00+Sp01 회귀 3패턴 재현 가능성:
- CS0246: Zero
- CS0579 (Data 3번째 파일, Sp02 첫 SO): Medium — 피로도 축적 상태. CP-M02 grep 필수
- TSV 경로 drift: Zero (SO는 파일 I/O 없음)
- 네임스페이스 혼동: Low (CP-M06:
GodBlade.Data.Prestige)
§4.3 선결 조건 체크
- #T02
PrestigeTab/PrestigeCurveId/PrestigeEffectType확정 GodBlade.Data.asmdefreferences[]유지Assets/_Project/Data/Prestige/출력 폴더 미존재 → Importer에서 생성- CP-M14 기본값
= new()미리 메모 (A3 체크리스트 포함)
§4.4 Rollback 지점
- git commit 단위: 1커밋 (
feat(sp02-w1): add PrestigeItemCatalogSO + PrestigeItemRow (10 fields from 14-col TSV)). - 파일 단위: 실패 시
PrestigeItemCatalogSO.cs1개 삭제. 다른 파일 무관. - 완료 체크 수준: Inspector 빈 SO 열람 +
rows: []+Count: 0표시.
§5. 태스크 #T04 — PrestigePpCostTableSO (A2 결정 (a) 가정)
§5.1 예상 Happy Path (A2 = (a))
- [15분]
PrestigePpCostTableSO.cs신규 생성.namespace GodBlade.Data.Prestige. - [10분]
[System.Serializable] struct PrestigePpCostRow { byte level; int costPp; int cumulativePp; }— 3필드, blittable 가능. - [15분]
[SerializeField] List<PrestigePpCostRow> rows = new()+[NonSerialized] int[] _cumulativeByLevel(1..100 직접 인덱스) +OnEnable에서 비선형 샘플링 보간 —rows가 60행 비연속이므로 Lv1..100 빈 구간 선형 보간 필수. README §9 ASCII 그래프 지시. - [20분] public API:
public int GetCumulative(byte level)/public int GetCost(byte level)/public byte LevelFromCumulative(int investedPp)(이진 탐색). Calculator 시그니처 §3.3 보조. - [10분]
[CreateAssetMenu]+ 빈 SO 생성 테스트.
§5.2 A2 결정 (b) = Calculator 내장 정적 배열 시 축소판
- [15분]
PrestigeCalculator.cs내부static readonly int[] _cumulativePp = { 1, 3, 6, 10, 15, 22, ... };(Lv1~100 직접 하드코딩 100개 값) - [10분] README §9 ASCII 그래프 값 수동 입력 — TSV 60행에서 Lv1..100 보간 수치 복사
- 장점: SO 1개 줄어듦 / Addressables 엔트리 줄어듦
- 단점: 튜닝 시 game-designer TSV 수정 → code-lead 코드 재컴파일 → "시그니처 불변 원칙(README §3.3)" 위배. (a) 가 안전
§5.3 예상 블로킹·회귀 리스크
| 리스크 | 심각도 | 근본 원인 | 재현 조건 | 대응 |
|---|---|---|---|---|
| ⚠️ A2 결정 미확정 시 W1 중 삽질 | High | PD 1줄 확인 없이 (a)/(b) 독단 결정 시 PR 충돌 | 결정 누락 | A2 사전 완화 필수. D-2 킥오프 오전 PD 1줄 확인 |
| CS0579 재발 (Data 4번째 파일) | Medium | Sp02 첫 2개 SO 연속 신설 — 피로도 Peak | InternalsVisibleTo 복제 | CP-M02 grep |
| Lv1..100 보간 로직 오류 | Medium | TSV 60행 비선형 샘플링 (Lv1/5/10/15/20/.../100) — 중간 Lv11/12/13 등 보간 필요 | 단순 선형 보간이 README §9 그래프와 일치하지 않을 가능성 | 드라이런 권고: TSV 원본에 Lv1..100 전부 (100행) 직접 저장하는 방안 game-designer 에 1줄 질의 (A2 확인 묶음). 설계상 현 60행이라면 선형 보간 명시 |
byte level 오버플로 | Low | Lv100 까지 → byte (0-255) OK. Lv256 이상 도입 시 재설계 | 현 범위 무관 | 명시적 byte 유지 (DOTS 친화 CP-M10) |
Sp00+Sp01 회귀 3패턴 재현 가능성:
- CS0246: Zero
- CS0579 (Data 4번째): Medium (피로도)
- TSV 경로 drift: N/A (#T06에서 발생 가능)
- 네임스페이스 혼동: Low
§5.4 선결 조건 체크
- A2 PD 결정 수신 (필수)
- #T02 enum 3종 완료
prestige_pp_cost.tsv61행 관찰 → 60행 예상과 gap 1건 확인 (§1.4)
§5.5 Rollback 지점
- git commit 단위: 1커밋. A2 (b) 시 이 태스크는 #T05 Calculator 내부 통합으로 흡수 → 커밋 0건 (W2 이월).
- 파일 단위: 실패 시 SO 1개 삭제.
§6. 태스크 #T05 — PrestigeItemImporter.cs
§6.1 예상 Happy Path
- [10분]
Assets/Editor/Importers/PrestigeItemImporter.cs신규 생성.namespace GodBlade.EditorTools(Sp01 W1 #02 패턴). - [10분]
#if UNITY_EDITOR가드 +using UnityEditor; using UnityEditor.AddressableAssets; using UnityEditor.AddressableAssets.Settings; using UnityEditor.AddressableAssets.Settings.GroupSchemas;+using GodBlade.Data.Prestige; - [10분]
[MenuItem("GodBlade/Data/Import Prestige Item TSV")] public static void Import()시그니처. - [10분]
ResolveTsvPath—"../../designs/prestige_items.tsv"후보 (Sp01 패턴 복제). - [15분]
TsvReader.Read(path, new[]{"item_id","tab","display_name_kr","display_name_en","effect_type","stat_key","curve_id","base_value","per_level_value","softcap_level","post_softcap_diminish","description","origin","notes"})호출 → 30 Row 수신. - [20분] Row →
PrestigeItemRow변환:
itemId = (ushort)row.I("item_id")/tab = Enum.Parse<PrestigeTab>(row.Get("tab"))/name = row.Get("display_name_kr")/statKey = row.Get("stat_key")(trim 필수)effectType = Enum.Parse<PrestigeEffectType>(row.Get("effect_type"))/curveId = Enum.Parse<PrestigeCurveId>(row.Get("curve_id"))baseValue = row.F("base_value")/perLevelValue = row.F("per_level_value")/softCap = (byte)row.I("softcap_level")/postSoftCapDiminish = row.F("post_softcap_diminish")
- [20분] 자기검증 CP-T1~T5 (README §6):
- CP-T1 rows.Count == 30 강제
- CP-T2 tab 화이트리스트 + 탭별 카운트 10/10/10
- CP-T3 softcap_level == 5 경고 (fail 아님)
- CP-T4 item_id 0..29 연속 + 탭 범위 (Offense 0~9 / Defense 10~19 / Utility 20~29)
- CP-T5 per_level_value 범위 + post_softcap_diminish 0.15~0.50 범위
- [10분]
AssetDatabase.CreateAsset(Assets/_Project/Data/Prestige/PrestigeItemCatalog.asset). - [15분]
RegisterAddressables—FindGroup("Prestige") ?? CreateGroup(...)+entry.address = "Prestige/ItemCatalog"+SetLabel("prestige-catalog", true, true). Sp01 #02 패턴 복제. - [10분] 메뉴 실행 → Console 로그
"[PrestigeItemImporter] 30 rows (Offense 10 / Defense 10 / Utility 10), softcap=5 uniform, 0 warnings". - [10분] Inspector 열어
PrestigeItemCatalog.asset30행 육안 확인 +GetByTab(PrestigeTab.Offense)static 호출 테스트 (없으면 W2로 이월).
§6.2 예상 블로킹·회귀 리스크
| 리스크 | 심각도 | 근본 원인 | 재현 조건 | 대응 |
|---|---|---|---|---|
| ⭐ Enum.Parse 대소문자 mismatch | Medium | TSV effect_type 컬럼 "PercentStat" 그대로 + enum 값 PercentStat 일치. 문제 없음. 단 curve_id 컬럼 "LinearThenLog" 와 PrestigeCurveId.LinearThenLog 일치 필수 — PascalCase 미준수 시 ArgumentException | game-designer TSV 에 대소문자 drift | TSV 실사: README §3.1 3갈래가 LinearThenLog / FlatCapped / FlatSteps PascalCase 명시. 일치 확인 완료 |
tab enum 이름 충돌 우려 | Low | Unity 내장 Offense / Defense 동명 타입 없음 확인 | — | 무시 |
| CP-T2 탭별 카운트 실수 | Low | rows.Count(r => r.tab == PrestigeTab.Offense) LINQ 사용 시 using System.Linq; 필수 | using 누락 시 CS1061 | using 1줄 + assert |
TSV 14컬럼 Row Get 실패 | Medium | expectedHeaders 14개 정확히 일치해야 TsvReader.Read 통과 — 순서·대소문자 drift 시 ArgumentException | game-designer TSV 헤더 변경 | 헤더 표는 §6.1 step 5 고정. 변경 시 game-designer 에스컬레이션 |
| CS0579 재발 | Medium | Importer는 Editor asmdef — InternalsVisibleTo 무관. 단 신규 SO 파일(#T03)에서 중복 선언 시 CS0579 발동 | — | CP-M02 grep (매 PR) |
Addressables 그룹 중복 (Prestige) | Low | FindGroup("Prestige") 선확인 | 재실행 시 중복 | CP-M12 — Sp01 Rewards 패턴 복제 |
float.Parse 로케일 | Low | TsvReader.Row.F 내부 invariant | — | #T01 해결됨 |
Sp00+Sp01 회귀 3패턴 재현 가능성:
- CS0246: Low — Addressables Editor API 사용.
GodBlade.Editor.asmdef에Unity.Addressables.Editor이미 존재 (Sp00). 단 신규 Importer 파일이 Data asmdef에 실수로 생성되면 재발. #T05 파일 위치Assets/Editor/Importers/강제 - CS0579 (누적 5번째 SO 이후 작성 피로도 peak): Medium
- TSV 경로 drift: Medium —
../../designs/prestige_items.tsv상대경로 오해. A2 템플릿 메모 재활용 - 네임스페이스 혼동: Low —
GodBlade.EditorTools명시
§6.3 선결 조건 체크
- #T01 TsvReader 완료 + Sp00~Sp01 4 Importer 회귀 0
- #T02 enum 3종 완료
- #T03 PrestigeItemCatalogSO 완료
designs/prestige_items.tsv30행 실존 (§1.4 확인)Assets/_Project/Data/Prestige/폴더 미존재 → Importer에서 생성Assets/Editor/Importers/폴더 존재 (Sp00)
§6.4 Rollback 지점
- git commit 단위: Phase A (Importer 뼈대+TSV 파싱) + Phase B (자기검증 5개) + Phase C (Addressables) 3단 분할 권장 (Sp01 #02 패턴).
- 파일 단위: 실패 시 Importer +
.asset+ Addressables 엔트리 제거. - 완료 체크 수준: Inspector
PrestigeItemCatalog.asset30행 + AddressablesPrestige/ItemCatalog엔트리 + Console 로그 1건.
§7. 태스크 #T06 — PrestigePpCostImporter.cs (A2 = (a) 가정)
§7.1 예상 Happy Path
- [10분]
PrestigePpCostImporter.cs신규 — #T05 복제, 헤더만 다름 (level/cost_pp/cumulative_pp3열 — README §6 TSV 스키마 미상세, TSV 원본 확인 필요). - [10분]
TsvReader.Read호출 → 60 Row. - [15분] 자기검증:
level1~100 단조 증가 +cumulative_pp[n] >= cumulative_pp[n-1].cost_pp[n] == cumulative_pp[n] - cumulative_pp[n-1]연속 검증은 비선형 샘플링이므로 건너뜀 (README §6 명시). - [10분] SO 저장 + Addressables
Prestige/PpCostTable등록. - [5분] 메뉴 실행 + Inspector 확인.
§7.2 예상 블로킹·회귀 리스크
| 리스크 | 심각도 | 근본 원인 | 재현 조건 | 대응 |
|---|---|---|---|---|
| ⚠️ TSV 행수 61 vs 60 gap (§1.4) | Medium | prestige_pp_cost.tsv 헤더 제외 61행 관찰 — README 기대값 "Lv1~100 비선형 샘플링" 60인지 61인지 명시 없음 | 행수 strict == 60 강제 시 fail | 자기검증 strict == 60 대신 >= 30 && <= 100 범위 검증. game-designer 1줄 확인 후 strict 도입 |
level 컬럼 데이터 타입 | Low | byte (0-255) vs int — 설계상 byte. 오버플로 없음 | Lv255 이상 도입 시 문제 | byte 강제, Importer 에서 (byte)row.I("level") 캐스트 |
| Lv1..100 빈 구간 SO 저장 정책 | Medium | TSV 가 Lv1/2/3/4/5/10/15/20/25/... 비선형이면 SO 에 저장되는 row 도 비선형. Calculator GetCost(byte level) 호출 시 빈 구간 해결 필요 | 설계 §5 명시 없음 | A2 묶음 결정: SO는 TSV 그대로 (60행) + Calculator 에서 선형 보간. 또는 OnEnable 에서 Lv1..100 pre-compute 배열로 확장 |
Sp00+Sp01 회귀 3패턴 재현 가능성:
- CS0246 / CS0579 / TSV 경로 / 네임스페이스 — #T05 와 동일 Medium / Low 수준
§7.3 선결 조건 체크
- A2 PD 결정 (a) 수신
prestige_pp_cost.tsv실측 헤더 3열 확인 (드라이런 시점 미확인)- #T01 TsvReader 완료 / #T02 enum 완료 / #T04 SO 완료
§7.4 Rollback 지점
- git commit 단위: 1커밋 (
feat(sp02-w1): add PrestigePpCostImporter (60-row)). - 파일 단위: 실패 시 Importer +
.asset제거. - 완료 체크 수준: Inspector 60행 + Addressables 엔트리 + Console 로그.
§8. 태스크 #T07 — Import ALL 메뉴 확장 + stat_key 매핑 상수
§8.1 예상 Happy Path
- [10분]
Assets/Editor/Importers/RewardImportAll.cs열어 Sp01 W1 #05 기존ImportAll()메서드에PrestigeItemImporter.Import()+PrestigePpCostImporter.Import()2회 호출 추가. 메뉴 이름 변경:"GodBlade/Data/Import ALL (Stage → Drop → Milestone → Affix → Prestige)"(설계 §2.4). - [15분]
Assets/_Project/Scripts/Data/Prestige/PrestigeStatKeyMap.cs신규 —static class PrestigeStatKeyMap. d8 검증 문서의 6행 매핑 하드코딩:
{ "IdleYieldPct", "IdleRateMul" }
{ "GoldGainPct", "GoldMul" }
{ "ExpGainPct", "ExpMul" }
{ "DropRatePct", "DropMul" }
{ "IdleCapHoursFlat", "<helper:GetIdleCapHours>" } // 특수값 — BuildSummary 필드 아님
- [10분] public API:
public static bool TryMapToBuildSummary(string statKey, out string buildSummaryField)— Dictionary<string, string> 조회. 미매핑 키는 원본 그대로 반환 (d8 "나머지 25개 stat_key: 원본 그대로"). - [10분] 실행 테스트: 메뉴
GodBlade > Data > Import ALL클릭 → 4 + 2 = 6개 Importer 순차 실행 → Console 로그 6건.
§8.2 예상 블로킹·회귀 리스크
| 리스크 | 심각도 | 근본 원인 | 재현 조건 | 대응 |
|---|---|---|---|---|
Import ALL 중간 단계 실패 시 복구 | Low | 6 단계 중 3단계 실패하면 후속 3단계 skip? 진행? | try/catch 정책 | Sp01 #05와 동일 — 각 Import 호출 전후 try/catch (Exception e) { Debug.LogError; return; }. 중단 원칙 |
| 메뉴 priority 충돌 | Low | priority=10 (Sp01 W1 #05) 그대로 유지 | — | 변경 없음 |
PrestigeStatKeyMap asmdef 경계 | Low | Data asmdef 배치 vs Runtime asmdef — BuildSummary 필드는 Runtime, stat_key 입력은 Data (TSV). Data asmdef에 두면 Runtime이 references에 Data 포함 (Sp01 완료) → OK | Runtime 배치 시 Data 역참조 금지 규칙 위반 | Data asmdef 배치 권장. 설계 §2.3 PrestigeItemRow.statKey 도 Data 소속 |
Sp00+Sp01 회귀 3패턴 재현 가능성:
- CS0246: Zero
- CS0579 (Data 5~6번째 파일 — Sp02 W1 종반): Low (ALL 메뉴는 Data 신규 없음, PrestigeStatKeyMap만 Data)
- TSV 경로 drift: Zero
- 네임스페이스 혼동: Low
§8.3 선결 조건 체크
- #T05 / #T06 완료
- Sp01 W1 #05
RewardImportAll.cs존재 확인 - d8 검증 문서 매핑 6행 숙지 (A3 체크리스트)
§8.4 Rollback 지점
- git commit 단위: 1커밋 (
feat(sp02-w1): extend Import ALL + add PrestigeStatKeyMap (d8 mapping)). - 파일 단위:
PrestigeStatKeyMap.cs1개 +RewardImportAll.cs1 diff. - 완료 체크 수준: 메뉴 실행 → 6단계 로그 +
PrestigeStatKeyMap.TryMapToBuildSummary("IdleYieldPct", out var f)→"IdleRateMul"반환 Smoke 확인.
§9. 통합 리스크 매트릭스
§9.1 태스크 × 리스크 유형 매트릭스
값 = Low (L) / Medium (M) / High (H) / Zero (-)
| 태스크 | CS0246 재현 | CS0579/1061 재현 | TSV 경로 drift | 네임스페이스 혼동 | 범위 오버런 | 패턴 충돌 | 공수 초과 (>+50%) |
|---|---|---|---|---|---|---|---|
| #T01 TsvReader | - | - | L | L | H | L | M-H |
| #T02 enum 4종 | - | M | - | L | - | L | L |
| #T03 CatalogSO | - | M | - | L | M (R-DR-05) | - | L |
| #T04 PpCostSO | - | M | - | L | M (보간) | - | M |
| #T05 ItemImporter | L | M | M | L | - | L | M |
| #T06 PpCostImporter | L | M | M | L | - | - | L |
| #T07 ALL + StatKeyMap | - | L | - | L | - | - | L |
§9.2 리스크 합산 (태스크 단위 최대치)
| 태스크 | 최상위 리스크 | 권장 버퍼 |
|---|---|---|
| #T01 | 범위 오버런 H + 공수 초과 M-H | +1.0~2.0h |
| #T02 | CS0579 M | +0.15h |
| #T03 | CS0579 M + R-DR-05 범위 공백 M | +0.3h |
| #T04 | CS0579 M + 보간 로직 M | +0.3~0.5h |
| #T05 | CS0579 M + TSV 경로 M + 공수 M | +0.5h |
| #T06 | CS0579 M | +0.2h |
| #T07 | (낮음) | +0.1h |
총 권장 버퍼: 2.5~4.0h → W1 실공수 밴드 13.5~17.0h (도출 13.0h + 버퍼 0.5~4.0h).
§9.3 D+7 중간 점검 판정 기준
- Green: D+7 시점 #T01 + #T02 + #T03 완료 (3건 = 5.25h). 정상
- Yellow: D+7 시점 #T01 단독 완료 (3h). #T04 A2 미결정 시 W2 이월 협의
- Red: D+7 시점 #T01 미완료 → 4 Importer 회귀 0 유지 실패 → PD 에스컬레이션 + 범위 축소
§10. Sp00+Sp01 회귀 3패턴 재현 리스크 태스크별 평가
§10.1 회귀 A — CS0246 Unity.ResourceManager / Addressables 참조 누락
원인: asmdef references 배열 누락 복구분:GodBlade.Runtime.asmdef:7/GodBlade.Editor.asmdef:9
| 태스크 | 재현 확률 | 근거 |
|---|---|---|
| #T01 TsvReader | Zero | System.IO.File 만 사용 |
| #T02 enum 4종 | Zero | Unity API 0 |
| #T03 CatalogSO | Zero | ScriptableObject 표준 타입만 |
| #T04 PpCostSO | Zero | 동상 |
| #T05 ItemImporter | Low | Addressables Editor API 사용. Editor asmdef 참조 유지 확인 필수 |
| #T06 PpCostImporter | Low | 동상 |
| #T07 ALL + StatKeyMap | Zero | Addressables API 미추가 |
W1 전체 재현 확률: Low (Addressables 2종 Importer 신설이 집중 포인트).
§10.2 회귀 B — CS0579 / CS1061 InternalsVisibleTo 중복 / 오류
원인: [assembly: InternalsVisibleTo("GodBlade.Editor")] 중복 선언 (Sp00 에서 이미 발생) Sp01 드라이런 경고: SO 3개 연속 신설 시 피로도 → Medium
| 태스크 | 재현 확률 | 근거 |
|---|---|---|
| #T01 TsvReader | Zero | Editor asmdef 파일. 내부 가시성 불필요 |
| #T02 enum 4종 | Medium | Data asmdef 2번째 파일 신설. Sp01 W2 이미 3 SO 신설 후 피로도 + Sp02 재개 |
| #T03 CatalogSO | Medium | Data asmdef 3번째. 계속 상승 |
| #T04 PpCostSO | Medium | Data asmdef 4번째. peak |
| #T05 ItemImporter | Medium | Importer는 Editor asmdef (InternalsVisibleTo 불필요). 단 연관 SO 수정 시 재발 여지 |
| #T06 PpCostImporter | Medium | 동상 |
| #T07 ALL + StatKeyMap | Low | PrestigeStatKeyMap 1개 신설. 5번째 Data 파일 |
W1 전체 재현 확률: Medium (#T03, #T04, #T07 연속 3개 Data 신규 SO 파일이 peak 구간).
§10.3 회귀 C — TSV 경로 drift (Sp01 드라이런 추가 발굴)
원인: ../../designs/<file>.tsv 상대경로 오해 / 하드코딩 실수
| 태스크 | 재현 확률 | 근거 |
|---|---|---|
| #T01 TsvReader | Low | 경로 해석 로직은 호출부에 잔존. Shared 모듈은 path 인자만 받음 |
| #T02~#T04 | Zero | 파일 I/O 없음 |
| #T05 ItemImporter | Medium | 새 TSV 경로 첫 도입 (prestige_items.tsv). Sp01 ../../designs/transcendent_*.tsv 패턴 재활용하되 파일명 변경 — 오타 유혹 |
| #T06 PpCostImporter | Medium | prestige_pp_cost.tsv 두 번째 신규 경로. 관성적으로 복제 가능 |
| #T07 ALL + StatKeyMap | Zero | 경로 변경 없음 |
W1 전체 재현 확률: Medium — #T05/#T06 신규 경로 2개. A2 사전 메모(템플릿) 필수.
§10.4 회귀 D — 네임스페이스 혼동 (Sp01 드라이런 R-DR-03 재활용)
원인: Editor asmdef rootNamespace=GodBlade.EditorToolsvs 문서 표기GodBlade.Editordrift
| 태스크 | 재현 확률 | 근거 |
|---|---|---|
| #T01 TsvReader | Low | Editor 소속. namespace GodBlade.EditorTools 명시 |
| #T02 enum | Low | Data + Runtime 양쪽. CP-M06 준수 |
| #T03~#T04 SO | Low | namespace GodBlade.Data.Prestige 명시 |
| #T05~#T06 Importer | Low | namespace GodBlade.EditorTools (R-DR-03 학습 반영) |
| #T07 ALL + StatKeyMap | Low | 양쪽 모두 |
W1 전체 재현 확률: Low — Sp01 W1 학습 반영으로 모든 파일 namespace 명시 예상. 단 자동 생성 유혹은 상존 → A3 체크리스트 반영.
§10.5 재현 방지 메커니즘 총 3건
- 구조적 가드: scaffold-sync-audit §1.5 "Data asmdef 전체 grep
[assembly: InternalsVisibleTo" → 1건 유지 불변식. Sp02 W1 신규 파일 4개(enum + CatalogSO + PpCostSO + StatKeyMap) 생성할 때마다 Grep 재실행 → 1건 유지 확인. - 프로세스 가드:
shared-checkpoints.mdSprint 02 W2 서브셋 17개 전부 W1 머지 전 사전 감지 가능 (SO 신설 관련). 설계 §8 체크리스트 16개 중 CP-M01/M02/M03/M05/M06/M09/M10/M11/M13/M14 등 10개가 W1 관련. - 학습 가드: Sp01 W1 드라이런 §8 A3 체크리스트 재활용 + 1항목 추가 — "⚠️
PpChannel은 Runtime/Prestige/ 에 별도 파일"
§11. Sp01 W1 드라이런에서 학습한 교훈 Sp02 W1 적용
§11.1 교훈 1 — TSV 경로 drift
Sp01 학습: ../../designs/transcendent_*.tsv 상대경로 오해 Medium.
Sp02 적용:
- A2 템플릿 메모 재활용:
"../../designs/prestige_items.tsv"/"../../designs/prestige_pp_cost.tsv"2줄 사전 준비 - #T05/#T06 Importer에 Sp01
ResolveTsvPath로컬 헬퍼 복제 — 3 후보 경로 탐색 (Application.dataPath,dataPath/.., ProjectRoot) 패턴 유지 - #T01 TsvReader 공통화 후에도 경로 해석은 호출부 책임 (Shared 모듈은 path 인자만) — 드라이런 §2.2 명시
§11.2 교훈 2 — 네임스페이스 혼동 (GodBlade.EditorTools)
Sp01 학습: Editor asmdef 파일명 GodBlade.Editor / rootNamespace GodBlade.EditorTools drift. scaffold audit D1.
Sp02 적용:
- #T01
TsvReader.cs/ #T05PrestigeItemImporter.cs/ #T06PrestigePpCostImporter.cs3개 Editor 파일 전부 최상단namespace GodBlade.EditorTools명시 - Unity 자동 생성 "namespace GodBlade.Editor" 확인 즉시 수정
- CP-M06 PR 머지 전 grep 검증:
grep "namespace GodBlade.Editor$" Assets/Editor/→ 0건 (EditorTools 아닌 순수 Editor 네임스페이스 금지)
§11.3 교훈 3 — CS0579 InternalsVisibleTo 복제 (Sp00+Sp01 누적)
Sp01 학습: Data asmdef SO 3개 연속 신설 시 피로도. SO 3번째 (#04 AffixPool) 가 peak.
Sp02 적용:
- Sp02 W1 은 Sp01 에서 이미 3 SO 신설 후 피로도 축적 상태에서 재개 → Data 4번째(
PrestigeItemCatalogSO) / 5번째(PrestigePpCostTableSO) / 6번째(PrestigeStatKeyMap) 파일 연속 작성. Sp01 보다 위험도 증가 - A3 체크리스트 유지 + 매 신규 Data 파일 저장 직후 Grep 1회 강제
- PR 리뷰에 체크박스 1줄: "
[assembly: InternalsVisibleToGrep 결과TranscendentStageSO.cs:22단일 1건 유지 확인"
§11.4 Sp01 드라이런에서 적용 실패 우려 확인 사항
- 확인 사항: Sp01 W1 드라이런 §11 결론 "#02/#03/#04 SO 신설 시 CS0579 Medium" 실제 Sp01 W2 실행 시 재현되었는가? (드라이런 시점 = 2026-04-21, Sp01 킥오프 = 2026-05-04, 아직 실행 전)
- 본 드라이런 시점 재현 데이터 없음 → Sp02 W1 킥오프 D-1 (2026-05-17) 에 Sp01 W2 실행 결과 보고서(Sp01 회고 or sprints/sprint-01.md §5)에서 CS0579 발생 건수 재확인 필수. 발생 0건이면 Sp02 적용 난이도 Low, 1건 이상이면 High
§12. 사전 완화 액션 (최종 4건, 2026-05-17 이전)
2026-05-18 킥오프 D-1 최대 1.5시간 내 수행. 코드 0줄.
A1 — Sp01 W2 회귀 보고 확인 + asmdef/InternalsVisibleTo 사전 점검 (45분)
목적: Sp00 → Sp01 W1 → Sp01 W2 실행 누적 회귀 건수 확정 + Sp02 W1 위험도 재평가.
작업:
sprints/sprint-01.md§5 (종료 회고) 또는sprints/sprint-02.md킥오프 노트 읽기- Sp01 W2 실행 중 발생한 CS0579 / CS0246 / CS1061 건수 기록
Unity6/Assets/_Project/Scripts/Data/전수 Grep[assembly: InternalsVisibleTo→ 1건 유지 확인GodBlade.Runtime.asmdef존재 + references 확인 (#T02PpChannel배치 선결 조건)GodBlade.Tests.Editor.asmdefreferences 에GodBlade.Runtime포함 여부 확인 (Sp02 W2 테스트 대비)- 결과를
sprints/sprint-02.md§7 (현재 없음 → PM 신설 필요) 킥오프 GO 체크박스에 기록
산출: Sp02 W1 킥오프 GO / NO-GO 결정 1줄 + 회귀 누적 카운트
A2 — PD 1줄 질의 2건 (20분)
목적: R-DR-06 / §1.4 행수 gap 해소.
작업:
- Q1 (#T04 스코프): "
prestige_pp_cost.tsv는 (a) 별도PrestigePpCostTableSO+ Importer 인가 (b)PrestigeCalculator내장 정적 배열인가 (c)PrestigeItemCatalogSO의 보조 필드인가" — 1줄 답 - Q2 (
pp_cost.tsv61행): "prestige_pp_cost.tsv데이터행 61행 관찰. 기대값 60행인지, 61행이 정답인지, Lv1~100 모두 100행이 정답인지 1줄 확인" - 답변 받는 대로
designs/prestige_pp_cost.tsvREADME 섹션 또는 prestige_items_README.md 에 1줄 추가 (game-designer 작업으로 이관)
산출: Q1/Q2 답변 2건 기록
A3 — Data 어셈블리 신규 파일 체크리스트 v2 (15분)
목적: CS0579 재발 차단 + PpChannel asmdef 경계 포함.
작업:
- Sp01 W1 드라이런 §8 A3 체크리스트 4항목 + 1항목 추가:
namespace GodBlade.Data.Prestige(파일 최상단)[assembly: InternalsVisibleTo(...)]복제 절대 금지using UnityEditor금지 / 필요 시#if UNITY_EDITOR가드- blittable 필드 유지 (int/enum/float/byte/ushort/long)
- ⚠️
PpChannel은 Data asmdef에 두지 말 것 —Runtime/Prestige/PpChannel.cs별도 파일 (CP-M13)
- #T02/#T03/#T04/#T07 (Data 신규 4 파일) 작성 시 매번 확인
산출: 체크리스트 1건 (v2)
A4 — TSV 경로 상수 템플릿 메모 + stat_key 매핑표 인쇄 (10분)
목적: R-DR-02 (TSV 경로) + d8 매핑 6행 상기.
작업:
- Sp01 A2 메모에 2줄 추가:
private const string ITEMS_TSV_REL = "../../designs/prestige_items.tsv";
private const string PP_COST_TSV_REL = "../../designs/prestige_pp_cost.tsv";
- d8 문서 §1 Importer 매핑 6행 체크리스트 형태로 A3 옆에 나란히 놓기 (#T07 작성 시 참조)
산출: 경로 메모 + 매핑표 2건 (커밋 파일 아님, 에이전트 작업 공간)
§13. 특수 리스크 — struct+List hot path vs SO 카탈로그 패턴 충돌
§13.1 문제 정의
Sp01 W2 DQ1 결정: DropRateTableSO / MilestoneRewardCatalogSO / AffixPoolSO = SO 옵션 A (개별 SO, read-only 카탈로그).
Sp02 W2 Q1 결정: PlayerPrestigeState = 옵션 B (PrestigeSlot blittable struct + List<PrestigeSlot>, read-write hot path).
Sp02 W1: PrestigeItemCatalogSO 는 Sp01 W2 옵션 A 재활용 (read-only 정적 카탈로그). PrestigeSlot / PlayerPrestigeState 는 W2 에서 도입.
두 패턴이 프로젝트 구조상 의도적으로 공존하나, Sp02 W1 종반 → W2 킥오프 사이 1주 간격으로 동일 개발자(code-lead)가 두 패턴을 연속 작성. 혼동 유발 여지.
§13.2 혼동 시나리오 3건
- 시나리오 1:
PrestigeItemCatalogSO.rows(List<PrestigeItemRow>) 와PlayerPrestigeState._slots(List<PrestigeSlot>) 가 모두 List 기반 → 개발자가 W2 작성 중 "이거 SO로 하면 되잖아?" 독단 결정 가능성. 설계 §1.2 3옵션 비교표 재확인 필요. - 시나리오 2:
PrestigeItemRow(Data asmdef) vsPrestigeSlot(Runtime asmdef) — 어셈블리 다르나 파일명/네임스페이스 유사 (Prestige서브 네임스페이스 공유).using실수로 잘못된 타입 참조 시 CS0104 (ambiguous reference) 위험. - 시나리오 3:
OnEnablelazy build (Sp02 W1 SO 패턴) vsOnApplicationPause즉시 flush (Sp02 W2 State 패턴) — 생명주기 관리 2축 공존. 혼동 시 "왜 SO에서도 flush 필요하지?" 같은 오해 여지.
§13.3 완화책
- W1 PR 본문 필수 1줄: "본 PR은 Sprint 01 W2 DQ1 옵션 A (SO 카탈로그) 재활용. W2 도입 예정인
PlayerPrestigeState옵션 B (struct+List) 와 의도적 분기. 두 패턴은 다른 어셈블리·다른 성격(read-only vs read-write)." - 코드 주석 1줄:
PrestigeItemCatalogSO.cs파일 최상단 다음 주석 명시:
// read-only catalog. Runtime mutable state → see GodBlade.Runtime.Prestige.PlayerPrestigeState (Sp02 W2)
- CP-M06 강화: 네임스페이스 컨벤션
GodBlade.Data.Prestige(카탈로그) /GodBlade.Runtime.Prestige(상태) 물리적 구분. Sp02 W2 설계 §8 CP-P1 재확인 (PpChannel은 Runtime에만). - PR 리뷰 포인트 1건 추가: W2 작성 시점에 "
PrestigeSlot은 SO에 저장 금지, 반드시PlayerPrestigeState내부 List" 체크.
§13.4 충돌 리스크 판정
| 축 | Sp02 W1 (SO 카탈로그) | Sp02 W2 (struct+List) | 충돌 리스크 |
|---|---|---|---|
| 어셈블리 | GodBlade.Data | GodBlade.Runtime | Zero (물리적 분리) |
| 네임스페이스 | GodBlade.Data.Prestige | GodBlade.Runtime.Prestige | Low (서브 네임스페이스 혼동 여지) |
| 데이터 구조 | List<PrestigeItemRow> | List<PrestigeSlot> | Medium (List 패턴 동일) |
| 생명주기 | OnEnable lazy build | OnApplicationPause/Quit flush | Low-Medium (생명주기 축 다름) |
| 직렬화 | Unity SO auto | JsonUtility explicit | Low (직렬화 엔진 다름) |
| 개발자 혼동 | — | 1주 연속 작성 | Medium (W1→W2 전환 시점) |
종합: Medium. 설계상 분리는 명확하나 휴먼 에러 축에서 주의 필요. 완화책 4건 적용 시 Low로 축소 가능.
§14. TsvReader 공통화 리스크 (Sp01 Importer 3종 + Sp00 1종 = 4개 리팩터 범위)
§14.1 리팩터 범위 정량화
| 파일 | Sp01 W2 머지 상태 추정 | Read 로직 라인 수 | 편집 범위 |
|---|---|---|---|
TranscendentStageImporter.cs | Sp00 산출, 이미 Green | ~30 lines (private Row / ReadTsv / ValidateHeader) | 제거 30 lines + 호출부 1줄 교체 |
DropRateTableImporter.cs | Sp01 W1 신규 | ~25 lines (복제본) | 동상 |
MilestoneRewardImporter.cs | Sp01 W1 신규 | ~25 lines | 동상 |
AffixPoolImporter.cs | Sp01 W1 신규 | ~25 lines | 동상 |
합계: 4 파일 × ~100 lines 제거 + 4 호출부 1줄씩 교체 + 신규 TsvReader.cs ~80 lines
§14.2 최소 편집 원칙 (설계 §2.5 준수)
원칙: "Sprint 00 Importer는 동작 불변 — 새 공통 모듈을 호출하도록 최소 편집"
실행 지침:
TsvReader.Read반환 타입List<Row>가 각 Importer 의 기존Row내부 struct와 필드 interface 호환 이어야 함. 기존 Importer 에서row.Get("col")호출 패턴 유지.- 각 Importer 의
expectedHeaders배열만 남기고ReadTsv메서드 본체 삭제 →TsvReader.Read(path, expectedHeaders)호출로 교체. - 헤더 검증 로직 은
TsvReader.Read내부로 흡수. 각 Importer 는 반환값.Count만 확인.
§14.3 회귀 검증 절차 (Rollback 방지)
실행 전:
GodBlade > Data > Import ALL메뉴 1회 실행 → 4개.asset파일 Inspector 스냅샷 (row 수 + 첫 3행 내용)
실행 후 (#T01 머지 직전):
- 같은 메뉴 재실행 → 4개
.asset파일 row 수 동일 + 첫 3행 내용 동일 검증 - Addressables 엔트리 4건 주소·라벨 변경 0 (재확인)
다른 절차:
- Console 로그: Stage 200 + Drop 60 + Milestone 22 + Affix 6 = 288 row 수 합산 기록
§14.4 리팩터 오버런 시 대응
- Trigger: #T01 공수가 3.0h × 1.5 = 4.5h 초과 시
- 대응: Sp01 W1 3 Importer 만 전환 (
TranscendentStageImporter.cs는 W2 이월). 설계 §2.5 "Sprint 00 재건드림 금지" 정신은 유지하되, 공수 초과 시 Sp00 건드림 지연 으로 완화 - PD 에스컬레이션: #T01 4시간 초과 시 PM 보고 + 범위 축소 협의
§14.5 대안 — 점진적 공통화 (Plan B)
정당성: Sp01 W2 DQ3 결정은 "Sprint 02 이월" = "Sprint 02 W1 전체가 범위". 구체 완료 조건 미명시.
Plan B:
- #T01 =
TsvReader.cs만 신규 작성 (2h) - Sp01 Importer 3종 전환은 Sp02 W1 후반부 또는 Sp02 W2 초반 잉여 시간 활용
- Sp00
TranscendentStageImporter.cs은 회귀 제로 보장 불가 → Sp03 또는 그 이후 이월 - Plan B 선택 시 Sp02 W1 공수 2.5h 절감 가능
권고: Plan B 는 PM 에스컬레이션 대상. 기본은 4 파일 일괄 전환 (설계 §2.5 준수).
§15. Sp02 W1 TodoWrite 목록 제안 (7건)
2026-05-18 Sprint 02 W1 킥오프 시 PM이 TodoWrite 도구에 입력할 초안. 근거: §1.2 태스크 도출 7건 + 각 태스크 공수·선행 의존 반영. 로드맵 v2.0 §10 "비추정 공수 플래그" 해소 기여.
TodoWrite Sp02 W1 초안:
1. [T01] TsvReader.cs 공통화 + Sp00/Sp01 Importer 4종 호출 전환 (회귀 0 유지) (3.0h, 선행: 없음, 상태: pending)
2. [T02] Prestige enum 4종 선언 (PrestigeTab/PrestigeCurveId/PrestigeEffectType / PpChannel 분리) (0.75h, 선행: 없음, 상태: pending)
3. [T03] PrestigeItemCatalogSO + PrestigeItemRow struct (Data.Prestige asmdef) (1.5h, 선행: T02, 상태: pending)
4. [T04] PrestigePpCostTableSO (A2 결정 (a) 가정, (b) 시 축소) (1.5h, 선행: T02, 상태: pending, 블로커: A2 결정)
5. [T05] PrestigeItemImporter.cs — 30행 Import + CP-T1~T5 5개 자기검증 + Addressables Prestige 그룹 (2.5h, 선행: T01·T02·T03, 상태: pending)
6. [T06] PrestigePpCostImporter.cs — 60행 Import + 단조증가 검증 + Addressables (1.0h, 선행: T01·T02·T04, 상태: pending, 블로커: A2 결정)
7. [T07] Import ALL 메뉴 확장 + PrestigeStatKeyMap (d8 매핑 6행) (0.75h, 선행: T05·T06, 상태: pending)
시작 시점 3건 동시 pending 가능: T01 / T02 (병렬 가능, 독립) / A2 사전 완화 A1~A4 4건 블로킹 의존: T04/T06 은 A2 결정 의존. T05 는 T01+T02+T03, T07 은 T05+T06. PM 주간 점검 포인트:
- D+3 (2026-05-20): T01 + T02 완료 확인 (3.75h)
- D+7 (2026-05-24): T03 + T05 Phase A 까지 (Green 판정 기준)
- D+10 (2026-05-27): 전체 7건 완료 + W2 킥오프 준비
§16. 메타정보
- 작성자: code-lead (프로그래밍 리드)
- 작성일: 2026-04-21 (Sprint 00 D+1, Sprint 02 W1 킥오프 D-27)
- 감사 범위: Sprint 02 W1 예상 태스크 #T01~#T07 7건
- 입력 자료:
designs/sprint-02-w2-prestige-tech-sketch.mdv1.0 APPROVED (§8 체크 16개)designs/prestige_items_README.mdv1.0 APPROVED (§6 CP-T1~T5)designs/sprint-01-w2-importer-design.mdv1.0 APPROVED (§2.5 TsvReader 공통화 이월)sprints/shared-checkpoints.mdv1.0 (Sprint 02 W2 서브셋 17개 중 W1 관련 10개)sprints/sprint-01-dry-run-2026-04-21.mdv1.0 (Sp01 W1 드라이런 — 구조 재활용)designs/d8-stat-key-validation-2026-04-21.mdv1.0 APPROVED (Importer 매핑 6행 + GetIdleCapHours 헬퍼)sprints/phase-2-roadmap-2026-04-21.mdv2.0 §5 W5 (Sp02 W1 공수 12~15h)- 메모리:
project_sprint02_w2_prestige_tech_sketch.md/project_sprint02_w1_prestige_items.md/feedback_codelead_review_compile_verify.md - 실사 확인 파일:
designs/prestige_items.tsv헤더 14컬럼 + 30 데이터행 (§1.4)designs/prestige_pp_cost.tsv61 데이터행 (⚠️ §1.4 60 vs 61 gap)designs/prestige_effect_matrix.tsv10 데이터행 (code-lead 소비 외)Unity6/Assets/_Project/Scripts/Data/현황 (Sp00 기준) —TranscendentStageSO.cs/TranscendentStageCatalogSO.cs/GodBlade.Data.asmdefUnity6/Assets/Editor/Importers/TranscendentStageImporter.cs(Sp00 기준, 15473 bytes)- 드라이런 제약 준수:
- 실제 코드 0줄 ✅
Unity6/폴더 수정 0건 ✅- Sprint 02 설계 v1.0 APPROVED 변경 제안 0건 ✅
- 감지·권고만 ✅
- Sp00+Sp01 회귀 3패턴 태스크별 Low/Med/High 평가 ✅ (§10)
- TodoWrite 7건 제안 ✅ (§15, v2.0 로드맵 §10 비추정 플래그 해소 기여)
- 코드 작성 Write 호출: 1회 (본 파일)
- 드라이런 소요: 약 2.5시간 (독서 60분 + 분석 60분 + 문서 작성 30분)
§17. 판정 요약
2026-05-18 Sprint 02 W1 킥오프 → GO (Yellow)
- P0 블로커: 0건
- P1 완화 권장: 4건 (A1 Sp01 W2 회귀 건수 확인 / A2 PD 2건 질의 / A3 Data 체크리스트 v2 / A4 TSV 경로 + stat_key 매핑)
- Sp00+Sp01 회귀 3패턴 재현 최고 확률 포인트:
- CS0579 (InternalsVisibleTo 중복): #T03/#T04/#T07 Data 신규 4 파일 연속 작성 구간 — Sp01 누적 피로도 축적 후 재개 = Medium (Sp01 보다 상승)
- TSV 경로 drift: #T05/#T06 신규 경로 2개 도입 — Medium
- W1 실공수 예상 밴드: 13.5~17.0h (도출 13.0h + 회귀 버퍼 1.0~2.0h + TsvReader 리팩터 오버런 0.5~2.0h)
- 최대 주의 태스크: #T01 TsvReader 공통화 (범위 오버런 High, 4 Importer 회귀 0 유지 난이도 High). 단독 PR + 5커밋 체인 권장
- 휴먼 에러 최고 위험 태스크: #T02 enum 4종 (
PpChannel을 Data asmdef에 실수로 배치 — CP-M13 위반) - 패턴 충돌 특수 리스크: Medium (§13 — SO 카탈로그 vs struct+List 공존, 완화 4건 적용 시 Low)
- TodoWrite 7건 제안 완료 — v2.0 로드맵 §10 비추정 플래그 해소 기여
(끝 — v1.0, 2026-04-21 code-lead 작성)