BurningTimesAi/프로젝트/신규 프로젝트/개발/04_데이터_파이프라인.md

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 {날짜} 개발팀장 템플릿 초안. 수상한잡화점 데이터 파이프라인 패턴 + 시뮬레이터 이원화 방지 규칙 반영