Company
교육 철학

DataProvider 가이드

무엇을 하나요?

DataProvider<T>리소스에서 데이터(에셋/바이너리/파일시스템)를 비동기로 읽어헬퍼로 파싱이벤트로 결과를 알려주는 중간 계층입니다.
읽기는 IResourceManager, 파싱은 IDataProviderHelper<T>가 담당하고, DataProvider<T>가 둘을 이어줘요.

왜 굳이 DataProvider를 쓰나

교체 쉬움: JSON → 바이너리, 로컬 파일 → CDN 바꿔도 UI/게임 코드는 그대로. (헬퍼/리소스만 교체)
표준 이벤트: 성공/실패/진행률/의존 리소스 이벤트로 로딩 UI 연결이 간단.
성능/GC: 큰 테이블은 내부 공용 버퍼 재사용으로 스파이크 완화.
테스트 용이: 파싱 로직(헬퍼)은 순수 함수에 가까워 단위 테스트가 쉬움.

두 줄 요약

DataProvider: 가져오기알림 담당(웨이터).
헬퍼(IDataProviderHelper): 파싱/변환/저장 담당(요리사).
→ 인벤/상점/퀘스트/맵/로컬라이즈 같은 실제 화면이 이 데이터에 바인딩돼서 움직여.

구조 요약

런타임 흐름
1.
ReadData("path", priority, userData)
2.
IResourceManager.HasAsset()으로 종류 판별(에셋/바이너리/파일시스템)
3.
LoadAsset / LoadBinary / LoadBinaryFromFileSystem
4.
완료 콜백에서 IDataProviderHelper<T>ReadData/ParseData 호출
5.
다음 이벤트 발행
ReadDataSuccess / ReadDataFailure
ReadDataUpdate(진행률)
ReadDataDependencyAsset(의존 리소스 로드시)
성능 메모
큰 바이너리 재사용을 위해 정적 버퍼(4KB 블록 단위) 확보/해제 API 제공
EnsureCachedBytesSize(int), CachedBytesSize, FreeCachedBytes().

파일별 역할

DataProvider.cs
IDataProvider<T> 구현체. 읽기/파싱 오버로드와 4가지 이벤트를 실제로 발생. 내부 캐시 버퍼 재사용.
DataProviderCreator.cs
생성 편의 유틸. Create<T>(owner, resourceManager, helper)로 안전하게 만들고 필수 의존성 주입.
캐시 버퍼 유틸도 외부에 노출(크기 조회/확보/해제).
IDataProvider.cs
공개 인터페이스. 이벤트(성공/실패/업데이트/의존) + ReadData(...), ParseData(...) 시그니처 정의.
IDataProviderHelper.cs
실제 파싱 담당. 에셋(object)/바이트/문자열을 받아 도메인 데이터로 해석. 필요 시 ReleaseDataAsset로 에셋 해제.
ReadDataSuccessEventArgs.cs
DataAssetName, Duration, UserData.
ReadDataFailureEventArgs.cs
DataAssetName, ErrorMessage, UserData.
ReadDataUpdateEventArgs.cs
DataAssetName, Progress, UserData.
ReadDataDependencyAssetEventArgs.cs
DataAssetName, DependencyAssetName, LoadedCount/TotalCount, UserData.

쉽게 이해 하기

게임에선 DataProvider가 “창고(리소스/서버)에서 재료(데이터)를 가져와서 → 요리사(헬퍼)가 먹기 좋게 가공 → HUD/메뉴/시스템에 내어주는 웨이터” 역할.
DataProvider = “데이터 배달 담당자”
창고에서 가져오고(로드) → 내용을 풀어서(파싱) → **도착 알림(이벤트)**까지 해주는 애.

등장인물 3명

IResourceManager: “창고 담당” → 파일/에셋/원격에서 가져오기
DataProvider<T>: “배달 기사” → 어디서 가져올지 판단하고 진행 상황/완료를 전달
IDataProviderHelper<T>: “해석가(요리사)” → 가져온 텍스트/바이너리를 우리 게임 데이터로 변환

쓰는 흐름 (4단계)

