# 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` | `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>(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 tableDatas // 순차 접근 → Dictionary 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 경로 | 단계 | 경로 | |---|---| | SOT 엑셀 | `D:/NerdNavis/FilGoodBandits/DeckBuilding/Assets/ResWork/Table/DeckBuilding.xlsm` (최근 수정 2026-04-14) | | 백업 | 동 경로 `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 초안 |