192 lines
13 KiB
Markdown
192 lines
13 KiB
Markdown
|
|
---
|
||
|
|
from: 개발팀
|
||
|
|
to: PM
|
||
|
|
date: 2026-04-20
|
||
|
|
ref_pd_instruction: "#58 Tool_Left 버그 유무 점검"
|
||
|
|
status: 완료
|
||
|
|
tags: [#58, Tool_Left, 툴버그점검, 몬스터누락, 직렬화, 스키마마이그레이션]
|
||
|
|
관련_PD지시: "#57 A 집행 완료(IngameStageData.Init 자동 복구) · #57-B 재export 보류 · #57-C → #58 축소 재정의"
|
||
|
|
---
|
||
|
|
|
||
|
|
# Tool_Left 버그 유무 점검 보고서 (#58)
|
||
|
|
|
||
|
|
> PD 지시 #58 "#57-C는 툴 버그 유무를 개발팀에 지시해서 점검하도록 해" 집행. 원인 조사가 아닌 **툴 버그 유무 명확 판정**이 목표.
|
||
|
|
|
||
|
|
## §1. 점검 방법
|
||
|
|
|
||
|
|
### 1-1. 점검 환경 (실측 기반)
|
||
|
|
- Unity 프로젝트 루트: `D:/NerdNavis/FilGoodBandits/DeckBuilding` (git repo 확인)
|
||
|
|
- 원격 대비 최신 상태 (`git fetch origin` 후 `git status` clean, 변경은 IDE 생성 파일뿐)
|
||
|
|
- HEAD: `24578499a 몬스터 오류 수정` (= #57 A 집행 커밋, IngameStageData.Init 자동 복구 28줄 추가)
|
||
|
|
|
||
|
|
### 1-2. 점검 대상 코드 (Read 실측)
|
||
|
|
| 파일 | 줄수 | 핵심 역할 |
|
||
|
|
|------|------|----------|
|
||
|
|
| `Assets/Tool/Script/Tool_Left.cs` | 190 | `CreateStageAppearMonster` 정의 + `Add_Stage` 진입점 |
|
||
|
|
| `Assets/Tool/Script/ToolStageCard.cs` | 160 | `OnValueChange_MapConfig` → `CreateStageAppearMonster` 호출 (mapconfig 변경 시) |
|
||
|
|
| `Assets/Tool/Script/Tool_Right.cs` | 227 | 노드 저장 전 validation (Mob/Boss 노드 존재 시 `list_MobData`/`list_BossMobData` 비어있는지 체크) |
|
||
|
|
| `Assets/Tool/Script/ToolMain.cs` | 572+ | `SaveToJson` / `LoadToJson` — ToolData.json 직렬화·역직렬화 + 로드 시 테이블 존재 안 하는 몹 정리 루프 |
|
||
|
|
| `Assets/Editor/MyEditorUtil.cs` | 514+ | `Tools/ToolStageBossSetting` 메뉴 — 기존 저장분 일괄 복구 기능 |
|
||
|
|
| `Assets/Script/InGame/Stage/IngameStageData.cs` | 149 | 런타임 자료구조 · `Init()` 내 #57 A 자동 복구 로직 |
|
||
|
|
|
||
|
|
### 1-3. ToolData.json 실측
|
||
|
|
- 파일: `Assets/Resources/ToolData.json` (796,235 bytes, 2026-04-14 생성)
|
||
|
|
- 전수 파싱으로 `list_MobData`·`list_BossMobData` 상태 통계 집계 (Python JSON parser)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## §2. 3축 점검 결과
|
||
|
|
|
||
|
|
### 2-1. 축 1 — Tool_Left의 `CreateStageAppearMonster` 호출 경로
|
||
|
|
|
||
|
|
**호출부 전수 탐지 결과**:
|
||
|
|
| 호출 위치 | 트리거 | 분배 대상 |
|
||
|
|
|----------|--------|-----------|
|
||
|
|
| `Tool_Left.Add_Stage()` (119행) | `[+]` 버튼으로 스테이지 신규 추가 | 해당 신규 스테이지에만 |
|
||
|
|
| `ToolStageCard.OnValueChange_MapConfig()` (89행) | 카드 dropdown으로 mapConfigID 변경 | 해당 스테이지에만 |
|
||
|
|
|
||
|
|
**분배 로직 (Tool_Left.cs 125~152)**:
|
||
|
|
```csharp
|
||
|
|
public void CreateStageAppearMonster(IngameStageData isdata, CreateMapConfigTableData mapconfig)
|
||
|
|
{
|
||
|
|
isdata.list_MobData = new List<StageMonsterData>(); // 반드시 새 리스트로 초기화
|
||
|
|
isdata.list_BossMobData = new List<StageMonsterData>(); // 반드시 새 리스트로 초기화
|
||
|
|
|
||
|
|
var createstagemobdatas = table_ApprearMonsterPattern.Ins.Get_DataList(mapconfig.n_AppearMonsterGroup);
|
||
|
|
if (createstagemobdatas != null)
|
||
|
|
for (int i = 0; i < createstagemobdatas.Count; i++) { /* list_MobData 추가 */ }
|
||
|
|
|
||
|
|
var createstagebossdatas = table_ApprearMonsterPattern.Ins.Get_DataList(mapconfig.n_AppearBossGroup);
|
||
|
|
if (createstagebossdatas != null)
|
||
|
|
for (int i = 0; i < createstagebossdatas.Count; i++) { /* list_BossMobData 추가 */ }
|
||
|
|
|
||
|
|
if (isdata.list_BossMobData.Count == 0)
|
||
|
|
Popup.Ins.Set("보스 몬스터가 설정되지 않았습니다 ..."); // 경고 팝업
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**판정**: **호출 경로·분배 로직 모두 정상**. 신규 추가·mapConfig 변경 시 모두 테이블에서 몬스터를 읽어 정상 분배. 표 조회가 null이면 빈 리스트 유지(방어 코드 정상). `n_AppearBossGroup` 결과 비면 Popup 경고까지 띄움.
|
||
|
|
|
||
|
|
**잠재 이슈**: `CreateStageAppearMonster`는 **신규 추가 or mapconfig 변경 시에만** 호출. **기존에 이미 저장된 스테이지가 같은 mapconfig로 유지되는 동안은 본 메서드가 호출되지 않음** → 구 스키마 시절 데이터가 누적된 경우 자동 복구 트리거 없음. 이는 버그가 아니라 **설계 의도(불필요 재생성 방지)**.
|
||
|
|
|
||
|
|
### 2-2. 축 2 — Newtonsoft.Json 직렬화 시 `List<StageMonsterData>` 필드 유실 여부
|
||
|
|
|
||
|
|
**점검 방법**:
|
||
|
|
1. `IngameStageData` 필드 속성 검사: `[JsonIgnore]`·`[NonSerialized]` **0건** (모든 public 필드 직렬화 대상)
|
||
|
|
2. `ToolMain.SaveToJson` 기본 설정: `JsonConvert.SerializeObject(td)` — 기본 설정(default NullValueHandling, 빈 컬렉션 포함)
|
||
|
|
3. 실제 ToolData.json 전수 파싱 (125개 스테이지, 24개 챕터)
|
||
|
|
|
||
|
|
**실측 결과 (125 스테이지 전수)**:
|
||
|
|
| 항목 | 건수 | 비율 |
|
||
|
|
|------|------|------|
|
||
|
|
| `list_MobData` **필드 자체 누락** (JSON key 부재) | **0건** | 0% |
|
||
|
|
| `list_BossMobData` **필드 자체 누락** (JSON key 부재) | **0건** | 0% |
|
||
|
|
| `list_MobData` 필드는 있으나 **빈 배열 `[]`** | **123건** | 98.4% |
|
||
|
|
| `list_BossMobData` 필드는 있으나 **빈 배열 `[]`** | **124건** | 99.2% |
|
||
|
|
| 두 필드 모두 빈 배열 | **122건** | 97.6% |
|
||
|
|
|
||
|
|
**샘플 케이스 (Stage 1 / mapConfig `Stage1_1`)**:
|
||
|
|
```json
|
||
|
|
{ "m_Stage": 1, "mapConfigID": "Stage1_1",
|
||
|
|
"list_MobData": [],
|
||
|
|
"list_BossMobData": [{"m_Index":0, "m_MobID":10003, "m_Weight":100}] }
|
||
|
|
```
|
||
|
|
|
||
|
|
**판정**: **JSON 직렬화·역직렬화 자체는 완전 정상**. 모든 필드가 예외 없이 직렬화·저장됨. 문제는 **"빈 리스트 그대로 저장된 데이터가 존재"**라는 것이지 직렬화 유실이 아님.
|
||
|
|
|
||
|
|
### 2-3. 축 3 — JSON 스키마 마이그레이션 이력 추적
|
||
|
|
|
||
|
|
**핵심 커밋 발견**: `686a25a30` (2026-04-08, Ino 작성자)
|
||
|
|
- 제목: "CreateMapConfig 테이블에 보스 몬스터 패턴을 설정해두었지만 맵툴에는 보스 몬스터가 설정되지 않는 문제 수정 바랍니다"
|
||
|
|
- 변경: `Tool_Left.cs` 26줄 재작성 + `MyEditorUtil.cs` 56줄 신규(`Tools/ToolStageBossSetting` 메뉴) + 기타 4개 파일
|
||
|
|
|
||
|
|
**스키마 변경 내용**:
|
||
|
|
|
||
|
|
| 시점 | 분배 방식 |
|
||
|
|
|------|----------|
|
||
|
|
| **변경 전 (커밋 이전)** | 단일 테이블 `n_AppearMonsterGroup`에서 몬스터 읽고 `tdata.IsBoss()`로 list_MobData/list_BossMobData **자체 분기** |
|
||
|
|
| **변경 후 (현재)** | **두 테이블 개별 조회**: `n_AppearMonsterGroup` → list_MobData · `n_AppearBossGroup` → list_BossMobData |
|
||
|
|
|
||
|
|
`CreateMapConfig` 테이블 스키마에 `n_AppearBossGroup` 컬럼이 신규 추가됐고, 이에 맞춰 `CreateStageAppearMonster` 재구성. 동일 커밋에서 **`MyEditorUtil.cs`의 `Tools/ToolStageBossSetting` 일괄 복구 메뉴를 추가한 것은** 기존 저장분 중 `list_BossMobData`가 비어있는 스테이지를 신 스키마 기준으로 재채우기 위함 (명시적으로 "맵툴 실행 상태에서 실행" + "모든 보스가 없는 스테이지의 경우 테이블에서 읽어서 다시 세팅").
|
||
|
|
|
||
|
|
**이후 커밋 이력 관찰**:
|
||
|
|
- `045ed3176 맵툴 데이터 추가` · `a2dde619b 임시 작업물 업데이트` — ToolData.json 단순 업데이트 커밋 다수
|
||
|
|
- `410504a9a 몬스터 등장 패턴 구성 관련 요청` — 기획팀 테이블 요청 대응
|
||
|
|
- `24578499a 몬스터 오류 수정` (#57 A) — **런타임 Init()에 같은 자동 복구 로직을 편입**
|
||
|
|
|
||
|
|
즉 #57 A는 과거 Editor 메뉴(`ToolStageBossSetting`)가 했던 복구를 **런타임 진입 시점에 자동 실행**하도록 이관한 조치입니다. 툴 측은 2026-04-08 시점에 이미 복구 경로가 존재했으나, **실행자가 메뉴를 직접 누르지 않으면 기존 저장분은 그대로 유지**되는 구조.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## §3. 버그 유/무 최종 판정
|
||
|
|
|
||
|
|
### 3-1. 판정 결과: **툴 버그 없음** (3축 모두 정상)
|
||
|
|
|
||
|
|
| 축 | 기대 버그 | 실측 결과 | 판정 |
|
||
|
|
|----|-----------|----------|------|
|
||
|
|
| 1 | Tool_Left가 신규 추가/mapConfig 변경 시 `CreateStageAppearMonster` 호출 누락 | 2곳 호출·분배 로직 정상 동작 | **버그 없음** |
|
||
|
|
| 2 | Newtonsoft.Json이 `List<StageMonsterData>` 필드 유실 | 필드 자체 누락 0건. 모든 스테이지에 필드 존재 | **버그 없음** |
|
||
|
|
| 3 | JSON 스키마 마이그레이션 누락 | 2026-04-08 `686a25a30`에서 로직 이전 + 일괄 복구 메뉴 동시 제공 완료 | **버그 없음** |
|
||
|
|
|
||
|
|
### 3-2. 그럼 왜 125 스테이지 중 122건(97.6%)이 빈 배열인가
|
||
|
|
|
||
|
|
**가설 (증거 기반 해석)**:
|
||
|
|
1. **스키마 마이그레이션 시점 데이터가 주원인**: 2026-04-08 이전에 만들어진 스테이지 데이터는 구 분배 방식의 산물. 이후 스키마 변경 시 `Tools/ToolStageBossSetting` 메뉴를 **수동 실행하지 않으면 자동 재채워지지 않음**. 기획·개발 파트에서 메뉴를 실행한 스테이지(Stage 1의 list_BossMobData 등 일부 존재)만 갱신됐고 나머지는 미실행.
|
||
|
|
2. **PD님 언급 일치**: PD님이 #57-B 재export 보류 사유로 "해당 스테이지는 임시 데이터"라 말씀. 실제로 125 스테이지 중 **거의 전부가 빈 몬스터 배열** → "미완성 임시 데이터" 성격.
|
||
|
|
3. **기획·테이블 운영 방식 영향 가능**: 빈 배열 상태는 Popup 경고도 띄우지 않음(`Count == 0`은 `list_BossMobData`만 경고. 비어있는 `list_MobData`는 경고 없음). 기획 단계에서 **노드 생성 직전에야 Tool_Right 검증 다이얼로그**로 경고가 뜸 — "나중에 채워도 된다"는 운영 패턴 허용 구조.
|
||
|
|
|
||
|
|
### 3-3. 기존 조직 자산 확인 (C31-E 준수)
|
||
|
|
|
||
|
|
본 건은 #57 A에서 이미 **런타임 자동 복구 로직**을 투입하여 "빈 배열이어도 게임 실행 시 자동 채움" 구조로 전환된 상태. 현재 정상 동작 중이며 추가 툴 버그 수정은 **필요하지 않음**.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## §4. 수정 제안 (버그는 없지만 운영 개선 여지)
|
||
|
|
|
||
|
|
버그는 없지만, PD님 결정을 돕기 위해 **발견된 설계·운영상 관찰점**을 4가지 옵션으로 제시합니다. **선택적 개선안이며 현 시점 즉각 집행 대상 아님** (PD 결정 영역).
|
||
|
|
|
||
|
|
### 4-1. 관찰점 (현 상태 유지도 무방)
|
||
|
|
|
||
|
|
1. **`list_MobData.Count == 0` 상태에 경고 누락**: `CreateStageAppearMonster`가 `list_BossMobData.Count == 0`일 때만 Popup으로 경고하고, `list_MobData`가 비면 경고 없음. 기획자가 인지 못 한 채 스테이지 저장 가능 → Tool_Right.cs 저장 직전 validation에서 걸러지긴 함.
|
||
|
|
2. **`ToolStageBossSetting` 메뉴의 대칭 메뉴 없음**: Boss 일괄 복구 메뉴는 있으나 **일반 몬스터 일괄 복구 메뉴는 부재**. 위 데이터 98.4% 비어있는 주 원인.
|
||
|
|
3. **런타임 Init() 자동 복구(#57 A)와 툴 저장 상태의 gap**: 런타임에선 자동 채워지나 **ToolData.json 자체는 여전히 빈 배열** → 기획팀 툴 화면에서는 여전히 "0건"으로 표시(ToolStageCard.cs:31~32) → 기획 파악 혼선 가능성.
|
||
|
|
|
||
|
|
### 4-2. 개선 옵션 (PD 판단 영역 — 본 Task 범위 외)
|
||
|
|
|
||
|
|
| # | 옵션 | 비용 | 효과 |
|
||
|
|
|---|------|------|------|
|
||
|
|
| A | **현 상태 유지** (#57 A 런타임 복구로 충분) | 0 | 런타임 안전. 툴 표시만 "0건"으로 남음 |
|
||
|
|
| B | `MyEditorUtil.cs`에 "list_MobData 일괄 복구 메뉴" 추가 + 한 번 수동 실행 | 소규모 | ToolData.json 실제 데이터 정상화 (1회성) |
|
||
|
|
| C | `ToolMain.LoadToJson` 시점에 `IngameStageData.Init()` 자동 호출 → 저장까지 연동 | 중규모 | 툴 로드 즉시 자동 복구 + 저장 (사용자 개입 불요) |
|
||
|
|
| D | `CreateStageAppearMonster`에 `list_MobData.Count == 0` 경고도 추가 + 기획 가이드 문서화 | 소규모 | 신규 추가 시 누락 예방 |
|
||
|
|
|
||
|
|
권장 순서: **A 유지 → 장기적으로 C 검토** (C는 "자동 복구" 설계를 툴 영역까지 일관 확장하는 근본 개선).
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## §5. 후속 권고
|
||
|
|
|
||
|
|
### 5-1. 수정 범위 판정
|
||
|
|
- **본 Task(#58) 범위**: 점검만. 수정 집행 없음. (지시 명시 사항)
|
||
|
|
- **추가 수정 필요 시**: §4-2 옵션 중 PD님 선택에 따라 별도 지시로 집행. 개발팀 자율 집행은 C36 관점에서 방향·원칙 수준 아닌 구현 수준이므로 PM 재량 가능하나 **현 상태에서 필요성 낮음**
|
||
|
|
|
||
|
|
### 5-2. 기획팀 협업 필요 여부
|
||
|
|
- **불필요**: 런타임 동작은 #57 A로 이미 안전. 기획팀 추가 확인 사항 없음
|
||
|
|
- **선택적 공유**: 기획팀이 툴 화면에서 "0건" 표시를 이상하게 느낀다면 §4-1의 3번 관찰점을 공유하여 인지 제공 정도
|
||
|
|
|
||
|
|
### 5-3. 조직 기억 축적
|
||
|
|
- **feedback 메모리 신설 불요**: 본 건은 PD님 직접 지시 완료 집행이므로 #58 자체가 조직 기억. 별도 feedback 불필요
|
||
|
|
- **대화로그 기록**: 개발팀 대화로그에 본 점검 결과 1줄 엔트리 추가 (PM이 별도 집행)
|
||
|
|
|
||
|
|
### 5-4. PM에게 전달 요지 (1문장)
|
||
|
|
**Tool_Left 3축 모두 정상 동작, 툴 버그 없음 판정. 빈 배열 저장분은 2026-04-08 스키마 변경 시점에 수동 복구 메뉴 미실행으로 남은 잔재이며 #57 A 런타임 자동 복구로 실질 영향 해소됨. §4-2 개선 옵션은 PD 결정 영역으로 제출.**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 참조
|
||
|
|
|
||
|
|
- PD 지시 #57 (완료): `공유/소통/완료/2026-04-20_몬스터_미등장_A_집행완료.md`
|
||
|
|
- 본 보고 매니페스트: `$HOME/.claude/nerdnavis-audit/manifest/active/2026-04-20_58_툴버그점검.md`
|
||
|
|
- Unity 프로젝트 HEAD: `24578499a` (2026-04-20 #57 A 집행)
|
||
|
|
- 스키마 마이그레이션 커밋: `686a25a30` (2026-04-08)
|