1.
Helper를 만든다: “JSON → 아이템DB로 바꾸는 법” 같은 파싱 방법 정의
2.
Create로 프로바이더를 만든다: DataProviderCreator.Create(owner, resourceManager, helper)
3.
이벤트 구독: 성공/실패/진행률/의존 리소스 → UI나 로그에 연결
4.
ReadData("경로") 호출: 끝나면 헬퍼가 파싱해서 owner에 결과를 꽂아줌
// 1) 파싱 헬퍼: TextAsset/바이너리 → JSON → ItemDB public sealed class JsonDataHelper : IDataProviderHelper<GameDB> { public bool ReadData(GameDB db, string name, object asset, object ud) => ParseData(db, (asset as TextAsset)?.text, ud); public bool ReadData(GameDB db, string n, byte[] b, int s, int l, object ud) => ParseData(db, System.Text.Encoding.UTF8.GetString(b, s, l), ud); public bool ParseData(GameDB db, string json, object ud) { db.Items = JsonUtility.FromJson<ItemDB>(json); // ← 여기서 우리 구조로 변환 return db.Items != null; } public bool ParseData(GameDB db, byte[] b, int s, int l, object ud) => ParseData(db, System.Text.Encoding.UTF8.GetString(b, s, l), ud); public void ReleaseDataAsset(GameDB db, object asset) { } } // 2) 사용하는 쪽 public sealed class BootLoader : MonoBehaviour { public GameDB DB; IDataProvider<GameDB> _provider; void Awake() { var rm = GameEntry.GetComponent<ResourceComponent>(); // 창고 담당 _provider = DataProviderCreator.Create(DB, rm, new JsonDataHelper()); // 배달+해석 세팅 _provider.ReadDataSuccess += (_, e) => Debug.Log("Loaded: " + e.DataAssetName); _provider.ReadDataFailure += (_, e) => Debug.LogError(e.ErrorMessage); _provider.ReadData("Configs/ItemDB.json", 0, null); // 가져와서 → 해석 → DB에 채움 } }
C#
복사

사용 예시

1) 인벤토리 화면

어디서: Addressables에 있는 Items.bytes
가져오기: DataProvider가 로드
가공: 헬퍼가 바이너리를 ItemDB로 파싱
표시: 인벤토리 UI 그리드가 ItemDB 바인딩
public class InventoryPanel : MonoBehaviour { public GridView grid; IDataProvider<GameDB> _provider; void OnEnable() { var rm = GameEntry.GetComponent<ResourceComponent>(); // 창고 담당 _provider = DataProviderCreator.Create(Game.DB, rm, new ItemBinaryHelper()); // 웨이터+요리사 세팅 _provider.ReadDataSuccess += (_, __) => grid.Bind(Game.DB.Items); _provider.ReadDataFailure += (_, e) => Toast.Show($"인벤토리 로드 실패: {e.ErrorMessage}"); _provider.ReadData("Configs/Items.bytes", priority: 0); // 재료 가져오기 시작 } }
C#
복사

2) 상점(실시간 가격/재고)

어디서: CDN/서버의 Shop.json
가져오기: DataProvider가 네트워크 리소스 로드
가공: 헬퍼가 JSON → ShopModel 변환(통화 포맷/세일 적용)
표시/갱신: 상점 카드 UI가 모델을 구독해 자동 갱신

3) 로컬라이즈(다국어)

어디서: Localization/ko.json
가공: 헬퍼가 Dictionary<Key,Text>로 변환
적용: 화면의 LocalizedText들이 이벤트 받아 텍스트 일괄 갱신

4) 스테이지 선택/월드맵

어디서: Stages.bytes
가공: 헬퍼가 스테이지 메타(이름, 요구 레벨, 보상)로 파싱
표시: 맵 노드 UI가 목록을 바인딩 → 잠김/해금 표시

5) 순위/리더보드

어디서: REST API 응답(JSON)
가공: 헬퍼가 LeaderboardEntry[]로 정제(상위 N명, 자기 랭크 포함)
표시: 스크롤 리스트가 즉시 갱신, 진행률/실패는 이벤트로 토스트/리트라이