7.1 KiB
7.1 KiB
{프로젝트명} — 데이터 파이프라인
버전: v1 작성일: {날짜} 담당: 개발팀장 적용 범위: {프로젝트명} 데이터 테이블 설계 및 로딩 구조
1. SOT(Single Source of Truth) 정의
| 항목 | 값 |
|---|---|
| SOT 포맷 | Excel (.xlsm 또는 .xlsx) |
| SOT 경로 | {Unity프로젝트경로}/Assets/ResWork/Table/{프로젝트명}.xlsm |
| 변환 도구 | {선택 예: Editor 스크립트(자동화 권장) / VBA 매크로 / Python 스크립트} |
| 런타임 포맷 | JSON (UTF-8) |
| JSON 경로 | {Unity프로젝트경로}/Assets/ResWork/Table/Export/*.json |
| 경로 규칙 | 테이블명 = Excel 시트명 = JSON 파일명 = C# 클래스명 (대소문자 일치) |
SOT 규칙:
- Excel 파일이 유일한 SOT. JSON은 Export 결과물이며 직접 편집 금지
- Excel 수정 후 Export 없이 Unity에 반영된 것처럼 처리하는 행위 금지 (C5 정직성)
- 백업 파일(
{프로젝트명}_Ino.xlsm등)과 SOT를 혼동하지 않도록 파일명 규칙 명확화
2. 파이프라인 흐름
[기획팀] [개발팀] [런타임]
Excel 편집
│
▼
Export Tool 실행
(Editor 스크립트 권장)
│
▼
JSON 생성
Assets/ResWork/Table/Export/*.json
│
▼
Unity AssetDatabase.Refresh()
(에디터 자동 감지)
│
▼
Runtime DataTable Load
(Awake: TextAsset → json string cache)
(Start: JsonConvert.DeserializeObject → Dictionary)
│
▼
Memory Dictionary Cache
O(1) 조회
자동화 목표: Excel 수정 → Export Tool 실행 → 반영까지 수동 단계 최소화. 수상한잡화점 교훈: Export 단계가 수동이면 기획 수정 후 반영 누락이 발생함.
3. DataTable 베이스 클래스 (BT.Framework 활용)
// BurningTimes.Core.Data.DataTable 기반 — 직접 상속
// 프로젝트별 테이블은 아래 패턴으로 구현
using BurningTimes.Core.Data;
using Newtonsoft.Json;
namespace {ProjectNamespace}.Data
{
// 테이블 행 데이터 클래스
public class CardTableData : TableDataBase
{
[JsonProperty("_ID")] public int Id;
[JsonProperty("_Name")] public string Name;
[JsonProperty("_Damage")] public int Damage;
// ... 각 컬럼 필드
}
// 테이블 매니저 클래스 (MonoSingleton + DataTable 조합)
public class CardTable : DataTable<CardTableData>
{
// Dictionary 인덱스 — 자주 쓰는 키 기준으로 추가 정의
private Dictionary<int, CardTableData> _byId;
protected override void BuildIndex(List<CardTableData> records)
{
_byId = records.ToDictionary(r => r.Id);
}
// 권장: _orNull 패턴 (KeyNotFoundException 방지)
public CardTableData GetByIdOrNull(int id)
=> _byId.TryGetValue(id, out var data) ? data : null;
}
}
수상한잡화점 교훈 — 금지 패턴:
// 금지: Direct 인덱서 → 미등록 키 시 KeyNotFoundException 런타임 크래시
public CardTableData Get(int id) => _byId[id]; // ❌
// 권장: TryGet 또는 _orNull 패턴
public CardTableData GetOrNull(int id)
=> _byId.TryGetValue(id, out var data) ? data : null; // ✅
4. 로딩 전략
| 시점 | 대상 테이블 | 방식 |
|---|---|---|
| 앱 시작 (Bootstrap 씬) | 핵심 공통 테이블 (GlobalValue, Localization 등) | 동기 전체 로딩 → TableChecker.AllLoaded 확인 후 진행 |
| 씬 전환 시 | 해당 씬에서만 필요한 테이블 | 씬 로딩 중 비동기 로딩 |
| 온디맨드 | 이벤트·대화 등 대용량·선택적 테이블 | 필요 시 Addressables 연동 로딩 |
초기화 라이프사이클 (수상한잡화점 패턴 계승):
// Awake: JSON 문자열 캐시 + TextAsset 객체 언로드 (메모리 절약)
private void Awake()
{
_jsonCache = _textAsset.text;
Resources.UnloadAsset(_textAsset);
}
// Start: 역직렬화 + Dictionary 인덱스 구축
private void Start()
{
var records = JsonConvert.DeserializeObject<List<T>>(_jsonCache);
BuildIndex(records);
IsLoaded = true;
}
메모리 상주 정책:
- 전투 핫패스 테이블 (GlobalValue, CardList 등): 게임 실행 내내 상주
- 씬 전용 테이블: 씬 Unload 시 해제
- 로컬라이제이션 테이블: 언어 전환 시 재로딩
에디터 핫 리로드 (개발 편의):
- Editor PlayMode에서 Excel Export 후
AssetDatabase.Refresh()→ 자동 재로딩 - 런타임 핫패치는 현재 미지원 (필요 시 별도 설계)
5. 무결성 검증
5.1 Export 시 자동 검증 (Export Tool에 내장)
- FK 정합성: 참조 테이블의 ID 존재 여부 확인
- null 체크: 필수 컬럼의 빈 값 감지
- 범위 검증: 수치 컬럼의 최솟값·최댓값 범위 이탈 감지
5.2 런타임 검증 (개발 빌드 전용)
// 개발 빌드에서만 실행되는 검증 코드
#if DEVELOPMENT_BUILD || UNITY_EDITOR
DataValidator.ValidateAll();
#endif
5.3 테이블 버전 메타
{
"version": "1.0.3",
"exportedAt": "2026-04-16",
"records": [ ... ]
}
JSON 헤더에 version/exportedAt 포함하여 롤백·동기화 추적 가능하게 한다.
6. ⚠️ 시뮬레이터 이원화 방지
런타임과 시뮬레이터/분석 도구가 반드시 동일 데이터 소스를 참조해야 한다.
금지 패턴:
- 기획팀 시뮬레이터가 Excel에서 직접 읽고, 런타임은 JSON을 읽는 구조 → 수치 불일치 발생
- 시뮬레이터 전용 파싱 로직이 별도 존재 → SOT 분기
올바른 구조:
Excel (SOT)
│
├── Export → JSON (런타임 참조)
│ └── DataTable 로딩 → 게임 실행
│
└── Export → JSON (시뮬레이터 참조) ← 동일 JSON 파일 공유
└── 시뮬레이터/분석 도구
기획팀 밸런싱 시뮬레이터는 런타임 DataTable과 동일한 JSON Export 파일을 입력 소스로 사용한다. 별도 파싱 로직이 필요하다면 런타임 DataTable 클래스를 직접 재사용하거나, 공통 파서 모듈을 분리한다.
7. 리스크 및 개선 방향
| 항목 | 위험 | 개선 방향 |
|---|---|---|
| 수동 Export | 기획 수정 후 반영 누락 | Export 자동화 스크립트 + CI 통합 |
| JSON 평문 저장 | APK 분해 시 테이블 노출 | 빌드 시 암호화 래퍼 또는 바이너리 포맷 검토 |
| Direct 인덱서 | 미등록 키 시 런타임 크래시 | _orNull / TryGet 패턴 전수 적용 |
| 핫패스 문자열 키 조회 | 모바일 GC/딕셔너리 조회 비용 | 상수 캐시 / enum 키 도입 |
| 테이블 버전 메타 없음 | 롤백·동기화 추적 곤란 | JSON 헤더에 version/exportedAt 도입 (섹션 5.3) |
변경 이력
| 버전 | 일자 | 작성자 | 내용 |
|---|---|---|---|
| v1 | {날짜} | 개발팀장 | 템플릿 초안. 수상한잡화점 데이터 파이프라인 패턴 + 시뮬레이터 이원화 방지 규칙 반영 |