Initial sync: 너드나비스 조직 전체 자산 (v2 §3 인벤토리 기준)
- 루트: CLAUDE.md + pm-general 에이전트
- 공유/: PD 지시 트래킹, 일일보고, 공통_업무_규칙(C1~C15 + P1~P20 + 부록 A SOT), 조직공지, 부서간 REQ
- 개발실/: CLAUDE.md(C14-4 SOT 참조 전환), 에이전트·커맨드, 코어_설계(_skeleton 제외), 프로젝트 숙지 10종, 조직공지
- 기획실/: CLAUDE.md(C14-4 SOT 참조 전환), 에이전트·스킬모듈, 밸런싱 .md, Phase 3 HOLD 공지
- memory/org/: 사용자 메모리 6종 (외부 ~/.claude/projects/*/memory/ 사본)
- setup/: Windows·macOS 셋업 스크립트
- 제외: Unity·*.xlsm·*.sqlite·settings.local.json·data/·.cache/·_skeleton/
C14-4 참조 무결성 정리: '작업 시점별 자동 환기 메모'를 공통_업무_규칙.md 부록 A(SOT)로 단일화, 개발실/기획실 CLAUDE.md는 참조 링크로 전환.
PD 지시 #7 Phase 1 착수. push는 PAT 수신 후 실행 예정.
2026-04-14 16:40:28 +00:00
|
|
|
# 10. 데이터 테이블 로딩 · 캐싱 구조 v1
|
|
|
|
|
|
|
|
|
|
- 작성일: 2026-04-14
|
|
|
|
|
- 작성자: 개발실장 (Explore 에이전트 분석 위임)
|
|
|
|
|
- 목적: 기획실 엑셀(.xlsm) SOT가 Unity 런타임에 닿기까지의 **로딩·캐싱·조회·보안·버전관리** 구조 확정
|
|
|
|
|
- 스코프: `Assets/Script/Table/`, `Assets/ResWork/Table/Export/`, `MyClass.cs` 내 베이스 타입
|
|
|
|
|
- 선행: `08_전투시스템_SOT_v1.md`, `09_카드시스템_아키텍처_v1.md`
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 1. 로더 아키텍처
|
|
|
|
|
|
|
|
|
|
### 1.1 베이스 계층
|
|
|
|
|
|
|
|
|
|
| 타입 | 파일 | 역할 |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `table_base` (MonoBehaviour) | `Assets/Script/Table/table_base.cs` (1~27) | TextAsset → json 문자열 캐시, LoadComplete 플래그, 문자열 값 파서 |
|
|
|
|
|
| `TableDataBase` | `Assets/Script/My/MyClass.cs:23~45` | `Get_Name`, `Get_Desc`, `Get_ImagePath`, `Get_Value` 공통 인터페이스 |
|
|
|
|
|
| `MissionTableDataBase` | `Assets/Script/My/MyClass.cs:137~145` | 미션·업적 공통 필드 |
|
|
|
|
|
| `MonoBehaviourSingletonTemplate<T>` | `Assets/Script/Template/MonoBehaviourSingletonTemplate.cs` | `public static T Ins` / `public static bool isIns` / Awake에서 자기 주입 |
|
|
|
|
|
|
|
|
|
|
### 1.2 초기화 라이프사이클
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Awake: json_last = m_json.text; // 문자열만 유지
|
|
|
|
|
Resources.UnloadAsset(m_json); // TextAsset 객체는 언로드
|
|
|
|
|
Start: tableDatas = JsonConvert.DeserializeObject<List<T>>(json_last);
|
|
|
|
|
// Dictionary 인덱스 구축
|
|
|
|
|
LoadComplete = true;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- JSON 라이브러리: **Newtonsoft.Json** (`using Newtonsoft.Json;` 전 테이블 공통)
|
|
|
|
|
- 모든 테이블이 `Start()`에서 병렬적으로 역직렬화. `TableChecker.CheckAllLoad()`로 완료 확인 (`TableChecker.cs:12~22`).
|
|
|
|
|
- 타이틀/인게임 진입 시 `while (!TableChecker.Ins.CheckAllLoad()) yield return null;` 으로 블로킹 대기 (`Title_Mgr.Co_Check()` · `InGameInfo.Start()`).
|
|
|
|
|
|
|
|
|
|
### 1.3 메모리 레이아웃
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
TextAsset JSON
|
|
|
|
|
→ string json_last
|
|
|
|
|
→ List<T> tableDatas // 순차 접근
|
|
|
|
|
→ Dictionary<Key, T> dic_* // O(1) 조회 (ID·Enum·등급 등 다중 인덱스)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
예: `table_cardlist` 는 `tableDatas`, `dic_gradeData`, `dic_Data`(eCardType), `dic_Data_byID`(int) 4중 인덱스 유지 (`table_cardlist.cs:451~454`).
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 2. 조회 API 패턴
|
|
|
|
|
|
|
|
|
|
### 2.1 권장 패턴 — `Get_*_orNull`
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
public ActorListTableData Get_Data_orNull(string key)
|
|
|
|
|
=> dic_Data.ContainsKey(key) ? dic_Data[key] : null;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 2.2 폴백 메시지 패턴
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
// table_localtext
|
|
|
|
|
public string Get_Talk(int patternid)
|
|
|
|
|
=> dic_Data.ContainsKey(patternid) ? /* ... */ : $"No ActorTalk {patternid}";
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 2.3 위험 패턴 — Direct 인덱서
|
|
|
|
|
|
|
|
|
|
```csharp
|
|
|
|
|
// table_cardlist
|
|
|
|
|
public CardListTableData Get_Data(eCardType type) => dic_Data[type]; // KeyNotFoundException 가능
|
|
|
|
|
// table_GlobalValue
|
|
|
|
|
public int Get_Int(string id) => dic[id]; // 동일 위험
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
→ **리스크**: 문자열 키 오타, 미등록 카드 추가 시 런타임 크래시. B-3 개선 과제로 제안: 전체 `Get_*`를 TryGet 또는 `_orNull` 패턴으로 정규화.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 3. JSON 익스포트 워크플로
|
|
|
|
|
|
|
|
|
|
### 3.1 경로
|
|
|
|
|
|
|
|
|
|
| 단계 | 경로 |
|
|
|
|
|
|---|---|
|
2026-04-20 15:44:48 +00:00
|
|
|
| SOT 엑셀 | `D:/BurningTimes/FilGoodBandits/DeckBuilding/Assets/ResWork/Table/DeckBuilding.xlsm` (최근 수정 2026-04-14) |
|
Initial sync: 너드나비스 조직 전체 자산 (v2 §3 인벤토리 기준)
- 루트: CLAUDE.md + pm-general 에이전트
- 공유/: PD 지시 트래킹, 일일보고, 공통_업무_규칙(C1~C15 + P1~P20 + 부록 A SOT), 조직공지, 부서간 REQ
- 개발실/: CLAUDE.md(C14-4 SOT 참조 전환), 에이전트·커맨드, 코어_설계(_skeleton 제외), 프로젝트 숙지 10종, 조직공지
- 기획실/: CLAUDE.md(C14-4 SOT 참조 전환), 에이전트·스킬모듈, 밸런싱 .md, Phase 3 HOLD 공지
- memory/org/: 사용자 메모리 6종 (외부 ~/.claude/projects/*/memory/ 사본)
- setup/: Windows·macOS 셋업 스크립트
- 제외: Unity·*.xlsm·*.sqlite·settings.local.json·data/·.cache/·_skeleton/
C14-4 참조 무결성 정리: '작업 시점별 자동 환기 메모'를 공통_업무_규칙.md 부록 A(SOT)로 단일화, 개발실/기획실 CLAUDE.md는 참조 링크로 전환.
PD 지시 #7 Phase 1 착수. push는 PAT 수신 후 실행 예정.
2026-04-14 16:40:28 +00:00
|
|
|
| 백업 | 동 경로 `DeckBuilding_Ino.xlsm` |
|
|
|
|
|
| 익스포트 결과 | `Assets/ResWork/Table/Export/` — **JSON 58개 + CSV 일부** (총 ~3.3 MB) |
|
|
|
|
|
| 에디터 도구 후보 | `Assets/Editor/` — `MyEditorUtil.cs`에는 익스포트 코드 **없음**. **(확인 필요)** 외부 VBA/Python 스크립트 가능성 |
|
|
|
|
|
|
|
|
|
|
### 3.2 주요 JSON 파일 크기 Top 5
|
|
|
|
|
|
|
|
|
|
| 파일 | 크기 |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `PCAwakening.json` | 442 KB |
|
|
|
|
|
| `StatusOptionSet.json` | 354 KB |
|
|
|
|
|
| `Localization.json` | 261 KB |
|
|
|
|
|
| `CardList.json` | 180 KB |
|
|
|
|
|
| `MonsterList.json` | 157 KB |
|
|
|
|
|
|
|
|
|
|
### 3.3 CSV 혼재
|
|
|
|
|
|
|
|
|
|
일부 테이블(예: `ApprearMonsterPattern.csv`)이 CSV로 내보내짐. 파싱 경로가 JSON과 이원화될 수 있어 **(확인 필요)**.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 4. 핫패스 테이블 접근
|
|
|
|
|
|
|
|
|
|
`Actor.Get_Dmg()` 기준 전투 루프에서 접근되는 테이블:
|
|
|
|
|
|
|
|
|
|
| 테이블 | 호출 | 빈도 |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `table_GlobalValue.Ins.Get_Int("PCDefence")` | `Actor.cs:775` | **피해 계산마다** — 고빈도 |
|
|
|
|
|
| `table_GlobalValue.Ins.Get_Float("PCDefence_Mul")` | `Actor.cs:783` | 동 |
|
|
|
|
|
| `table_PCUniqueAwakening.Ins.Get_Data()` | `Actor.cs:793` | 피해 계산마다 |
|
|
|
|
|
| `table_cardlist.Ins.Get_Data()` | `Actor.cs:118` | 카드 초기화 시 |
|
|
|
|
|
| `table_SanctuaryConfig.Ins` / `table_StatusOptionSet.Ins` | `Actor.cs:158~159` | 부활·상태이상 이벤트 시 |
|
|
|
|
|
| `table_StatusConditionsList.Ins.Get_Data_orNull()` | `Actor.cs:930` | 부활 |
|
|
|
|
|
| `table_PCAwakening.Ins.Get_Value()` | `Actor.cs:937` | 부활 회복 계산 |
|
|
|
|
|
|
|
|
|
|
**개선 여지**: `PCDefence`·`PCDefence_Mul` 처럼 피해 계산마다 문자열 키로 GlobalValue를 조회하는 경로는 **한 번 캐시**해두면 알로케이션·딕셔너리 조회 비용이 줄어듦. 모바일 타깃에서는 유효.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 5. 런타임 교체 · 서버 연동
|
|
|
|
|
|
|
|
|
|
### 5.1 Hot-reload
|
|
|
|
|
|
|
|
|
|
- 런타임 테이블 교체 코드 **확인 안 됨**. Dictionary 자체는 수정 가능하지만 공식 경로 없음.
|
|
|
|
|
- Addressables 연동 **(확인 필요)** — `Res_Addr/` 폴더는 존재하나 테이블 JSON은 현재 TextAsset Resources 방식.
|
|
|
|
|
|
|
|
|
|
### 5.2 ServerData 오버라이드
|
|
|
|
|
|
|
|
|
|
- 경로: `Assets/Script/Server/ServerClass.cs` 의 `ServerData`
|
|
|
|
|
- Actor 생성 시 주입: `Actor.Set(int identity, ActorTableDataBase actordata, HUD_HPShield hud, ServerData sdata = null)`
|
|
|
|
|
- 쓰임: 각성·봉인 값 등 서버 계정 데이터로 테이블 값 일부 오버라이드 — `Get_ServerData().Get_PCAwakenLv(...)`
|
|
|
|
|
|
|
|
|
|
**결론**: 런타임 재조정은 **테이블 교체가 아닌 사용자 데이터 오버라이드** 방식으로 제한됨. 밸런싱 hot-reload는 미지원 — Phase 1+ 과제.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 6. 보안 · 변조
|
|
|
|
|
|
|
|
|
|
### 6.1 런타임 암호화 (CodeStage AntiCheat)
|
|
|
|
|
|
|
|
|
|
- `ObscuredInt` / `ObscuredFloat` 사용. 예: `CardListTableData._ID`, `BattleLevelUpTableData._Lv`, `MissionTableDataBase._Index`.
|
|
|
|
|
- 세터에서 `RandomizeCryptoKey()` 재수행 — 키 갱신.
|
|
|
|
|
- 메모리 스캔·치트엔진 공격 완화 목적.
|
|
|
|
|
|
|
|
|
|
### 6.2 디스크 JSON
|
|
|
|
|
|
|
|
|
|
- **평문 저장**. StreamingAssets/Resources로 빌드 포함 → APK 분해 시 노출.
|
|
|
|
|
- 클라이언트 변조 가능성 높음 — 서버 검증 필수 영역.
|
|
|
|
|
|
|
|
|
|
### 6.3 서버 검증
|
|
|
|
|
|
|
|
|
|
- PlayFab Editor Extensions 존재 (`Assets/PlayFabEditorExtensions/`) — 실 운영 API 연동 **(확인 필요)**.
|
|
|
|
|
- 05번 문서(서버연동 현황)에서 도출된 **Critical 3건** 보류 상태와 직결. (IAP 미검증·전투 클라 100%·AES 평문키)
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 7. 리스크 · 이슈
|
|
|
|
|
|
|
|
|
|
| 항목 | 영향 | 개선 방향 |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| 엑셀→JSON 수동 익스포트 | 기획 수정 후 반영 누락 가능 | 자동화 스크립트 + CI 통합 |
|
|
|
|
|
| 다중 엑셀 파일 (Ino 백업) | 어느 게 SOT인지 혼동 | 파일명 규칙·버전 태그 명시화 |
|
|
|
|
|
| CSV·JSON 혼재 | 파싱 경로 분기 | JSON으로 일원화 검토 |
|
|
|
|
|
| Direct 인덱서 사용 | 미등록 키 시 크래시 | `_orNull`/`TryGet` 표준화 |
|
|
|
|
|
| JSON 평문 | 클라 변조 | 빌드 시 암호화 래퍼 or 바이너리 포맷 |
|
|
|
|
|
| GlobalValue 문자열 키 핫패스 | 모바일 GC·딕셔너리 조회 비용 | 상수 캐시 / enum 키 도입 |
|
|
|
|
|
| 테이블 버전 메타 없음 | 롤백·동기화 추적 곤란 | JSON 헤더에 version/buildId 도입 |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 8. 테이블 인벤토리
|
|
|
|
|
|
|
|
|
|
- `Assets/Script/Table/Tables/` 아래 **51개 `table_*` 클래스**
|
|
|
|
|
- Export/ 아래 **58개 JSON + 소수 CSV**
|
|
|
|
|
- 대표:
|
|
|
|
|
- `table_ActorList` (534 B), `table_BuffPatternConfig` (2.6 KB)
|
|
|
|
|
- `table_cardlist` (180 KB), `table_Achievement` (247 KB)
|
|
|
|
|
- `table_ApprearMonsterPattern` (56 KB), `table_localtext` (다국어)
|
|
|
|
|
- `table_GlobalValue` (스칼라 파라미터 핫패스)
|
|
|
|
|
|
|
|
|
|
전수 목록은 필요 시 별도 부록으로 추출 가능.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 9. B-3 완료 조건 체크리스트
|
|
|
|
|
|
|
|
|
|
- [x] 로더 계층·싱글톤 패턴 확정
|
|
|
|
|
- [x] 초기화 라이프사이클(Awake 캐시 → Start 파싱) 확정
|
|
|
|
|
- [x] 조회 API 3패턴(`_orNull`/폴백 메시지/Direct) 확정
|
|
|
|
|
- [x] 핫패스 테이블 호출 맵
|
|
|
|
|
- [x] ObscuredTypes 적용 범위 확인
|
|
|
|
|
- [ ] **Excel → JSON 익스포트 도구 실체 확인** (Editor 스크립트 vs VBA/외부) **(확인 필요)**
|
|
|
|
|
- [ ] Addressables 연동 여부 확인
|
|
|
|
|
- [ ] PlayFab 서버 검증 실제 호출 경로 확인
|
|
|
|
|
- [ ] 전체 51개 테이블 인벤토리 부록화
|
|
|
|
|
- [ ] Direct 인덱서 전수 목록화 후 정규화 과제 티켓화
|
|
|
|
|
- [ ] JSON 암호화 방안 설계(타입 결정 + 빌드 파이프라인 반영)
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 10. 기획실 워크플로 접점 요약
|
|
|
|
|
|
|
|
|
|
| 단계 | 담당 | 산출 | 검증 |
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
| 밸런싱 작업 | 기획실 | `DeckBuilding.xlsm` | 기획 자체 검토 |
|
|
|
|
|
| 익스포트 | **(확인 필요)** | `Export/*.json` | 파일 타임스탬프 비교 |
|
|
|
|
|
| 빌드 포함 | Unity 빌드 | APK 내 TextAsset | TableChecker LoadComplete |
|
|
|
|
|
| 런타임 조회 | 코드 | Dictionary 조회 | — |
|
|
|
|
|
| 서버 오버라이드 | PlayFab | ServerData 주입 | 로그인 직후 |
|
|
|
|
|
|
|
|
|
|
→ **단일 취약점**: "익스포트 단계"가 자동화되지 않은 것으로 보이는 지점. 개발실 우선 정비 후보.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 11. 변경 이력
|
|
|
|
|
|
|
|
|
|
| 버전 | 일자 | 작성자 | 내용 |
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
| v1 | 2026-04-14 | 개발실장 (Explore 위임) | Phase 0-B-3 초안 |
|