# BurningTimes 신규 범용 코어 — 아키텍처 설계안 > **작성일**: 2026-04-14 > **작성자**: 개발실장 > **상태**: PD님 결정(네임스페이스 `BurningTimes.*`, MVP=Tier1+2) 반영 v1.2 > **적용 대상**: 수상한 잡화점 **이후** 프로젝트 (현 프로젝트에는 미적용) --- ## 1. 프로젝트 정체성 | 항목 | 값 | 비고 | |------|-----|------| | **정식 명칭** | `BT.Framework` | PD님 확정 ✅ (2026-04-14) | | **UPM 패키지 이름** | `com.nerdnavis.framework` | PD님 확정 ✅ (2026-04-14) | | **루트 네임스페이스** | `BurningTimes` | PD님 확정 ✅ | | **Unity 호환** | 6000.0.x (Unity 6 LTS) 이상 | 수상한 잡화점 환경 기준 | | **API 호환성** | .NET Standard 2.1 | | | **저장소** | PD님 NAS Git (세부 논의 대기) | ①②④ 완료 후 확정 예정 | | **첫 적용 프로젝트** | 수상한 잡화점의 **다음** 프로젝트 | | ## 2. 네임스페이스 체계 ``` BurningTimes 루트 (공용 인터페이스, 공용 enum) │ ├── BurningTimes.Core 코어 시스템 │ ├── Patterns 싱글톤·옵저버·오브젝트풀·팩토리 │ ├── Container ObservableList/Dictionary/Queue 등 │ ├── Coroutine 코루틴 러너 │ ├── Event 이벤트 버스 (타입 안전) │ ├── Data 마스터 테이블·CSV 로더 │ ├── Util Math/Validation/Formatter/KeyMaker/Rate/Style │ ├── Attribute ReadOnly/ShowIf/ArrayTitle │ └── Optimization EnumString/ScopedValue 등 │ ├── BurningTimes.UI UI 프레임워크 │ ├── UGUI UGUI 기반 (수상한 잡화점 경험 반영) │ ├── UIToolkit UI Toolkit 기반 (기존 코어 계승) │ ├── Components SafeArea/FitLabel/Layout │ └── Extensions │ ├── BurningTimes.Save [Tier 2] 세이브/로드 시스템 ├── BurningTimes.Localization [Tier 2] 로컬라이제이션 ├── BurningTimes.Audio [Tier 2] 오디오 매니저 ├── BurningTimes.Addressable [Tier 2] Addressable 래퍼 ├── BurningTimes.Economy [Tier 2] 재화 모델 (Goods) — PD님 지시로 Tier 2 이관 │ ├── BurningTimes.Network [Tier 3] (서버팀 셋업 이후) ├── BurningTimes.Security [Tier 3] (서버팀 셋업 이후) │ └── BurningTimes.Editor 에디터 도구 ├── Build 빌드 자동화 ├── Hierarchy 계층창 개선 ├── Data CSV/Excel 컨버터 └── Symbols 컴파일 심볼 관리 ``` ## 3. 네이밍 재작성 매핑표 (IP 회피 필수) 기존 코드 **구조·로직 재사용 허용**, **네이밍·식별자는 반드시 재작성**. ### 네임스페이스 | 기존 | 신규 | |------|------| | `DG.Core` | `BurningTimes.Core` | | `DG.Util` | `BurningTimes.Core.Util` | | `DG.Util.Container` | `BurningTimes.Core.Container` | | `DG.UI` | `BurningTimes.UI` | | `DG.Manager` | `BurningTimes.Core.Event` (→ EventBus로 재설계) | | `DG.OutGame` | `BurningTimes.Core.Goods` (Goods만 분리) | | `DG.Editor` | `BurningTimes.Editor` | | `DG.Core.Tool` | `BurningTimes.Editor.Data` | ### 클래스 | 기존 | 신규 | 사유 | |------|------|------| | `UniList` | `ObservableList` | 표준 .NET 용어 | | `UniDictionary` | `ObservableDictionary` | | | `UniQueue` | `ObservableQueue` | | | `UniEventList` | (통합 제거) | `ObservableList`에 옵저버 기능 통합 | | `UniObserverList` | (통합 제거) | 동상 | | `UniEventQueue` | (통합 제거) | `ObservableQueue`로 통합 | | `UniObserverQueue` | (통합 제거) | 동상 | | `UniDoubleArray` | `Grid2D` | 이름 직관화 | | `UniPair` | (제거) | .NET `ValueTuple` 사용 권장 | | `UniRange` | `NumRange` | 직관성 | | `UniEnumValue` | `EnumLookup` | | | `UniGroup` | `Group` | | | `BoostController` | `BuffController` | 게임 업계 표준 용어 | | `Boost`, `BoostElement` | `BuffEntry`, `BuffDefinition` | | | `SchedulHandler` | `TaskScheduler` (네임 충돌 시 `GameScheduler`) | 오탈자 수정 | | `ObserverManager` | `EventBus` | 현대 네이밍 + 타입 안전 재설계 | | `MyHierarchyHeader` | `HierarchyHeader` | `My` 접두사 제거 | | `MyHierarchyGroup` | `HierarchyGroup` | | | `MyHierarchySettings` | `HierarchySettings` | | | `Toolkit.*` | (분할 유지, 네임 변경) `MathEx`, `ValidationEx`, `FormatEx`, `KeyMaker`, `RateRoller`, `StyleEx` | 부분 클래스 의존 축소 | | `CoroutineHandler` + `CoroutineRunner` | `CoroutineRunner` 단일화 | 2개 분리 이유 불명, 통합 | | `Singleton`, `AsyncSingleton`, `InnerSingleton`, `ReadySingleton` | **통합 → `MonoSingleton`** + 옵션 플래그 | 4종 분산의 유지보수 부담 해소 | | `WaitCahe` | `WaitCache` | **오탈자 수정** | | `MasterTableBase`, `MasterTableSO` | `DataTable`, `DataTableSO` | 네이밍 일관성 | | `CustomParserBase` | `CustomParser` | `Base` 접미사 제거 (추상은 abstract 키워드로 충분) | | `GachaGradeInfo`, `GachaTracker` | `GachaGrade`, `PityTracker` | `Info` 접미사 제거, 천장 기능 명확 | | `RegistUIHelper`, `ShowHideRegistUI` | `UIRegistry`, `UIVisibilityToggle` | 오탈자(Regist→Register) + 역할 명시 | ## 4. 기존 코드 구조적 개선점 (PD님 지시: "더 효율적으로 변형" 반영) ### 4-1. 싱글톤 4종 통합 → `MonoSingleton` + 옵션 **문제**: 기존에는 `Singleton`, `AsyncSingleton`, `InnerSingleton`, `ReadySingleton` 4개가 각기 존재해 사용자가 어느 것을 써야 하는지 혼란. **개선안**: ```csharp public abstract class MonoSingleton : MonoBehaviour where T : MonoSingleton { [SingletonOption(Persistent = true, AutoCreate = true, InitMode = InitMode.Sync)] public static T Instance { get; } } ``` - `Persistent`: `DontDestroyOnLoad` 여부 - `AutoCreate`: 인스턴스 없을 때 자동 생성 여부 - `InitMode`: `Sync` / `Async` / `ManualReady` - 쓰레드 안전은 내부 표준 제공, 사용자 선택 필요 없음 ### 4-2. ObserverManager → EventBus (타입 안전 재설계) **문제**: - 문자열 키 기반 → 오타·컴파일 검증 불가 - `object data` 전달 → 박싱·언박싱 비용 - `GenerateItemTypeKey(ItemType, int)` 같은 **프로젝트 특화 키 생성기가 코어에 존재** → C11 오염 **개선안**: ```csharp public static class EventBus { public static void Subscribe(Action handler); public static void Unsubscribe(Action handler); public static void Publish(TEvent e); } // 사용 예 EventBus.Subscribe(OnPlayerDied); EventBus.Publish(new PlayerDiedEvent { PlayerId = 42 }); ``` - 이벤트를 **타입으로 식별** → 컴파일 타임 안전 - `GenerateItemTypeKey` 등 프로젝트 특화 키는 **전부 제거** (프로젝트 쪽에서 이벤트 struct로 정의) - 문자열 키 버전은 `EventBus.Raw` 하위 네임스페이스로 분리 (특수 용도만) ### 4-3. 컨테이너 2종 체계 단순화 **문제**: `UniList` / `UniEventList` / `UniObserverList` 3종이 나뉘어 "언제 어느 것?" 혼란. **개선안**: - `ObservableList` 하나로 통합 - 이벤트(`OnAdd`, `OnRemove`, `OnChange`, `OnClear`)는 기본 제공 - 옵저버가 필요 없을 때는 표준 `List` 사용하면 됨 (원래 그랬어야 함) - Dictionary/Queue도 동일 단순화 ### 4-4. CoroutineHandler + CoroutineRunner 통합 **문제**: 2개가 분리된 이유가 README·코드 주석에도 없음. **개선안**: - `CoroutineRunner` 하나로 통합 - 일시정지·재시작·중복방지·키 기반 식별 전부 단일 API로 - 향후 UniTask 지원 여부는 별도 결정(외부 의존성) ### 4-5. `DG.OutGame/Goods.cs`, `RegistUIHelper`, `ShowHideRegistUI` 위치 재검토 **문제**: `OutGame` 네임스페이스가 코어에 있는데 내용은 사실상 UI 레지스트리 + 재화 모델. 게임 특화인지 범용인지 애매. **결정 (PD님 확정 ✅ 2026-04-14)**: - `Goods`는 **Tier 2로 이관** → `BurningTimes.Economy.Goods` - `RegistUIHelper` → `UIRegistry` 로 `BurningTimes.UI` 하위 이동 (Tier 1 유지) - `ShowHideRegistUI` → `UIVisibilityToggle` 로 `BurningTimes.UI` 하위 이동 (Tier 1 유지) ### 4-6. Boost 시스템 재설계 (Buff 표준화) **문제**: "Boost"는 모바일 광고/강화 뉘앙스 → 범용 게임 프레임워크로서 부적절. **개선안**: - `BuffSystem` 으로 재명명 + 재설계 - 시간·스택·중첩 정책·가산/승산/치환 정책 명시적 enum화 - `IModifier` 인터페이스 기반 → 게임 스탯 시스템과 쉽게 결합 ### 4-7. Toolkit.* 부분 클래스 해체 **문제**: 기존 `Toolkit.Math.cs`, `Toolkit.Rate.cs`, `Toolkit.Formatter.cs` 등은 전부 `partial class Toolkit`. 단일 진입점은 편하지만, **IDE 자동완성이 수백 개 메서드 노출** → 탐색 저하. **개선안**: - 부분 클래스 해체: `MathEx`, `RateRoller`, `FormatEx`, `KeyMaker`, `ValidationEx`, `StyleEx` 각각 독립 static 클래스 - using static 가능, 카테고리별 명확한 진입점 ### 4-8. WaitCahe 오탈자 수정 **문제**: 파일명·클래스명 모두 `WaitCahe` (Cache 오탈자). 기존 사용처 그대로 따라감. **개선안**: `WaitCache` 로 수정. (재작성이므로 기회 활용) ### 4-9. ServiceLocator 신설 (v1.2 추가, PD님 지시 2026-04-14) **배경**: PD님께서 Tier 1 구현 지시 시 Logger·ServiceLocator·CoroutineRunner 3종을 기반 Core로 명시. 기존 설계에는 ServiceLocator 개념이 없었고 "MonoSingleton + EventBus" 2축으로만 서비스 접근을 해결하려 했음. **설계 판단**: - **MonoSingleton** = 씬 생명주기와 동기화되는 `MonoBehaviour` 단일 인스턴스 (Update/OnDestroy 훅 필요한 서비스) - **ServiceLocator** = 순수 C# 서비스 레지스트리 (MonoBehaviour 아님, 인터페이스 바인딩·테스트 대체 용이) - **EventBus** = 타입 안전 이벤트 분기 (Pub/Sub) 세 축은 역할이 분리되어 공존한다. ServiceLocator는 "안티패턴" 비판이 있으나 경량 DI 컨테이너 대체로서 **(1) 테스트 시 Mock 주입 가능 (2) 인터페이스 기반 느슨한 결합 (3) 기동 순서 제어 용이** 이점이 있다. **개선안**: ```csharp public static class ServiceLocator { public static void Register(T service) where T : class; public static void Register(Func factory) where T : class; // Lazy public static T Resolve() where T : class; public static bool TryResolve(out T service) where T : class; public static void Unregister() where T : class; public static void Clear(); // 테스트용 } // 사용 예 ServiceLocator.Register(new JsonSaveProvider()); var save = ServiceLocator.Resolve(); ``` **주의 규칙**: 1. 인터페이스 타입으로만 등록·조회 권장 (구체 타입 바인딩은 결합도 상승) 2. 씬 전환 시 scope 고려 — 글로벌 서비스만 등록, 씬 서비스는 `MonoSingleton` 사용 3. `Resolve` 실패 시 `ServiceNotRegisteredException` 발생 (silent null 금지) 4. 코어 자체는 ServiceLocator에 의존하지 않음 (순환 의존 방지) ## 5. Tier 1 모듈 목록 (MVP 필수) | 영역 | 네임스페이스 | 기존 코드 기반 여부 | 비고 | |------|-------------|-------------------|------| | 싱글톤 | `BurningTimes.Core.Patterns` | ✅ 4종 통합 (4-1) | `MonoSingleton` + 옵션 | | **서비스 로케이터** | `BurningTimes.Core.Patterns` | 🔴 신규 (4-9) | `ServiceLocator` — PD님 지시 v1.2 추가 | | 이벤트 버스 | `BurningTimes.Core.Event` | 🟡 재설계 (4-2) | 타입 안전 | | 옵저버 컨테이너 | `BurningTimes.Core.Container` | 🟡 단순화 (4-3) | | | 코루틴 | `BurningTimes.Core.Coroutine` | 🟡 통합 (4-4) | | | 오브젝트풀 | `BurningTimes.Core.Patterns` | ✅ 거의 그대로 | `ObjectPool` | | 팩토리 | `BurningTimes.Core.Patterns` | ✅ 거의 그대로 | | | 로깅 | `BurningTimes.Core.Util` | 🟡 카테고리·필터 확장 | `Log` | | 데이터 테이블 | `BurningTimes.Core.Data` | ✅ 구조 계승 | `DataTable`, `DataTableSO` | | CSV 로더 | `BurningTimes.Core.Data` | ✅ 거의 그대로 | | | Toolkit | `BurningTimes.Core.Util` | 🟡 부분 클래스 해체 (4-7) | | | 속성(Attribute) | `BurningTimes.Core.Attribute` | ✅ 거의 그대로 | ReadOnly/ShowIf | | UI 프레임워크 (UGUI) **주력** | `BurningTimes.UI.UGUI` | 🔴 신규 (수상한 잡화점 경험 반영) | `UIView` UGUI 버전. PD님 지시: 주력 ✅ | | UI 프레임워크 (UIToolkit) **보조** | `BurningTimes.UI.UIToolkit` | ✅ 기존 `UIView` 계승 | 최소 수준 유지, 확장 우선순위 낮음 | | SafeArea | `BurningTimes.UI.Components` | ✅ 계승 | | | 에디터 도구 | `BurningTimes.Editor.*` | ✅ 계승 (네이밍만 변경) | | ## 6. Tier 2 모듈 목록 (신규 설계) 기존 코어에 없었던 누락 모듈. 완전 신규 설계. ### 6-0. `BurningTimes.Economy` — 재화 모델 (PD님 지시로 Tier 2 이관) - `Goods` 범용 재화 모델 (타입·수량·최대치·오버플로 정책) - 기존 `DG.OutGame/Goods.cs` 구조 계승, 네이밍만 변경 - 인벤토리·획득 이벤트 훅 (`EventBus` 연동) ### 6-1. `BurningTimes.Save` — 세이브/로드 - `ISaveProvider` 인터페이스 (PlayerPrefs / JSON 파일 / 암호화 JSON / 클라우드 교체 가능) - JSON 직렬화 + 버전 마이그레이션 훅(`IMigration`) - AES 암호화는 선택 레이어 (`EncryptedJsonProvider`) - 키 관리는 Tier 3 `BurningTimes.Security.ICryptoProvider` 합류 전까지는 디바이스ID 유도 임시 방식 ### 6-2. `BurningTimes.Localization` — 로컬라이제이션 - Unity Localization 패키지 래퍼 - 키 기반 조회 + 폴백 체인(현재 언어 → 영어 → 키 원본) - 런타임 언어 변경 이벤트 (`LocaleChangedEvent` via EventBus) - 폰트 자동 스왑 지원 ### 6-3. `BurningTimes.Audio` — 오디오 매니저 - BGM 채널 1 + SFX 채널 풀링(8~16) - AudioMixer 연동, 볼륨 저장(Save 연동) - iOS 사일런트 모드 대응, Unity AudioFocus 처리 - 3D 오디오는 초기 미포함 (필요 시 Tier 2 후속) ### 6-4. `BurningTimes.Addressable` — Addressable 래퍼 - 참조 카운팅 기반 `AddressableHandle` - Preload/Unload 정책(`Scene` / `Manual` / `TTL`) - 로드 실패 폴백 훅 - 수상한 잡화점 `AddrHandleBase` 를 범용화한 형태 ## 7. Tier 3 목록 (서버팀 셋업 시점 합류) | 영역 | 네임스페이스 | 합류 조건 | |------|-------------|-----------| | 네트워크 추상화 | `BurningTimes.Network` | 서버팀 구성 + 백엔드 스택 결정 후 | | IAP 영수증 검증 | `BurningTimes.Network.Purchase` | 〃 | | 서버 전투 아비터 인터페이스 | `BurningTimes.Core.Battle` | 〃 | | 암호화·서명 | `BurningTimes.Security` | 〃 | **→ `project_shop_security_pending.md` 메모에 연동된 Critical 3건 재기동과 동시 추진** ## 8. 폴더 구조 (패키지 스켈레톤) ``` com.nerdnavis.framework/ ├── package.json ├── README.md ├── CHANGELOG.md ├── LICENSE.md (내부용 고지) │ ├── Runtime/ │ ├── BT.Framework.Runtime.asmdef │ ├── Core/ │ │ ├── Patterns/ │ │ ├── Container/ │ │ ├── Coroutine/ │ │ ├── Event/ │ │ ├── Data/ │ │ ├── Util/ │ │ ├── Attribute/ │ │ └── Optimization/ │ ├── UI/ │ │ ├── UGUI/ (주력) │ │ ├── UIToolkit/ (보조, 최소) │ │ ├── Components/ │ │ └── Extensions/ │ ├── Save/ [Tier 2] │ ├── Localization/ [Tier 2] │ ├── Audio/ [Tier 2] │ ├── Addressable/ [Tier 2] │ └── Economy/ [Tier 2] (Goods) │ ├── Editor/ │ ├── BT.Framework.Editor.asmdef │ ├── Build/ │ ├── Hierarchy/ │ ├── Data/ │ └── Symbols/ │ └── Tests/ ├── Runtime/ │ └── BT.Framework.Tests.asmdef └── Editor/ └── BT.Framework.EditorTests.asmdef ``` ## 9. 수상한 잡화점 코드 활용 (범용 패턴 추출 대상) 수상한 잡화점 Unity 프로젝트 (`D:/BurningTimes/FilGoodBandits/DeckBuilding/Assets/Script/`) 에서 **범용화 가치가 있는 패턴**. 상세는 별도 문서 `02_수상한잡화점_추출대상_v1.md` 로 분리 예정. **1차 후보** - `My/MyCoroutine.cs` → 코루틴 베이스 → `CoroutineRunner` 참고 자료 - `Template/MonoBehaviourSingletonTemplate.cs` → 싱글톤 패턴 → `MonoSingleton` 참고 자료 - `My/MyEnum.cs`, `MyValue.cs` 중 범용 enum/상수 선별 - `My/DSUtil.cs` → 데이터 구조 유틸 → `MathEx`/`ValidationEx` 흡수 후보 - `My/CryptoUtil.cs` → 구조는 참고, **하드코딩 키 제거** 후 `BurningTimes.Security` 초안 → **Tier 3으로 이관** - `Addressable/AddrHandleBase.cs` → `BurningTimes.Addressable` - `Manager/ErrorLogHookManager.cs` → 범용 로그 훅 패턴 - `UGUI/Common/GameUI.cs` → UGUI UIView 추상화 출발점 - `UGUI/Manager/UIAtlasMgr.cs` → UI 아틀라스 매니저 - `UGUI/Util/SafeArea.cs` → 이미 `FilGoodBandits` 네임스페이스 → `BurningTimes.UI.Components` 로 재작성 - `UGUI/Manager/uScrollViewMgr.cs`, `uScrollViewArrMgr.cs` → 무한 스크롤 패턴 범용화 ## 10. 다음 작업 순서 | # | 작업 | 산출물 | |---|------|--------| | 1 | 본 설계안 PD님 검토 → 승인 | v1.1 고정 | | 2 | 수상한 잡화점 추출 대상 상세 문서화 | `02_수상한잡화점_추출대상_v1.md` | | 3 | PD님과 NAS Git 저장소 위치·접근 방식 협의 | 저장소 URL 확정 | | 4 | 패키지 스켈레톤 생성 (빈 폴더 + package.json + asmdef) | 공란 패키지 | | 5 | Tier 1 모듈 순차 구현 | 각 모듈별 PR/커밋 | | 6 | Tier 2 모듈 순차 구현 | | | 7 | 수상한 잡화점 개발 준비(Phase 0-B/C) 재개 | | | 8 | 서버팀 셋업 시점 Tier 3 합류 + 보안 Critical 3건 재기동 | `project_shop_security_pending.md` 참조 | ## 11. PD님 확정 사항 (2026-04-14) | # | 항목 | 확정값 | |---|------|--------| | 1 | 정식 명칭 | `BT.Framework` ✅ | | 2 | UPM 패키지 이름 | `com.nerdnavis.framework` ✅ | | 3 | `Goods` (재화 모델) | **Tier 2로 이관** (`BurningTimes.Economy`) ✅ | | 4 | UI 우선순위 | **UGUI 주력**, UI Toolkit은 보조(최소 유지) ✅ | | 5 | 저장소 위치 | PD님 NAS Git, 위 4항 확정 후 별도 협의 (진행 중) | ## 12. 잔여 의사결정 (진행 중) - **저장소 위치 / 접근 방식** — PD님 NAS Git. 위치·접근법 확정 필요 (스켈레톤 초기화 전 논의 필요) --- ## 부록 A. 변경 이력 - **v1 (2026-04-14)**: 초안. 기존 BurningTimesCore 85개 cs 파일 조사 + 수상한 잡화점 범용 패턴 1차 식별 기반. - **v1.1 (2026-04-14)**: PD님 결정 4건 반영 — 정식 명칭·UPM 이름 확정, Goods는 Tier 2로 이관(`BurningTimes.Economy` 신설), UGUI 주력·UI Toolkit 보조 원칙. - **v1.2 (2026-04-14)**: PD님 Tier 1 착수 지시(Logger·ServiceLocator·CoroutineRunner) 반영 — 섹션 4-9 ServiceLocator 설계 신설, Tier 1 모듈 목록에 ServiceLocator 추가. 기존 MonoSingleton·EventBus 설계는 유지되며 3축 역할 분리 원칙 명시.