feat(template): 범용 프로젝트 템플릿 17개 파일 생성 — 신규 프로젝트 기반 셋팅
기획 8개(게임컨셉·핵심재미·시스템·컨텐츠·밸런스·UX·수익화·라이브) + 개발 6개(아키텍처·기술스택·코딩컨벤션·데이터파이프라인·빌드배포·QA) + 관리 2개(시작체크리스트·Unity셋업가이드) + README. C7 게이트(재미정의 PD승인 전 착수금지), 보안 안티패턴 3건, NerdNavis.Framework C+H1 연동 절차, 시뮬레이터 이원화 방지 등 수상한잡화점 교훈을 구조적으로 내장. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
882a8ed339
commit
9ce50ce6cd
|
|
@ -0,0 +1,47 @@
|
|||
# 너드나비스 범용 프로젝트 템플릿
|
||||
|
||||
> **용도**: 신규 게임 프로젝트 시작 시 이 폴더를 복사하여 기반 구조를 빠르게 갖춘다.
|
||||
> **버전**: v1
|
||||
> **작성일**: 2026-04-16
|
||||
> **담당**: 개발팀장
|
||||
|
||||
---
|
||||
|
||||
## 사용법
|
||||
|
||||
1. `_템플릿/` 폴더를 `프로젝트/{프로젝트명}/`으로 복사
|
||||
2. 각 파일 내 `{프로젝트명}`, `{장르}`, `{ProjectNamespace}` 등 placeholder를 실제 값으로 치환
|
||||
3. `관리/프로젝트_시작_체크리스트.md`의 Phase 순서대로 진행
|
||||
4. 해당 프로젝트에 불필요한 섹션은 삭제 (C14 토큰 최소화)
|
||||
|
||||
---
|
||||
|
||||
## 작성 원칙
|
||||
|
||||
- **C7**: `기획/02_핵심_재미_정의.md`가 PD님 승인을 받기 전 03~08번 문서 착수 금지
|
||||
- **C9**: MVP/점진적 도입 등 타협 표현 사용 금지
|
||||
- **C15**: 일정/기한 표현("이번 주", "N일 내" 등) 사용 금지
|
||||
- 각 문서는 `_v1` 접미사로 시작, 변경 시 버전 증가
|
||||
- 버전 관리는 Git 커밋 이력 + 문서 내 버전 표기 병행
|
||||
|
||||
---
|
||||
|
||||
## 폴더 구조
|
||||
|
||||
| 폴더 | 내용 | 파일 수 |
|
||||
|------|------|--------|
|
||||
| `기획/` | 게임 기획 문서 (컨셉, 재미, 시스템, 컨텐츠, 밸런스, UX, 수익화, 라이브) | 8 |
|
||||
| `개발/` | 기술 문서 (아키텍처, 기술스택, 컨벤션, 데이터, 빌드, QA) | 6 |
|
||||
| `관리/` | 프로젝트 관리 (시작 체크리스트, Unity 셋업 가이드) | 2 |
|
||||
|
||||
---
|
||||
|
||||
## NerdNavis.Framework 연동
|
||||
|
||||
본 템플릿은 `com.nerdnavis.framework` (NerdNavis.Framework) 사용을 전제한다.
|
||||
연동 절차는 `관리/Unity_셋업_가이드.md` 참조.
|
||||
|
||||
- **패키지 이름**: `com.nerdnavis.framework`
|
||||
- **루트 네임스페이스**: `NerdNavis`
|
||||
- **배포 방식**: C+H1 (UPM Git URL + 로컬 file: 오버라이드)
|
||||
- **상세**: `관리/Unity_셋업_가이드.md` 섹션 2 참조
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
# {프로젝트명} — 아키텍처 설계
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 개발팀장
|
||||
> **적용 범위**: {프로젝트명} Unity 클라이언트
|
||||
|
||||
---
|
||||
|
||||
## 1. 프로젝트 기본 정보
|
||||
|
||||
| 항목 | 값 | 비고 |
|
||||
|------|-----|------|
|
||||
| **Unity 버전** | 6000.0.x 이상 (Unity 6 LTS) | 하위 버전 사용 시 팀장 확인 필수 |
|
||||
| **타겟 플랫폼** | Android(주), iOS, Windows(Editor) | {장르}에 따라 조정 |
|
||||
| **Scripting Backend** | IL2CPP | Android/iOS 공통 |
|
||||
| **API 호환성** | .NET Standard 2.1 | |
|
||||
| **NerdNavis.Framework 버전** | `com.nerdnavis.framework v0.x.y` | `관리/Unity_셋업_가이드.md` 참조 |
|
||||
| **렌더 파이프라인** | URP (기본) / Built-in (선택) | 착수 시 확정 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 어셈블리(asmdef) 구성
|
||||
|
||||
> ⚠️ **Assembly-CSharp 단일 어셈블리 금지** (수상한잡화점 교훈: asmdef 미적용으로 컴파일 시간 증가·의존성 관리 불가 문제 발생)
|
||||
|
||||
| asmdef | 경로 | 의존 |
|
||||
|--------|------|------|
|
||||
| `{ProjectNamespace}.Core` | `Assets/Scripts/{ProjectNamespace}/Core/` | NerdNavis.Framework.Runtime |
|
||||
| `{ProjectNamespace}.UI` | `Assets/Scripts/{ProjectNamespace}/UI/` | .Core |
|
||||
| `{ProjectNamespace}.Data` | `Assets/Scripts/{ProjectNamespace}/Data/` | .Core |
|
||||
| `{ProjectNamespace}.Server` | `Assets/Scripts/{ProjectNamespace}/Server/` | .Core |
|
||||
| `{ProjectNamespace}.Editor` | `Assets/Scripts/{ProjectNamespace}/Editor/` | .Core, NerdNavis.Framework.Editor (Editor only) |
|
||||
| `ThirdParty/` | `Assets/ThirdParty/` | 서드파티별 격리 |
|
||||
|
||||
**규칙**:
|
||||
- 각 asmdef는 자신의 역할 외 다른 도메인 코드를 포함하지 않는다
|
||||
- 순환 참조 금지 (Core ← UI ← Data ← Server 단방향)
|
||||
- 에디터 전용 코드는 반드시 `.Editor` asmdef로 분리
|
||||
|
||||
---
|
||||
|
||||
## 3. Assets 폴더 구조
|
||||
|
||||
```
|
||||
Assets/
|
||||
├── Scripts/
|
||||
│ └── {ProjectNamespace}/
|
||||
│ ├── Core/ ← 게임 매니저, 부트스트랩, 공통 모델
|
||||
│ ├── UI/ ← UI View, Panel, HUD
|
||||
│ ├── Data/ ← DataTable 서브클래스, DataLoader
|
||||
│ ├── Server/ ← 서버 통신 레이어 (INetworkService 구현)
|
||||
│ └── Editor/ ← 에디터 전용 도구
|
||||
├── Addressable/
|
||||
│ ├── Ingame/ ← 인게임 리소스 그룹
|
||||
│ ├── UI/ ← UI 리소스 그룹
|
||||
│ └── Audio/ ← 오디오 그룹
|
||||
├── Scenes/
|
||||
│ ├── 00_Bootstrap.unity
|
||||
│ └── ...
|
||||
├── Prefabs/
|
||||
├── Art/
|
||||
│ ├── Sprites/
|
||||
│ ├── Effects/
|
||||
│ └── Characters/
|
||||
├── Audio/
|
||||
│ ├── BGM/
|
||||
│ └── SFX/
|
||||
├── ThirdParty/ ← 서드파티 패키지 격리
|
||||
└── Editor/ ← 프로젝트 에디터 도구 (asmdef 없는 구역)
|
||||
```
|
||||
|
||||
**주의**: `Resources/` 폴더는 최소 사용. 동적 로딩은 Addressables로 대체한다.
|
||||
|
||||
---
|
||||
|
||||
## 4. 네임스페이스 체계
|
||||
|
||||
> ⚠️ **전역 네임스페이스(global) 사용 금지** (수상한잡화점 교훈: 클래스명 충돌 위험, 장기 리팩토링 부담)
|
||||
|
||||
```
|
||||
{ProjectNamespace} ← 루트 (공용 인터페이스, 공용 enum)
|
||||
│
|
||||
├── {ProjectNamespace}.Core ← 게임 매니저, 부트스트랩, 공통 도메인
|
||||
├── {ProjectNamespace}.UI ← UI View, Panel
|
||||
├── {ProjectNamespace}.Data ← DataTable 구현체, DataLoader
|
||||
├── {ProjectNamespace}.Server ← 서버 통신, Request/Response 래퍼
|
||||
└── {ProjectNamespace}.Editor ← 에디터 도구 (런타임 제외)
|
||||
```
|
||||
|
||||
**NerdNavis 네임스페이스와 분리 원칙**:
|
||||
- `NerdNavis.*` = 프레임워크 영역 (수정 불가)
|
||||
- `{ProjectNamespace}.*` = 프로젝트 전용 영역
|
||||
- 두 영역의 혼합 사용 금지
|
||||
|
||||
---
|
||||
|
||||
## 5. 매니저/시스템 목록
|
||||
|
||||
| 클래스 | 역할 | 라이프사이클 | Framework 의존 |
|
||||
|--------|------|-------------|---------------|
|
||||
| `GameManager` | 게임 전체 상태 관리, 씬 전환 총괄 | `MonoSingleton<T>` (Persistent) | ✅ |
|
||||
| `DataManager` | DataTable 로딩·캐시 관리 | `MonoSingleton<T>` (Persistent) | ✅ |
|
||||
| `UIManager` | UI View 스택·전환 관리 | `MonoSingleton<T>` (Persistent) | ✅ |
|
||||
| `AudioManager` | BGM/SFX 재생 | `NerdNavis.Audio` 위임 | ✅ |
|
||||
| `ServerManager` | 서버 통신 추상화 | `ServiceLocator` | ✅ |
|
||||
| `SaveManager` | 세이브/로드 | `ServiceLocator` + `NerdNavis.Save` | ✅ |
|
||||
| `{Game}Manager` | 핵심 게임 로직 매니저 ({장르} 특화) | `MonoSingleton<T>` or `ServiceLocator` | 상황별 |
|
||||
|
||||
**라이프사이클 선택 기준**:
|
||||
- `MonoSingleton<T>`: Update/OnDestroy 훅이 필요하거나 씬 생명주기와 동기화가 필요한 서비스
|
||||
- `ServiceLocator`: 순수 C# 서비스, 인터페이스 바인딩·테스트 대체가 필요한 서비스
|
||||
|
||||
---
|
||||
|
||||
## 6. 씬 구성
|
||||
|
||||
| 씬명 | 역할 | 로드 방식 |
|
||||
|------|------|----------|
|
||||
| `00_Bootstrap` | 앱 진입점, 초기화(Manager 셋업, DataTable 로딩) | Single (시작점) |
|
||||
| `01_Title` | 타이틀·로그인 화면 | Single |
|
||||
| `02_Main` | 메인 로비 | Single |
|
||||
| `03_Ingame` | 인게임(핵심 게임 루프) | Single or Additive |
|
||||
| `9x_Tool_*` | 개발용 도구 씬 (배포 빌드 씬 리스트 제외 필수) | Single |
|
||||
|
||||
**규칙**:
|
||||
- 배포 빌드에서 `9x_Tool_*` 씬은 Build Settings 씬 목록에서 **반드시 제외**
|
||||
- 씬 전환은 `GameManager`를 통해서만 수행 (직접 `SceneManager.LoadScene` 금지)
|
||||
|
||||
---
|
||||
|
||||
## 7. 서드파티 의존성
|
||||
|
||||
| 패키지 | 버전 | 용도 | 라이선스 |
|
||||
|--------|------|------|----------|
|
||||
| `com.unity.addressables` | 2.x | 리소스 번들 관리 | Unity |
|
||||
| `com.unity.nuget.newtonsoft-json` | 3.x | JSON 직렬화 | MIT |
|
||||
| `com.unity.render-pipelines.universal` | 17.x | URP 렌더링 | Unity |
|
||||
| `com.unity.textmeshpro` | (번들) | UI 텍스트 | Unity |
|
||||
| `(AntiCheatToolkit)` | 최신 | 메모리 변조 방어 | 구매 |
|
||||
| `{추가 서드파티}` | `{버전}` | `{용도}` | `{라이선스}` |
|
||||
|
||||
**서드파티 추가 규칙**:
|
||||
- 신규 서드파티 추가 시 `공유/` 채널에 라이선스·용도·대안 검토 결과를 기록 (P15)
|
||||
- `ThirdParty/` 폴더에 격리하여 프로젝트 코드와 물리적으로 분리
|
||||
|
||||
---
|
||||
|
||||
## 8. 열린 결정 항목
|
||||
|
||||
| 항목 | 선택지 | 현재 상태 |
|
||||
|------|--------|----------|
|
||||
| 렌더 파이프라인 | URP / Built-in | 미결 |
|
||||
| 백엔드 서비스 | PlayFab / GameSparks / 자체 서버 | 미결 |
|
||||
| DI 추가 도구 | ServiceLocator(Framework 내장) / VContainer | 미결 |
|
||||
| 비동기 패턴 | async/await + CoroutineRunner / UniTask | 미결 |
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 일자 | 작성자 | 내용 |
|
||||
|------|------|--------|------|
|
||||
| v1 | {날짜} | 개발팀장 | 템플릿 초안 |
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
# {프로젝트명} — 기술스택 결정
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 개발팀장
|
||||
> **적용 범위**: {프로젝트명} 전 개발 스택
|
||||
|
||||
---
|
||||
|
||||
## 1. 서버/백엔드
|
||||
|
||||
| 항목 | 선택 | 대안 | 근거 |
|
||||
|------|------|------|------|
|
||||
| **백엔드 서비스** | `{선택 예: PlayFab / 자체 서버}` | `{대안}` | `{선택 근거}` |
|
||||
| **인증 방식** | `{선택 예: 디바이스ID / 구글 로그인}` | `{대안}` | `{근거}` |
|
||||
| **실시간 통신** | `{선택 예: 불필요 / WebSocket}` | `{대안}` | `{근거}` |
|
||||
| **데이터 저장** | `{선택 예: 서버 계정 데이터 + 로컬 캐시}` | `{대안}` | `{근거}` |
|
||||
|
||||
**결정 미완료 항목**: 위 표에서 `{}`로 표기된 항목은 착수 전 팀장 확정 필수. 결정 후 이 섹션을 갱신한다.
|
||||
|
||||
---
|
||||
|
||||
## 2. 클라이언트 핵심 스택
|
||||
|
||||
| 영역 | 선택 | 비고 |
|
||||
|------|------|------|
|
||||
| **UI 시스템** | UGUI 주력, UIToolkit 보조 | NerdNavis.Framework 정책 (01_아키텍처_개요 참조) |
|
||||
| **리소스 관리** | Unity Addressables | Resources.Load 남용 금지 (03_코딩_컨벤션 참조) |
|
||||
| **JSON 라이브러리** | Newtonsoft.Json (Unity 패키지) | `com.unity.nuget.newtonsoft-json` |
|
||||
| **비동기 패턴** | async/await + `NerdNavis.Core.Coroutine.CoroutineRunner` | UniTask 도입 여부는 별도 결정 |
|
||||
| **DI** | `NerdNavis.Core.Patterns.ServiceLocator` | 인터페이스 기반 등록·조회 |
|
||||
| **이벤트** | `NerdNavis.Core.Event.EventBus` (타입 안전) | 문자열 키 이벤트 금지 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 🔴 보안 안티패턴 체크리스트
|
||||
|
||||
> **수상한잡화점 Critical 3건에서 도출된 필수 점검 항목.** 착수 전 개발팀장이 전수 검토하고, 해당 항목의 설계 결정을 이 섹션에 기록한다.
|
||||
|
||||
### 3.1 전투/핵심 연산 서버 검증
|
||||
|
||||
- [ ] **전투·핵심 게임 연산의 서버 검증 구조 확보 (100% 클라이언트 연산 금지)**
|
||||
- 위반 사례: 수상한잡화점 HP/Shield/Buff 전부 클라 계산 → 클라 변조 시 서버 검증 불가
|
||||
- 적용 방향: `{선택 예: 클리어 판정·보상 지급은 서버 재연산 / 최소 HMAC 서명 검증}`
|
||||
- 결정 상태: `{미결 / 완료}`
|
||||
|
||||
### 3.2 암호화 키 관리
|
||||
|
||||
- [ ] **암호화 키·비밀값 하드코딩 금지 (서버 측 키 관리 또는 환경변수)**
|
||||
- 위반 사례: 수상한잡화점 CryptoUtil.cs에 AES 키(32byte), IV(16byte) 평문 하드코딩
|
||||
- 적용 방향: `{선택 예: 런타임 디바이스ID 유도 키 / 서버 전달 키 / 환경변수}`
|
||||
- 결정 상태: `{미결 / 완료}`
|
||||
|
||||
### 3.3 IAP 영수증 서버 검증
|
||||
|
||||
- [ ] **IAP 영수증 서버 검증 필수 (클라이언트 단독 결제 처리 금지)**
|
||||
- 위반 사례: 수상한잡화점 영수증 검증 전부 주석처리 → 결제 우회 가능, 매출 직접 손실
|
||||
- 적용 방향: `{선택 예: PlayFab ValidateXXXReceipt API / 자체 서버 검증 엔드포인트}`
|
||||
- 결정 상태: `{미결 / 완료 / 해당 없음(IAP 미포함 프로젝트)}`
|
||||
|
||||
### 3.4 추가 보안 항목
|
||||
|
||||
- [ ] **SpeedHack/TimeCheck Detector 적용** (AntiCheatToolkit 또는 자체 구현)
|
||||
- [ ] **전투 스탯·재화·레벨 핵심 필드 `Obscured*` 적용** (AntiCheatToolkit 사용 시)
|
||||
- [ ] **빌드 시 JSON 평문 노출 대응** (APK 분해 시 데이터 테이블 노출 위험)
|
||||
|
||||
---
|
||||
|
||||
## 4. CI/CD
|
||||
|
||||
| 항목 | 선택 | 비고 |
|
||||
|------|------|------|
|
||||
| **버전 관리** | Git (main 브랜치 기준) | C18 조직 공유 완료 기준 |
|
||||
| **빌드 자동화** | `{선택 예: GitHub Actions / Jenkins / 수동}` | `{근거}` |
|
||||
| **배포 채널** | `{선택 예: Firebase App Distribution / TestFlight / 사내 공유}` | QA 배포용 |
|
||||
| **스토어 배포** | `{선택 예: 수동 / fastlane}` | Release 빌드 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 개발 도구
|
||||
|
||||
| 도구 | 용도 | 비고 |
|
||||
|------|------|------|
|
||||
| Claude Code (Claude Code) | 코드 생성·리뷰·문서 | NerdNavis 조직 표준 |
|
||||
| Unity MCP | Claude ↔ Unity Editor 연동 | `unity-mcp` 패키지 |
|
||||
| `{추가 도구}` | `{용도}` | |
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 일자 | 작성자 | 내용 |
|
||||
|------|------|--------|------|
|
||||
| v1 | {날짜} | 개발팀장 | 템플릿 초안. 보안 체크리스트 수상한잡화점 3건 반영 |
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
# {프로젝트명} — 코딩 컨벤션
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 개발팀장
|
||||
> **적용 범위**: {프로젝트명} 전 C# 코드
|
||||
|
||||
---
|
||||
|
||||
## 1. 네이밍 규칙
|
||||
|
||||
> 아래 규칙은 NerdNavis.Framework 아키텍처 설계안(네이밍 매핑표)을 기반으로 한다.
|
||||
> `My*` 접두사, `u*` 접두사, `Mgr` 접미사는 **전면 금지** (수상한잡화점 패턴 계승 금지).
|
||||
|
||||
| 대상 | 규칙 | 예시 |
|
||||
|------|------|------|
|
||||
| **네임스페이스** | PascalCase | `{ProjectNamespace}.Core` |
|
||||
| **클래스** | PascalCase | `GameManager`, `PlayerController` |
|
||||
| **인터페이스** | `I` + PascalCase | `ISaveProvider`, `INetworkService` |
|
||||
| **메서드** | PascalCase | `LoadData()`, `HandleDamage()` |
|
||||
| **프로퍼티** | PascalCase | `CurrentHp`, `IsGameOver` |
|
||||
| **private 필드** | `_` + camelCase | `_currentHp`, `_isInitialized` |
|
||||
| **const / static readonly** | SCREAMING_SNAKE_CASE | `MAX_HP`, `DEFAULT_TIMEOUT` |
|
||||
| **enum 타입** | PascalCase | `GameState`, `ItemType` |
|
||||
| **enum 값** | PascalCase | `GameState.Playing`, `ItemType.Weapon` |
|
||||
| **지역 변수** | camelCase | `int damage`, `string key` |
|
||||
| **이벤트 구조체(EventBus용)** | PascalCase + `Event` 접미사 | `PlayerDiedEvent`, `StageCompleteEvent` |
|
||||
|
||||
**금지 패턴**:
|
||||
- `My*` 접두사: `MyCoroutine` → `CoroutineRunner` 사용
|
||||
- `u*` 소문자 접두사: `uScrollViewMgr` → `ScrollViewController`
|
||||
- `Mgr` 접미사: `UIAtlasMgr` → `UIAtlasManager`
|
||||
- `Base` 접미사 (추상 클래스): `CustomParserBase` → `abstract class CustomParser`
|
||||
- `Info` 접미사 (데이터 클래스): `GachaGradeInfo` → `GachaGrade`
|
||||
- `Handler` 접미사 (스케줄러): `SchedulHandler` → `GameScheduler`
|
||||
|
||||
---
|
||||
|
||||
## 2. 파일 구조
|
||||
|
||||
```csharp
|
||||
// 헤더 주석 (선택, 복잡한 파일만)
|
||||
// 파일명: PlayerController.cs
|
||||
// 네임스페이스: {ProjectNamespace}.Core
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using NerdNavis.Core.Patterns; // Framework 참조는 using 으로만
|
||||
|
||||
namespace {ProjectNamespace}.Core
|
||||
{
|
||||
public class PlayerController : MonoBehaviour
|
||||
{
|
||||
// 1. 직렬화 필드 (Inspector)
|
||||
[SerializeField] private int _maxHp = 100;
|
||||
|
||||
// 2. private 필드
|
||||
private int _currentHp;
|
||||
|
||||
// 3. 프로퍼티
|
||||
public int CurrentHp => _currentHp;
|
||||
|
||||
// 4. Unity 라이프사이클 메서드 (Awake > Start > Update > ...)
|
||||
private void Awake() { }
|
||||
private void Start() { }
|
||||
|
||||
// 5. public 메서드
|
||||
public void TakeDamage(int amount) { }
|
||||
|
||||
// 6. private 메서드
|
||||
private void Die() { }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**규칙**:
|
||||
- 1파일 = 1클래스 (partial class 예외: 에디터 확장, 자동 생성 코드)
|
||||
- 파일명 = 클래스명 (대소문자 포함 일치)
|
||||
- 폴더 경로 ≈ 네임스페이스 구조
|
||||
|
||||
---
|
||||
|
||||
## 3. NerdNavis.Framework 사용 패턴
|
||||
|
||||
### 3.1 MonoSingleton<T> — MonoBehaviour 싱글톤
|
||||
|
||||
```csharp
|
||||
// 씬 라이프사이클과 동기화되는 서비스에 사용
|
||||
// Update/OnDestroy 훅이 필요한 경우
|
||||
public class GameManager : MonoSingleton<GameManager>
|
||||
{
|
||||
// [SingletonOption(Persistent = true)] 로 DontDestroyOnLoad 제어
|
||||
protected override void OnAwake()
|
||||
{
|
||||
// 초기화 코드
|
||||
}
|
||||
}
|
||||
|
||||
// 사용
|
||||
GameManager.Instance.StartGame();
|
||||
```
|
||||
|
||||
### 3.2 ServiceLocator — 순수 C# 서비스 DI
|
||||
|
||||
```csharp
|
||||
// MonoBehaviour와 독립된 서비스, 인터페이스 바인딩, 테스트 Mock 주입 시 사용
|
||||
// Bootstrap 씬에서 등록
|
||||
ServiceLocator.Register<ISaveProvider>(new JsonSaveProvider());
|
||||
ServiceLocator.Register<INetworkService>(new PlayFabNetworkService());
|
||||
|
||||
// 사용처
|
||||
var save = ServiceLocator.Resolve<ISaveProvider>();
|
||||
save.Save(playerData);
|
||||
|
||||
// 테스트 시 Mock 교체
|
||||
ServiceLocator.Register<ISaveProvider>(new MockSaveProvider());
|
||||
ServiceLocator.Clear(); // 테스트 후 정리
|
||||
```
|
||||
|
||||
**주의**: 인터페이스 타입으로만 등록·조회 (구체 타입 바인딩 시 결합도 상승).
|
||||
`Resolve` 실패 시 `ServiceNotRegisteredException` 발생 — silent null 금지.
|
||||
|
||||
### 3.3 CoroutineRunner — 전역 코루틴 관리
|
||||
|
||||
```csharp
|
||||
// 키 기반 중복 제어, 일시정지·재시작 지원
|
||||
// MonoBehaviour 없이 코루틴 실행 가능
|
||||
|
||||
// 시작 (키로 중복 방지)
|
||||
CoroutineRunner.Start("LoadData", LoadDataCoroutine());
|
||||
|
||||
// 중지
|
||||
CoroutineRunner.Stop("LoadData");
|
||||
|
||||
// 완료 시 자동 해제
|
||||
```
|
||||
|
||||
### 3.4 Log — 중앙 로거
|
||||
|
||||
```csharp
|
||||
// Debug.Log 직접 호출 금지 → Log 클래스 사용
|
||||
Log.Info("GameManager", "게임 시작");
|
||||
Log.Warn("DataManager", $"데이터 키 없음: {key}");
|
||||
Log.Error("ServerManager", "서버 연결 실패", exception);
|
||||
|
||||
// 카테고리 필터링 → 빌드 변형별 로그 레벨 제어 가능
|
||||
```
|
||||
|
||||
### 3.5 EventBus — 타입 안전 이벤트
|
||||
|
||||
```csharp
|
||||
// 이벤트 정의 (struct 권장)
|
||||
public struct PlayerDiedEvent
|
||||
{
|
||||
public int PlayerId;
|
||||
public string Cause;
|
||||
}
|
||||
|
||||
// 구독
|
||||
EventBus.Subscribe<PlayerDiedEvent>(OnPlayerDied);
|
||||
private void OnPlayerDied(PlayerDiedEvent e) { /* ... */ }
|
||||
|
||||
// 발행
|
||||
EventBus.Publish(new PlayerDiedEvent { PlayerId = 1, Cause = "Fall" });
|
||||
|
||||
// 구독 해제 (OnDestroy에서 반드시 해제)
|
||||
EventBus.Unsubscribe<PlayerDiedEvent>(OnPlayerDied);
|
||||
```
|
||||
|
||||
**금지**: 문자열 키 이벤트 (`EventBus.Raw` 하위 특수 용도만 허용).
|
||||
|
||||
---
|
||||
|
||||
## 4. 금지 사항
|
||||
|
||||
| 금지 항목 | 사유 | 대안 |
|
||||
|-----------|------|------|
|
||||
| **수치 하드코딩** | 수정 시 코드 수정 필요, 기획-개발 분리 파괴 | DataTable 참조 (04_데이터_파이프라인 참조) |
|
||||
| **암호키 평문 하드코딩** | IL2CPP 빌드도 메모리 덤프로 추출 가능 (수상한잡화점 Critical) | 서버 측 키 관리 또는 런타임 유도 (02_기술스택 참조) |
|
||||
| **`Resources.Load` 남용** | 빌드 시 모든 Resources/ 포함 → 빌드 크기 증가 | Addressables |
|
||||
| **문자열 이벤트 키** | 컴파일 타임 검증 불가, 오타 런타임 버그 | `EventBus<TEvent>` 타입 이벤트 |
|
||||
| **`Find` / `FindWithTag` 게임 로직** | 씬 오브젝트 의존, 테스트 불가 | 직접 참조 or ServiceLocator |
|
||||
| **`My*` / `u*` 접두사** | 비표준, 가독성 저하 | 표준 네이밍 규칙(섹션 1) |
|
||||
| **`Assembly-CSharp` 단일 어셈블리** | 컴파일 시간 증가, 의존성 관리 불가 (수상한잡화점 교훈) | asmdef 분리 (01_아키텍처_설계 참조) |
|
||||
| **전역 네임스페이스** | 클래스명 충돌 위험 | `{ProjectNamespace}.*` 체계 |
|
||||
| **`Debug.Log` 직접 호출 (배포 코드)** | 릴리스 빌드 로그 노출 | `Log.Info/Warn/Error` |
|
||||
|
||||
---
|
||||
|
||||
## 5. Git 커밋 메시지
|
||||
|
||||
```
|
||||
{type}: {summary}
|
||||
|
||||
[optional body]
|
||||
```
|
||||
|
||||
| type | 용도 |
|
||||
|------|------|
|
||||
| `feat` | 신규 기능 추가 |
|
||||
| `fix` | 버그 수정 |
|
||||
| `refactor` | 기능 변경 없는 코드 구조 개선 |
|
||||
| `docs` | 문서 변경 |
|
||||
| `test` | 테스트 추가/수정 |
|
||||
| `chore` | 빌드·설정·의존성 변경 |
|
||||
| `data` | 데이터 테이블 변경 |
|
||||
|
||||
**예시**:
|
||||
```
|
||||
feat: 전투 데미지 계산 서버 검증 구조 추가
|
||||
fix: DataTable 로딩 완료 확인 타이밍 버그 수정
|
||||
refactor: UIManager 씬 전환 로직 분리
|
||||
data: CardList 밸런스 조정 반영 (기획팀 승인)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 일자 | 작성자 | 내용 |
|
||||
|------|------|--------|------|
|
||||
| v1 | {날짜} | 개발팀장 | 템플릿 초안. Framework 3축(MonoSingleton·ServiceLocator·EventBus) 패턴 정립 |
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
# {프로젝트명} — 데이터 파이프라인
|
||||
|
||||
> **버전**: 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 베이스 클래스 (NerdNavis.Framework 활용)
|
||||
|
||||
```csharp
|
||||
// NerdNavis.Core.Data.DataTable 기반 — 직접 상속
|
||||
// 프로젝트별 테이블은 아래 패턴으로 구현
|
||||
|
||||
using NerdNavis.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;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**수상한잡화점 교훈 — 금지 패턴**:
|
||||
```csharp
|
||||
// 금지: 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 연동 로딩 |
|
||||
|
||||
**초기화 라이프사이클 (수상한잡화점 패턴 계승)**:
|
||||
```csharp
|
||||
// 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 런타임 검증 (개발 빌드 전용)
|
||||
|
||||
```csharp
|
||||
// 개발 빌드에서만 실행되는 검증 코드
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
DataValidator.ValidateAll();
|
||||
#endif
|
||||
```
|
||||
|
||||
### 5.3 테이블 버전 메타
|
||||
|
||||
```json
|
||||
{
|
||||
"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 | {날짜} | 개발팀장 | 템플릿 초안. 수상한잡화점 데이터 파이프라인 패턴 + 시뮬레이터 이원화 방지 규칙 반영 |
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
# {프로젝트명} — 빌드 및 배포
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 개발팀장
|
||||
> **적용 범위**: {프로젝트명} 빌드·배포 전 과정
|
||||
|
||||
---
|
||||
|
||||
## 1. 플랫폼별 빌드 설정
|
||||
|
||||
### 1.1 Android
|
||||
|
||||
| 항목 | 값 |
|
||||
|------|-----|
|
||||
| **Scripting Backend** | IL2CPP |
|
||||
| **Target Architecture** | ARM64 (필수), ARMv7 (선택 — 구형 기기 지원 시) |
|
||||
| **Minimum API Level** | Android 7.0 (API 24) 이상 권장 |
|
||||
| **Target API Level** | 최신 API (Play Store 정책 준수) |
|
||||
| **Internet Access** | Require |
|
||||
| **Custom Main Gradle Template** | 서드파티 요구 시 활성화 |
|
||||
| **Split APK / AAB** | 배포: AAB (Play Store), QA: APK |
|
||||
|
||||
**빌드 전 체크**:
|
||||
- [ ] KeyStore 파일 경로·비밀번호 확인 (릴리스 빌드)
|
||||
- [ ] `AndroidManifest.xml` 권한 최소화 검토
|
||||
- [ ] ANR·크래시 없음 (에뮬레이터 + 실기기 모두)
|
||||
|
||||
### 1.2 iOS
|
||||
|
||||
| 항목 | 값 |
|
||||
|------|-----|
|
||||
| **Scripting Backend** | IL2CPP |
|
||||
| **Target SDK** | Device SDK (배포), Simulator SDK (에뮬레이터 테스트) |
|
||||
| **Minimum iOS Version** | 14.0 이상 권장 |
|
||||
| **Signing** | Xcode Automatic Signing (Provisioning Profile) |
|
||||
|
||||
**빌드 전 체크**:
|
||||
- [ ] Apple 개발자 인증서·Provisioning Profile 유효기간 확인
|
||||
- [ ] `Info.plist` 권한 설명(NSPhotoLibraryUsageDescription 등) 입력
|
||||
- [ ] TestFlight 업로드 전 크래시 없음 확인
|
||||
|
||||
### 1.3 Windows (Editor/Standalone)
|
||||
|
||||
| 항목 | 값 |
|
||||
|------|-----|
|
||||
| **용도** | 개발 에디터 + Windows Standalone QA |
|
||||
| **Architecture** | x86_64 |
|
||||
| **Scripting Backend** | Mono (Editor), IL2CPP (Standalone 배포 시) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 빌드 변형(Build Variant)
|
||||
|
||||
| 변형 | 로그 레벨 | 치트 | 용도 | 컴파일 심볼 |
|
||||
|------|----------|------|------|------------|
|
||||
| **Dev** | 전체 (Info+Warn+Error) | 활성 | 개발 중 디버깅 | `DEVELOPMENT_BUILD`, `ENABLE_CHEATS` |
|
||||
| **QA** | 일부 (Warn+Error) | 활성 | QA 배포, 버그 재현 | `QA_BUILD`, `ENABLE_CHEATS` |
|
||||
| **Release** | 최소 (Error만) | 비활성 | 스토어 제출 | (없음, 기본) |
|
||||
|
||||
**컴파일 심볼 활용 예시**:
|
||||
```csharp
|
||||
#if ENABLE_CHEATS
|
||||
// 치트 메뉴, 수동 데이터 조작 코드
|
||||
#endif
|
||||
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
// 개발/에디터 전용 검증 코드
|
||||
DataValidator.ValidateAll();
|
||||
#endif
|
||||
```
|
||||
|
||||
**컴파일 심볼 관리**:
|
||||
- Player Settings > Other Settings > Scripting Define Symbols에서 설정
|
||||
- NerdNavis.Framework의 `NerdNavis.Editor.Symbols` 도구를 활용하여 변형별 심볼 일괄 전환
|
||||
|
||||
---
|
||||
|
||||
## 3. 버전 관리
|
||||
|
||||
**버전 체계**: `Major.Minor.Patch` (Semantic Versioning)
|
||||
|
||||
| 구성 | 변경 기준 |
|
||||
|------|----------|
|
||||
| **Major** | 하위 호환 불가한 대규모 변경, 새 게임 모드 추가 등 |
|
||||
| **Minor** | 새 기능 추가, 컨텐츠 업데이트 |
|
||||
| **Patch** | 버그 수정, 밸런스 조정 |
|
||||
|
||||
**빌드 넘버**: 각 빌드마다 자동 증가 (CI/CD 또는 Editor 스크립트로 자동화)
|
||||
|
||||
```csharp
|
||||
// NerdNavis.Editor.Build 도구 연동 또는 직접 구현
|
||||
// PlayerSettings.bundleVersion = "1.2.3"
|
||||
// PlayerSettings.Android.bundleVersionCode = 123 (Major*10000 + Minor*100 + Patch 권장)
|
||||
```
|
||||
|
||||
**스토어 정책**:
|
||||
- Android: `bundleVersionCode` 는 항상 단조 증가 (롤백 불가)
|
||||
- iOS: `Build Number` 항상 단조 증가
|
||||
|
||||
---
|
||||
|
||||
## 4. 배포 파이프라인
|
||||
|
||||
```
|
||||
[개발팀] 빌드 생성
|
||||
│
|
||||
▼
|
||||
코드 서명 (KeyStore / Apple Certificate)
|
||||
│
|
||||
▼
|
||||
업로드
|
||||
├── Dev/QA → Firebase App Distribution / TestFlight / 사내 공유
|
||||
└── Release → Google Play Console / App Store Connect
|
||||
│
|
||||
▼
|
||||
배포 완료 → 공유/일일보고 or PD 지시 로그 기록 (C13·P19)
|
||||
```
|
||||
|
||||
**자동화 목표**:
|
||||
- 빌드 트리거: Git 태그 push 또는 수동 트리거
|
||||
- 업로드 자동화: `{선택 예: fastlane / GitHub Actions / Jenkins}`
|
||||
- 배포 알림: 팀 내 채널 공유
|
||||
|
||||
---
|
||||
|
||||
## 5. 스토어 제출 체크리스트
|
||||
|
||||
### 5.1 공통 (Android / iOS 공통)
|
||||
|
||||
- [ ] **Release 빌드 변형** 으로 빌드 (ENABLE_CHEATS 없음 확인)
|
||||
- [ ] **빌드 번호** 이전 버전보다 증가했는지 확인
|
||||
- [ ] **콘솔 에러 없음** (P14: Unity 콘솔 에러 잔존 상태 배포 금지)
|
||||
- [ ] **크래시 없음** (실기기 최소 1대 이상 검증)
|
||||
- [ ] **IAP 영수증 서버 검증** 정상 동작 확인 (수상한잡화점 Critical 교훈)
|
||||
- [ ] **AES 키 하드코딩 없음** 확인 (소스 검색: `02_기술스택_결정 섹션 3.2 참조`)
|
||||
- [ ] **개발용 씬(`9x_Tool_*`) Build Settings에서 제외** 확인
|
||||
- [ ] **권한 요청** 최소화 및 사유 명시 (`Info.plist` / `AndroidManifest.xml`)
|
||||
- [ ] **개인정보처리방침 URL** 스토어 등록 완료
|
||||
|
||||
### 5.2 Android 추가
|
||||
|
||||
- [ ] **AAB 포맷** 제출 (APK 아님)
|
||||
- [ ] **Target API Level** Play Store 현행 정책 충족
|
||||
- [ ] **64-bit 지원** (ARM64 포함 빌드)
|
||||
|
||||
### 5.3 iOS 추가
|
||||
|
||||
- [ ] **TestFlight** 에서 베타 검증 완료
|
||||
- [ ] **Provisioning Profile** 유효기간 충분히 남음
|
||||
- [ ] **앱 심사 노트** 작성 (특수 기능 있는 경우)
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 일자 | 작성자 | 내용 |
|
||||
|------|------|--------|------|
|
||||
| v1 | {날짜} | 개발팀장 | 템플릿 초안. 수상한잡화점 Critical 3건 체크리스트 반영 |
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
# {프로젝트명} — QA 테스트 전략
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 개발팀장
|
||||
> **적용 범위**: {프로젝트명} 전 테스트 계층
|
||||
|
||||
---
|
||||
|
||||
## 1. 테스트 레이어
|
||||
|
||||
### 1.1 Unit Test — EditMode
|
||||
|
||||
> NerdNavis.Framework 자체 테스트와 동일 패턴 적용.
|
||||
|
||||
| 대상 | 예시 | 실행 모드 |
|
||||
|------|------|----------|
|
||||
| `ServiceLocator` | Register/Resolve/Clear 동작 | EditMode |
|
||||
| `Log` | 카테고리 필터링, 로그 레벨 분기 | EditMode |
|
||||
| DataTable 파싱 | JSON 역직렬화, null/범위 검증 | EditMode |
|
||||
| 순수 C# 비즈니스 로직 | 대미지 계산 공식, 확률 계산 | EditMode |
|
||||
|
||||
```csharp
|
||||
// EditMode 테스트 예시
|
||||
[TestFixture]
|
||||
public class ServiceLocatorTests
|
||||
{
|
||||
[SetUp]
|
||||
public void SetUp() => ServiceLocator.Clear();
|
||||
|
||||
[Test]
|
||||
public void Register_And_Resolve_ReturnsCorrectService()
|
||||
{
|
||||
var mock = new MockSaveProvider();
|
||||
ServiceLocator.Register<ISaveProvider>(mock);
|
||||
|
||||
var resolved = ServiceLocator.Resolve<ISaveProvider>();
|
||||
|
||||
Assert.AreEqual(mock, resolved);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 1.2 Unit Test — PlayMode
|
||||
|
||||
| 대상 | 예시 | 실행 모드 |
|
||||
|------|------|----------|
|
||||
| `MonoSingleton<T>` | Instance 생성, Persistent 동작 | PlayMode |
|
||||
| `CoroutineRunner` | Start/Stop, 키 중복 방지 | PlayMode |
|
||||
| UI View 전환 | UIManager Push/Pop 동작 | PlayMode |
|
||||
| 씬 로딩 | Bootstrap → Title 씬 전환 | PlayMode |
|
||||
|
||||
### 1.3 Integration Test
|
||||
|
||||
| 대상 | 내용 |
|
||||
|------|------|
|
||||
| DataTable 전체 로딩 | Bootstrap 씬 진입 → TableChecker.AllLoaded 확인 |
|
||||
| 서버 연동 E2E | 로그인 → 데이터 로딩 → 저장 → 재로그인 후 복원 |
|
||||
| 핵심 게임 루프 | {장르} 핵심 액션 1회 플레이 성공 (크래시·콘솔 에러 없음) |
|
||||
|
||||
### 1.4 Data Validation
|
||||
|
||||
DataTable의 무결성을 Export 시 + 런타임(개발 빌드) 에서 이중 검증한다.
|
||||
|
||||
```csharp
|
||||
// 04_데이터_파이프라인 섹션 5 참조
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
DataValidator.ValidateAll(); // FK 정합성, null, 범위
|
||||
#endif
|
||||
```
|
||||
|
||||
### 1.5 Manual QA
|
||||
|
||||
수동 QA는 5축 체크리스트(섹션 3)에 따라 수행한다.
|
||||
자동화 범위를 초과하는 UX 검증·디바이스 다양성·성능 체감은 수동 QA 영역이다.
|
||||
|
||||
---
|
||||
|
||||
## 2. 테스트 네이밍
|
||||
|
||||
> NerdNavis.Framework 테스트와 동일한 패턴 적용.
|
||||
|
||||
```
|
||||
{Method}_{Condition}_{Expected}
|
||||
```
|
||||
|
||||
| 구성 | 설명 | 예시 |
|
||||
|------|------|------|
|
||||
| `{Method}` | 테스트 대상 메서드/동작 | `TakeDamage` |
|
||||
| `{Condition}` | 입력 조건 | `WithMaxShield` |
|
||||
| `{Expected}` | 기대 결과 | `ReducesShieldFirst` |
|
||||
|
||||
**전체 예시**:
|
||||
```csharp
|
||||
[Test] public void TakeDamage_WithMaxShield_ReducesShieldFirst() { }
|
||||
[Test] public void TakeDamage_WhenHpIsZero_TriggersDeathEvent() { }
|
||||
[Test] public void GetOrNull_WithUnknownId_ReturnsNull() { }
|
||||
[Test] public void ServiceLocator_Resolve_WhenNotRegistered_ThrowsException() { }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. QA 체크리스트 프레임 (5축)
|
||||
|
||||
각 기능 머지 전 해당 5축 중 적용 항목을 확인한다 (P14 QA 게이트).
|
||||
|
||||
### 3.1 기능(Functional)
|
||||
|
||||
- [ ] 핵심 게임 루프 정상 동작 ({장르} 핵심 액션)
|
||||
- [ ] DataTable 로딩 완료 후 진행 (TableChecker.AllLoaded)
|
||||
- [ ] UI 전환 정상 동작 (화면맵 경로별)
|
||||
- [ ] 저장/로드 복원 일치
|
||||
- [ ] 서버 인증 정상 처리
|
||||
- [ ] 엣지 케이스: 재화 0, 최대치, 연속 탭 등
|
||||
|
||||
### 3.2 성능(Performance)
|
||||
|
||||
- [ ] 초기 로딩 체감 (Bootstrap → 첫 플레이 가능 시점)
|
||||
- [ ] 인게임 FPS 안정성 (목표 프레임 유지)
|
||||
- [ ] 메모리 증가 없음 (Profiler 확인)
|
||||
- [ ] GC Alloc 핫패스 없음 (Profiler Deep Profile)
|
||||
|
||||
### 3.3 메모리(Memory)
|
||||
|
||||
- [ ] 씬 전환 시 메모리 해제 확인 (Addressables Release)
|
||||
- [ ] 장시간 플레이 메모리 누수 없음
|
||||
- [ ] TextAsset 언로드 확인 (DataTable Awake 패턴)
|
||||
|
||||
### 3.4 네트워크(Network)
|
||||
|
||||
- [ ] 오프라인 상태 진입 처리 (에러 메시지 + 복구 흐름)
|
||||
- [ ] 느린 네트워크(3G 상당) 타임아웃 처리
|
||||
- [ ] 재연결 후 상태 복원
|
||||
- [ ] IAP 영수증 서버 검증 정상 처리 (해당 프로젝트)
|
||||
|
||||
### 3.5 보안(Security)
|
||||
|
||||
- [ ] 빌드에 하드코딩 키 없음 (`02_기술스택_결정 섹션 3.2`)
|
||||
- [ ] IAP 클라이언트 단독 결제 처리 경로 없음
|
||||
- [ ] SpeedHack/TimeCheck Detector 동작 확인 (해당 프로젝트)
|
||||
- [ ] 개발용 씬/치트 코드 릴리스 빌드에서 제거 확인
|
||||
|
||||
---
|
||||
|
||||
## 4. 자동화 범위
|
||||
|
||||
### 4.1 Framework 테스트 (기구현)
|
||||
|
||||
NerdNavis.Framework 패키지에 포함된 테스트. 프로젝트 도입 시 자동으로 사용 가능.
|
||||
|
||||
| 영역 | 테스트 유형 | 위치 |
|
||||
|------|-----------|------|
|
||||
| `MonoSingleton<T>` | PlayMode | `NerdNavis.Framework.Tests` |
|
||||
| `ServiceLocator` | EditMode | `NerdNavis.Framework.Tests` |
|
||||
| `CoroutineRunner` | PlayMode | `NerdNavis.Framework.Tests` |
|
||||
| `EventBus` | EditMode | `NerdNavis.Framework.Tests` |
|
||||
| `Log` | EditMode | `NerdNavis.Framework.Tests` |
|
||||
| `DataTable` 파싱 | EditMode | `NerdNavis.Framework.Tests` |
|
||||
|
||||
### 4.2 프로젝트 테스트 (프로젝트에서 추가)
|
||||
|
||||
| asmdef | 위치 | 내용 |
|
||||
|--------|------|------|
|
||||
| `{ProjectNamespace}.Tests` | `Assets/Tests/Runtime/` | PlayMode 통합 테스트 |
|
||||
| `{ProjectNamespace}.EditorTests` | `Assets/Tests/Editor/` | EditMode 단위 테스트 |
|
||||
|
||||
**asmdef 설정 예시**:
|
||||
```json
|
||||
// {ProjectNamespace}.Tests.asmdef
|
||||
{
|
||||
"name": "{ProjectNamespace}.Tests",
|
||||
"references": [
|
||||
"NerdNavis.Framework.Tests",
|
||||
"{ProjectNamespace}.Core",
|
||||
"UnityEngine.TestRunner",
|
||||
"UnityEditor.TestRunner"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"testPlatforms": ["PlayMode"]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 CI 자동화 실행 (해당 시)
|
||||
|
||||
```
|
||||
Git push → CI 트리거
|
||||
└── Unity Test Runner (EditMode + PlayMode)
|
||||
└── 결과 리포트 → 실패 시 머지 차단
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 버그 관리
|
||||
|
||||
| 심각도 | 기준 | 처리 |
|
||||
|--------|------|------|
|
||||
| **P0 Critical** | 크래시, 결제 실패, 데이터 손실 | 즉시 수정 (C2 근원 해결) |
|
||||
| **P1 High** | 핵심 기능 불가, 보안 이슈 | 현 개발 단계 완료 전 수정 |
|
||||
| **P2 Medium** | 기능 이상, 표시 오류 | 다음 개발 단계 전 수정 |
|
||||
| **P3 Low** | 미관, 텍스트 오탈자 | 여유 시 수정 |
|
||||
|
||||
**규칙**: P14에 따라 Unity 빌드 에러·콘솔 에러 잔존 상태로 작업 종료 금지.
|
||||
버그 수정 시 동일 경로의 회귀 검증 포함.
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 일자 | 작성자 | 내용 |
|
||||
|------|------|--------|------|
|
||||
| v1 | {날짜} | 개발팀장 | 템플릿 초안. Framework 테스트 패턴 + 5축 QA 체크리스트 정립 |
|
||||
|
|
@ -0,0 +1,308 @@
|
|||
# {프로젝트명} — Unity 셋업 가이드
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 개발팀장
|
||||
> **적용 범위**: 신규 PC에서 {프로젝트명} Unity 개발 환경 구축 + NerdNavis.Framework 연동
|
||||
|
||||
---
|
||||
|
||||
## 1. Unity 프로젝트 생성
|
||||
|
||||
### 1.1 Unity 버전
|
||||
|
||||
- **필수**: Unity 6000.0.x 이상 (Unity 6 LTS)
|
||||
- Unity Hub에서 `6000.0.x` 버전 설치 확인
|
||||
- 하위 버전 사용 시 개발팀장 확인 필수 (NerdNavis.Framework 호환성 보장 범위)
|
||||
|
||||
### 1.2 렌더 파이프라인 선택
|
||||
|
||||
| 선택지 | 권장 상황 |
|
||||
|--------|----------|
|
||||
| **URP (Universal Render Pipeline)** | 모바일 최적화, 셰이더 커스터마이즈 필요 시 (권장 기본값) |
|
||||
| **Built-in** | 서드파티 셰이더·플러그인이 URP 미지원인 경우 |
|
||||
|
||||
결정 후 `개발/01_아키텍처_설계.md 섹션 1`에 기록.
|
||||
|
||||
### 1.3 프로젝트 경로 규칙
|
||||
|
||||
```
|
||||
D:\NerdNavis\{프로젝트명}\ ← Unity 프로젝트 루트
|
||||
D:\NerdNavis\NerdNavisAi\ ← 조직 레포 (별도)
|
||||
D:\NerdNavis\NerdNavis.Framework\ ← Framework 레포 (로컬 개발용, 선택)
|
||||
```
|
||||
|
||||
**경로 규칙**:
|
||||
- 경로에 공백 금지 (Unity 빌드 도구 호환성)
|
||||
- 한글 경로 금지 (Android/iOS 빌드 오류 원인)
|
||||
|
||||
---
|
||||
|
||||
## 2. NerdNavis.Framework 연동 (C+H1)
|
||||
|
||||
> **배포 방식**: C+H1 — UPM Git URL (원격 기본) + 로컬 file: 오버라이드 (개발용)
|
||||
> **근거**: 03_배포방식_안건_v1.md — 목표 1·2·3 세 축 모두 최우위
|
||||
|
||||
### 2.1 기본 (원격 — 모든 PC)
|
||||
|
||||
`Packages/manifest.json` 에 다음 항목 추가:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"com.nerdnavis.framework": "https://burning.i234.me/NerdNavis/NerdNavis.Framework.git#v0.x.y",
|
||||
"com.unity.addressables": "2.4.4",
|
||||
"com.unity.nuget.newtonsoft-json": "3.2.1",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- `#v0.x.y` 부분을 실제 사용할 Framework 버전 태그로 교체 (예: `#v0.1.0`)
|
||||
- **브랜치 추적(`#main`) 금지** — 재현성 보장을 위해 반드시 태그 또는 커밋 SHA 고정
|
||||
|
||||
### 2.2 개발용 (로컬 오버라이드 — Framework 동시 개발 시만)
|
||||
|
||||
Framework 코드를 동시에 수정해야 하는 경우 로컬 경로로 오버라이드:
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"com.nerdnavis.framework": "file:../../NerdNavis.Framework"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> ⚠️ **로컬 오버라이드 커밋 금지**: 이 상태로 `manifest.json`을 커밋하면 다른 PC에서 빌드 실패.
|
||||
> 로컬 개발 완료 후 반드시 원격 URL로 복원 후 커밋.
|
||||
|
||||
**`.gitignore`에 추가 권장**:
|
||||
```
|
||||
# 로컬 manifest 오버라이드 (있는 경우)
|
||||
Packages/manifest.local.json
|
||||
```
|
||||
|
||||
### 2.3 Git 인증 (사내 Gitea)
|
||||
|
||||
Windows Credential Manager에 인증 정보 등록 (최초 1회):
|
||||
```
|
||||
git credential-manager configure
|
||||
# 또는 직접 입력 후 캐싱
|
||||
git clone https://burning.i234.me/NerdNavis/NerdNavis.Framework.git
|
||||
```
|
||||
|
||||
Package Manager가 자동으로 Windows Credential Manager를 사용하여 인증.
|
||||
|
||||
---
|
||||
|
||||
## 3. 프로젝트 설정
|
||||
|
||||
### 3.1 Player Settings
|
||||
|
||||
| 항목 | 값 |
|
||||
|------|-----|
|
||||
| **Company Name** | NerdNavis |
|
||||
| **Product Name** | {프로젝트명} |
|
||||
| **Bundle Identifier** | `com.nerdnavis.{프로젝트명소문자}` |
|
||||
| **Scripting Backend** | IL2CPP |
|
||||
| **API Compatibility Level** | .NET Standard 2.1 |
|
||||
| **Managed Stripping Level** | Minimal (개발), High (릴리스) |
|
||||
|
||||
### 3.2 필수 패키지 (Package Manager)
|
||||
|
||||
| 패키지 | 버전 | 용도 |
|
||||
|--------|------|------|
|
||||
| `com.unity.addressables` | 2.x 최신 | 리소스 번들 |
|
||||
| `com.unity.nuget.newtonsoft-json` | 3.x | JSON 직렬화 (DataTable) |
|
||||
| `com.unity.render-pipelines.universal` | 17.x | URP (선택한 경우) |
|
||||
| `com.unity.textmeshpro` | (번들 포함) | UI 텍스트 |
|
||||
|
||||
### 3.3 Quality Settings
|
||||
|
||||
- 모바일 타겟은 Quality Level을 "Medium" 이하로 시작 (실기기 테스트 후 조정)
|
||||
|
||||
---
|
||||
|
||||
## 4. Git 설정
|
||||
|
||||
### 4.1 .gitignore (Unity 표준)
|
||||
|
||||
프로젝트 루트에 `.gitignore` 생성:
|
||||
|
||||
```gitignore
|
||||
# Unity 생성 폴더
|
||||
[Ll]ibrary/
|
||||
[Tt]emp/
|
||||
[Oo]bj/
|
||||
[Bb]uild/
|
||||
[Bb]uilds/
|
||||
[Ll]ogs/
|
||||
[Mm]emoryCaptures/
|
||||
[Rr]ecordings/
|
||||
|
||||
# Unity Asset Database
|
||||
*.pidb.meta
|
||||
*.pdb.meta
|
||||
*.mdb.meta
|
||||
|
||||
# Unity 자동 생성 파일
|
||||
sysinfo.txt
|
||||
*.apk
|
||||
*.aab
|
||||
*.unitypackage
|
||||
*.app
|
||||
|
||||
# Visual Studio
|
||||
.vs/
|
||||
*.csproj
|
||||
*.sln
|
||||
*.suo
|
||||
*.tmp
|
||||
*.user
|
||||
*.userprefs
|
||||
*.pidb
|
||||
|
||||
# Rider
|
||||
.idea/
|
||||
|
||||
# OS 메타
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# NerdNavis 로컬 설정
|
||||
Packages/manifest.local.json
|
||||
```
|
||||
|
||||
### 4.2 .gitattributes (LFS)
|
||||
|
||||
대용량 바이너리 파일 LFS 관리:
|
||||
|
||||
```gitattributes
|
||||
# Unity
|
||||
*.meta merge=unityyamlmerge eol=lf
|
||||
*.unity merge=unityyamlmerge eol=lf
|
||||
*.prefab merge=unityyamlmerge eol=lf
|
||||
*.asset merge=unityyamlmerge eol=lf
|
||||
*.mat merge=unityyamlmerge eol=lf
|
||||
*.controller merge=unityyamlmerge eol=lf
|
||||
|
||||
# LFS — 바이너리 에셋
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
||||
*.psd filter=lfs diff=lfs merge=lfs -text
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||
*.fbx filter=lfs diff=lfs merge=lfs -text
|
||||
*.anim filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
*.xlsm filter=lfs diff=lfs merge=lfs -text
|
||||
*.xlsx filter=lfs diff=lfs merge=lfs -text
|
||||
```
|
||||
|
||||
**LFS 초기화** (최초 1회):
|
||||
```bash
|
||||
git lfs install
|
||||
git lfs track "*.png" "*.jpg" "*.wav" "*.mp3" "*.fbx" "*.psd"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 기본 코드 구조
|
||||
|
||||
### 5.1 Bootstrap 씬 구성
|
||||
|
||||
```
|
||||
00_Bootstrap.unity
|
||||
└── [Bootstrap] (GameObject)
|
||||
├── GameManager (MonoSingleton<GameManager>)
|
||||
├── DataManager (MonoSingleton<DataManager>)
|
||||
├── UIManager (MonoSingleton<UIManager>)
|
||||
└── ServiceLocatorBootstrap (MonoBehaviour)
|
||||
└── Awake()에서 ServiceLocator.Register<ISaveProvider>(...)
|
||||
```
|
||||
|
||||
### 5.2 asmdef 4개 생성
|
||||
|
||||
각 디렉토리에 asmdef 파일 생성:
|
||||
|
||||
```
|
||||
Assets/Scripts/{ProjectNamespace}/Core/{ProjectNamespace}.Core.asmdef
|
||||
Assets/Scripts/{ProjectNamespace}/UI/{ProjectNamespace}.UI.asmdef
|
||||
Assets/Scripts/{ProjectNamespace}/Data/{ProjectNamespace}.Data.asmdef
|
||||
Assets/Scripts/{ProjectNamespace}/Editor/{ProjectNamespace}.Editor.asmdef
|
||||
```
|
||||
|
||||
**Core asmdef 예시** (`{ProjectNamespace}.Core.asmdef`):
|
||||
```json
|
||||
{
|
||||
"name": "{ProjectNamespace}.Core",
|
||||
"references": [
|
||||
"NerdNavis.Framework.Runtime"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false
|
||||
}
|
||||
```
|
||||
|
||||
**Editor asmdef 예시** (`{ProjectNamespace}.Editor.asmdef`):
|
||||
```json
|
||||
{
|
||||
"name": "{ProjectNamespace}.Editor",
|
||||
"references": [
|
||||
"{ProjectNamespace}.Core",
|
||||
"NerdNavis.Framework.Runtime",
|
||||
"NerdNavis.Framework.Editor"
|
||||
],
|
||||
"includePlatforms": ["Editor"],
|
||||
"excludePlatforms": []
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 GameManager 기본 구현
|
||||
|
||||
```csharp
|
||||
using NerdNavis.Core.Patterns;
|
||||
|
||||
namespace {ProjectNamespace}.Core
|
||||
{
|
||||
public class GameManager : MonoSingleton<GameManager>
|
||||
{
|
||||
protected override void OnAwake()
|
||||
{
|
||||
Log.Info("GameManager", "초기화 시작");
|
||||
// 초기화 코드
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 셋업 검증 (6항 — 전체 통과 필수)
|
||||
|
||||
> **Phase 2 완료 기준**: 아래 6항 모두 체크 완료.
|
||||
> 하나라도 실패 시 원인 해결 후 재검증.
|
||||
|
||||
- [ ] **1. Framework 패키지 참조 확인** — Package Manager 창에서 `NerdNavis Framework` 표시됨
|
||||
- [ ] **2. 컴파일 오류 없음** — 콘솔 에러 0건 (경고는 검토 후 판단)
|
||||
- [ ] **3. Bootstrap 씬 Play → 콘솔 에러 없음** — Play 후 Console 확인
|
||||
- [ ] **4. MonoSingleton 인스턴스 생성 테스트** — `GameManager.Instance != null` 확인
|
||||
- [ ] **5. ServiceLocator Register/Resolve 테스트**
|
||||
```csharp
|
||||
// 테스트 코드 (에디터 또는 Unity Test Runner)
|
||||
ServiceLocator.Register<ISaveProvider>(new JsonSaveProvider());
|
||||
var resolved = ServiceLocator.Resolve<ISaveProvider>();
|
||||
Debug.Assert(resolved != null);
|
||||
```
|
||||
- [ ] **6. Log.Info/Log.Warn 출력 테스트** — 콘솔에 로그 출력 확인
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 일자 | 작성자 | 내용 |
|
||||
|------|------|--------|------|
|
||||
| v1 | {날짜} | 개발팀장 | 템플릿 초안. C+H1 배포 방식 + 셋업 검증 6항 정립 |
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
# {프로젝트명} — 프로젝트 시작 체크리스트
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 개발팀장 + 기획팀장
|
||||
> **용도**: 신규 프로젝트 착수 시 Phase 0~5를 순서대로 진행한다.
|
||||
|
||||
---
|
||||
|
||||
## Phase 개요
|
||||
|
||||
| Phase | 이름 | 완료 기준 |
|
||||
|-------|------|----------|
|
||||
| **Phase 0** | 프로젝트 생성 | 디렉토리 구조 + Git 초기화 완료 |
|
||||
| **Phase 1** | 핵심 기획 | `02_핵심_재미_정의.md` PD님 승인 |
|
||||
| **Phase 2** | 개발 환경 구축 | Framework 셋업 검증 6항 전체 통과 |
|
||||
| **Phase 3** | 데이터 기반 구성 | 데이터 1건 end-to-end 로드 성공 |
|
||||
| **Phase 4** | 프로토타입 | PD님 재미 확인 |
|
||||
| **Phase 5** | 본 개발 준비 | 전체 기반 완비 + PD님 최종 리뷰 |
|
||||
|
||||
> **C7 게이트**: `Phase 1`의 `02_핵심_재미_정의.md` PD님 승인 완료 전 `Phase 2~5` 착수 금지.
|
||||
> 재미 정의 없는 개발 환경 구축은 방향 없는 투자다.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: 프로젝트 생성
|
||||
|
||||
**완료 기준**: 디렉토리 구조 + Git 초기화 완료
|
||||
|
||||
### 0.1 템플릿 복사 및 치환
|
||||
|
||||
- [ ] `프로젝트/_템플릿/` 을 `프로젝트/{프로젝트명}/` 으로 복사
|
||||
- [ ] 모든 문서의 placeholder 치환:
|
||||
- `{프로젝트명}` → 실제 프로젝트명
|
||||
- `{ProjectNamespace}` → Unity 네임스페이스 (예: `MagicShop`)
|
||||
- `{장르}` → 게임 장르 (예: `로그라이크 덱빌딩`)
|
||||
- `{날짜}` → 작성일 (YYYY-MM-DD 형식)
|
||||
- [ ] 불필요한 섹션 삭제 (C14 토큰 최소화)
|
||||
|
||||
### 0.2 Git 레포 생성
|
||||
|
||||
- [ ] Gitea에 신규 레포 생성 (`NerdNavis/{프로젝트명}`)
|
||||
- [ ] 로컬 초기화: `git init && git remote add origin {레포 URL}`
|
||||
- [ ] `.gitignore` Unity 표준 템플릿 적용 (`관리/Unity_셋업_가이드.md 섹션 4`)
|
||||
- [ ] `.gitattributes` LFS 설정 적용 (`관리/Unity_셋업_가이드.md 섹션 4`)
|
||||
- [ ] 초기 커밋 + push (브랜치: `main`)
|
||||
|
||||
### 0.3 PD 지시 로그 초기화
|
||||
|
||||
- [ ] `공유/PD_지시_트래킹/{프로젝트명}_PD_지시_로그.md` 생성 (P19)
|
||||
- [ ] `공유/대화로그/{프로젝트명}/` 디렉토리 생성 (P24)
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: 핵심 기획
|
||||
|
||||
**완료 기준**: `02_핵심_재미_정의.md` PD님 승인
|
||||
|
||||
> ⚠️ **C7 게이트**: 02번 PD님 승인 전 Phase 2 착수 금지.
|
||||
|
||||
### 1.1 게임 컨셉 수립
|
||||
|
||||
- [ ] `기획/01_게임_컨셉.md` 작성 (기획팀장)
|
||||
- 한 줄 컨셉 (Elevator Pitch)
|
||||
- 레퍼런스 타이틀 3개 이상
|
||||
- 타겟 유저 정의
|
||||
- [ ] PD님 검토 후 방향 확정
|
||||
|
||||
### 1.2 핵심 재미 정의 (C7 게이트)
|
||||
|
||||
- [ ] `기획/02_핵심_재미_정의.md` 작성 (기획팀장)
|
||||
- "어떤 재미를 제공하는가" 명문화 (C7: 재미 정의 없는 진행 금지)
|
||||
- 핵심 게임 루프 다이어그램
|
||||
- 재미 검증 방법 (프로토타입 평가 기준)
|
||||
- [ ] **PD님 승인 획득** ← Phase 2 착수 조건
|
||||
|
||||
### 1.3 시스템·UX 초안
|
||||
|
||||
- [ ] `기획/03_시스템_카탈로그.md` 작성 (기획팀장) — 시스템 목록·우선순위
|
||||
- [ ] `기획/06_UX_화면맵.md` 작성 (기획팀장) — 화면 구성 초안
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: 개발 환경 구축
|
||||
|
||||
**완료 기준**: `관리/Unity_셋업_가이드.md` 셋업 검증 6항 전체 통과
|
||||
|
||||
> Phase 1 완료(PD님 승인) 후 착수.
|
||||
|
||||
### 2.1 Unity 프로젝트 생성
|
||||
|
||||
- [ ] Unity 6000.0.x 이상으로 신규 프로젝트 생성
|
||||
- [ ] 렌더 파이프라인 확정 (URP / Built-in)
|
||||
- [ ] 프로젝트 경로: `D:\NerdNavis\{프로젝트명}\`
|
||||
- [ ] `관리/Unity_셋업_가이드.md` 섹션 1 전체 수행
|
||||
|
||||
### 2.2 NerdNavis.Framework 연동
|
||||
|
||||
- [ ] `Packages/manifest.json` 에 Framework 항목 추가
|
||||
- [ ] `관리/Unity_셋업_가이드.md` 섹션 2 (C+H1) 수행
|
||||
- [ ] Package Manager에서 Import 확인
|
||||
|
||||
### 2.3 기술 문서 작성
|
||||
|
||||
- [ ] `개발/01_아키텍처_설계.md` — placeholder 치환 + 확정 항목 채우기
|
||||
- [ ] `개발/02_기술스택_결정.md` — 보안 체크리스트 3항 설계 결정 기입
|
||||
- [ ] `개발/03_코딩_컨벤션.md` — 팀 합의 후 확정
|
||||
|
||||
### 2.4 기본 코드 구조 생성
|
||||
|
||||
- [ ] Bootstrap 씬 생성 (`00_Bootstrap.unity`)
|
||||
- [ ] asmdef 4개 생성 (`{ProjectNamespace}.Core/.UI/.Data/.Editor`)
|
||||
- [ ] `GameManager` (MonoSingleton<T>) 기본 구현
|
||||
- [ ] `ServiceLocator` Bootstrap 등록 코드 작성
|
||||
|
||||
### 2.5 셋업 검증 (6항 전체 통과 필수)
|
||||
|
||||
- [ ] Framework 패키지 참조 확인 (Package Manager 창)
|
||||
- [ ] 컴파일 에러 없음
|
||||
- [ ] Bootstrap 씬 Play → 콘솔 에러 없음
|
||||
- [ ] MonoSingleton 인스턴스 생성 테스트 통과
|
||||
- [ ] ServiceLocator Register/Resolve 테스트 통과
|
||||
- [ ] Log.Info/Log.Warn 출력 테스트 통과
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: 데이터 기반 구성
|
||||
|
||||
**완료 기준**: 데이터 1건 end-to-end 로드 성공 (Excel → JSON → Unity 런타임)
|
||||
|
||||
> Phase 2 완료 후 착수.
|
||||
|
||||
### 3.1 컨텐츠 테이블 목록 확정
|
||||
|
||||
- [ ] `기획/04_컨텐츠.md` — 필요한 데이터 테이블 목록 초안 (기획팀장)
|
||||
- [ ] 개발팀장과 테이블 구조 합의
|
||||
|
||||
### 3.2 데이터 파이프라인 구성
|
||||
|
||||
- [ ] `개발/04_데이터_파이프라인.md` — SOT 포맷·경로·파싱 방식 확정
|
||||
- [ ] Excel 파일 생성 (SOT)
|
||||
- [ ] Export Tool 구현 또는 선택
|
||||
- [ ] JSON Export 경로 확정 (`Assets/ResWork/Table/Export/`)
|
||||
|
||||
### 3.3 DataTable 클래스 구현
|
||||
|
||||
- [ ] 첫 번째 테이블 `{TableName}TableData` + `{TableName}Table` 구현
|
||||
- [ ] `_orNull` 패턴 적용 확인 (Direct 인덱서 금지)
|
||||
|
||||
### 3.4 E2E 검증
|
||||
|
||||
- [ ] Excel 편집 → Export → Unity Play → DataTable.IsLoaded = true 확인
|
||||
- [ ] 테이블 데이터 1건 조회 성공
|
||||
- [ ] 데이터 무결성 검증 통과 (`DataValidator.ValidateAll()`)
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: 프로토타입
|
||||
|
||||
**완료 기준**: PD님 재미 확인
|
||||
|
||||
> Phase 3 완료 후 착수.
|
||||
|
||||
### 4.1 핵심 게임 루프 구현
|
||||
|
||||
- [ ] `02_핵심_재미_정의.md` 기반 핵심 인터랙션 1사이클 구현
|
||||
- [ ] 데이터 테이블 연동 (하드코딩 수치 사용 금지)
|
||||
- [ ] 기본 UI 연결 (UX 화면맵 초안 기반)
|
||||
|
||||
### 4.2 재미 검증
|
||||
|
||||
- [ ] 내부 플레이 테스트
|
||||
- [ ] `02_핵심_재미_정의.md`의 검증 기준 항목 대조 평가
|
||||
- [ ] **PD님 리뷰 + 재미 확인** ← Phase 5 착수 조건
|
||||
|
||||
### 4.3 밸런스 앵커 설정
|
||||
|
||||
- [ ] `기획/05_밸런스.md` — 핵심 수치 앵커 정의 (기획팀장)
|
||||
- [ ] 개발팀과 밸런스 데이터 테이블 연동 확인
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: 본 개발 준비
|
||||
|
||||
**완료 기준**: 전체 기반 완비 + PD님 최종 리뷰
|
||||
|
||||
> Phase 4 완료(PD님 재미 확인) 후 착수.
|
||||
|
||||
### 5.1 나머지 기획 문서 완성
|
||||
|
||||
- [ ] `기획/07_수익화.md` — 수익 모델 (PD님 확인 필요)
|
||||
- [ ] `기획/08_라이브.md` — 서비스·운영 계획 초안
|
||||
|
||||
### 5.2 개발 기반 문서 완성
|
||||
|
||||
- [ ] `개발/05_빌드_배포.md` — 배포 파이프라인 확정
|
||||
- [ ] `개발/06_QA_테스트_전략.md` — QA 게이트 기준 확정
|
||||
|
||||
### 5.3 보안 항목 완료
|
||||
|
||||
- [ ] `개발/02_기술스택_결정.md` 보안 체크리스트 3항 모두 설계 완료
|
||||
- [ ] IAP 서버 검증 구조 구현 또는 계획 확정
|
||||
- [ ] AES 키 서버 관리 방식 확정
|
||||
|
||||
### 5.4 PD님 최종 리뷰
|
||||
|
||||
- [ ] 전체 기획 문서 요약 보고
|
||||
- [ ] 기술 스택·보안 결정 사항 보고
|
||||
- [ ] **PD님 최종 승인** → 본 개발 착수
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 일자 | 작성자 | 내용 |
|
||||
|------|------|--------|------|
|
||||
| v1 | {날짜} | 개발팀장 | 템플릿 초안. Phase 0~5 체크리스트 + C7 게이트 반영 |
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
# {프로젝트명} — 게임 컨셉
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 기획팀장
|
||||
|
||||
---
|
||||
|
||||
## 1. 한 줄 요약
|
||||
|
||||
> {1문장으로 프로젝트 정체성 서술. 예: "X 장르에서 Y 메커니즘으로 Z 감정을 전달하는 게임"}
|
||||
|
||||
---
|
||||
|
||||
## 2. 기본 정보
|
||||
|
||||
| 항목 | 값 |
|
||||
|------|-----|
|
||||
| **장르** | {장르} |
|
||||
| **타겟 플랫폼** | {Android / iOS / PC / 크로스플랫폼} |
|
||||
| **세션 길이** | {N분 ~ N분} |
|
||||
| **타겟 유저** | {코어 / 미드코어 / 캐주얼} + {특성 서술} |
|
||||
| **레퍼런스 게임** | {게임명} — {참조하는 구체적 요소 명시} |
|
||||
|
||||
---
|
||||
|
||||
## 3. 핵심 게임 루프
|
||||
|
||||
```
|
||||
{행동} → {결과/피드백} → {보상} → {성장/변화} → 반복
|
||||
```
|
||||
|
||||
> 각 화살표는 유저가 체감하는 "다음 행동을 하고 싶은 이유"와 연결되어야 한다.
|
||||
|
||||
| 단계 | 유저 행동 | 시스템 반응 | 유저가 얻는 것 |
|
||||
|------|----------|------------|--------------|
|
||||
| 1 | {행동 서술} | {반응 서술} | {획득/감정} |
|
||||
| 2 | {행동 서술} | {반응 서술} | {획득/감정} |
|
||||
| 3 | {행동 서술} | {반응 서술} | {획득/감정} |
|
||||
|
||||
---
|
||||
|
||||
## 4. 차별점
|
||||
|
||||
> 시장 경쟁 대비 이 게임만의 고유 가치. "~와 비슷하지만 ~가 다르다" 형식 권장.
|
||||
|
||||
1. {차별점 1}: {경쟁작 대비 어떻게 다른가}
|
||||
2. {차별점 2}: {경쟁작 대비 어떻게 다른가}
|
||||
3. {차별점 3}: {경쟁작 대비 어떻게 다른가}
|
||||
|
||||
---
|
||||
|
||||
## 5. 열린 결정 항목
|
||||
|
||||
> PD님 결정이 필요한 방향성 안건. 설계 진행 전 반드시 해소해야 할 항목을 등록한다.
|
||||
|
||||
| # | 항목 | 배경 | PD님 결정 필요 시점 |
|
||||
|---|------|------|-------------------|
|
||||
| 1 | {결정 필요 항목} | {왜 결정이 필요한가} | {Phase N / 특정 설계 착수 전} |
|
||||
| 2 | {결정 필요 항목} | {왜 결정이 필요한가} | {Phase N / 특정 설계 착수 전} |
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
# {프로젝트명} — 핵심 재미 정의
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 기획팀장
|
||||
|
||||
---
|
||||
|
||||
> ⚠️ **C7 게이트 — 착수 금지**
|
||||
> 본 문서가 PD님 승인을 받기 전에는 03~08번 문서의 착수를 금지한다.
|
||||
> (C7 재미 우선 원칙: 재미 정의 없는 수치 조정·시스템 설계·컨텐츠 설계는 허용하지 않는다.)
|
||||
>
|
||||
> **승인 상태**: `미승인` / `승인 (날짜: {YYYY-MM-DD})`
|
||||
|
||||
---
|
||||
|
||||
## 1. 핵심 재미 (정확히 1개)
|
||||
|
||||
> 2개 이상 금지. 복수의 후보가 있다면 수렴 논의 후 1개만 남긴다.
|
||||
|
||||
**"{핵심 재미를 한 문구로 정의}"**
|
||||
|
||||
> 작성 지침: 유저가 "또 하고 싶다"고 느끼는 감정적 순간을 동사+목적어로 압축한다.
|
||||
> 예시 형식: "예상을 뒤엎는 조합이 터지는 순간의 쾌감"
|
||||
|
||||
---
|
||||
|
||||
## 2. 구체 발현 테이블
|
||||
|
||||
> 핵심 재미가 실제 플레이에서 어떻게 나타나는지 구체화한다. 3행 이상 필수.
|
||||
|
||||
| 상황 | 유저 감정 | 이를 유발하는 게임 메커니즘 |
|
||||
|------|----------|--------------------------|
|
||||
| {플레이 상황 1} | {감정 서술} | {어떤 메커니즘이 이 감정을 만드는가} |
|
||||
| {플레이 상황 2} | {감정 서술} | {어떤 메커니즘이 이 감정을 만드는가} |
|
||||
| {플레이 상황 3} | {감정 서술} | {어떤 메커니즘이 이 감정을 만드는가} |
|
||||
|
||||
---
|
||||
|
||||
## 3. 보조 재미 (최대 2개)
|
||||
|
||||
> 핵심 재미를 보강하는 부차적 재미. 핵심 재미와 방향이 일치해야 한다.
|
||||
|
||||
1. **{보조 재미 A}**: {핵심 재미와의 연결 관계}
|
||||
2. **{보조 재미 B}**: {핵심 재미와의 연결 관계}
|
||||
|
||||
---
|
||||
|
||||
## 4. 재미 판단 기준
|
||||
|
||||
> 모든 기획 결정은 아래 기준으로 판단한다. "재미 없어 보인다"는 직관이 아니라 **핵심 재미와의 연결 여부**로 판단한다.
|
||||
|
||||
| 판단 결과 | 기준 | 처리 |
|
||||
|----------|------|------|
|
||||
| **채택** | 이 결정이 핵심 재미를 **강화**한다 | 진행 |
|
||||
| **기각** | 이 결정이 핵심 재미를 **약화**시킨다 | 기각 (기술적·효율적 근거가 있어도) |
|
||||
| **효율 판단** | 이 결정이 핵심 재미와 **무관**하다 | 비용·공수 관점에서 결정 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 재미 안티패턴
|
||||
|
||||
> 이 게임에서 **하지 말아야 할 것**. 핵심 재미와 충돌하거나 희석시키는 패턴 목록.
|
||||
|
||||
1. {안티패턴 1}: {왜 이것이 핵심 재미를 해치는가}
|
||||
2. {안티패턴 2}: {왜 이것이 핵심 재미를 해치는가}
|
||||
3. {안티패턴 3}: {왜 이것이 핵심 재미를 해치는가}
|
||||
|
||||
---
|
||||
|
||||
## 6. 검증 방법
|
||||
|
||||
> 각 개발 단계에서 핵심 재미가 실제로 전달되고 있는지 확인하는 방법.
|
||||
|
||||
| 단계 | 검증 방식 | 기대 신호 | 실패 신호 |
|
||||
|------|----------|----------|----------|
|
||||
| **프로토타입** | {검증 방법} | {성공 시 나타나는 반응} | {실패 시 나타나는 반응} |
|
||||
| **알파** | {검증 방법} | {성공 시 나타나는 반응} | {실패 시 나타나는 반응} |
|
||||
| **베타** | {검증 방법} | {성공 시 나타나는 반응} | {실패 시 나타나는 반응} |
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
# {프로젝트명} — 시스템 설계
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 기획팀장
|
||||
>
|
||||
> **선행 조건**: `02_핵심_재미_정의.md` PD님 승인 완료 (C7 게이트 통과) 후 착수
|
||||
|
||||
---
|
||||
|
||||
## 1. 시스템 카탈로그
|
||||
|
||||
> 게임을 구성하는 모든 시스템을 나열하고 우선순위를 정한다.
|
||||
|
||||
| 시스템명 | 재미 기여도 | 우선순위 | 설계 상태 |
|
||||
|---------|-----------|---------|---------|
|
||||
| {시스템 A} | 직접 (핵심 재미 직결) | 1 | 미착수 |
|
||||
| {시스템 B} | 간접 (핵심 재미 보강) | 2 | 미착수 |
|
||||
| {시스템 C} | 인프라 (다른 시스템 지원) | 3 | 미착수 |
|
||||
|
||||
> 재미 기여도 분류:
|
||||
> - **직접**: 핵심 재미가 발생하는 시스템 자체
|
||||
> - **간접**: 핵심 재미의 맥락·깊이를 더하는 시스템
|
||||
> - **인프라**: 게임 운용에 필요하나 재미와 직결되지 않는 시스템
|
||||
|
||||
---
|
||||
|
||||
## 2. 시스템별 상세
|
||||
|
||||
---
|
||||
|
||||
### 2-1. {시스템 A}
|
||||
|
||||
**목적**: {핵심 재미(02번 문서)와 어떻게 연결되는가}
|
||||
|
||||
**기본 메커니즘**:
|
||||
|
||||
{시스템이 어떻게 동작하는지 서술. 유저의 행동과 시스템 응답을 중심으로}
|
||||
|
||||
**데이터 파라미터**:
|
||||
|
||||
| 파라미터 | 기준값 | SOT 테이블 | 비고 |
|
||||
|---------|-------|-----------|------|
|
||||
| {파라미터명} | {기준값} | {데이터 테이블명} | {조정 가능 범위 등} |
|
||||
| {파라미터명} | {기준값} | {데이터 테이블명} | {조정 가능 범위 등} |
|
||||
|
||||
**상태 전이**:
|
||||
|
||||
```
|
||||
{초기 상태} → {트리거: 유저 행동/조건} → {결과 상태}
|
||||
↓
|
||||
{예외 처리 경로}
|
||||
```
|
||||
|
||||
**시스템 간 상호작용**:
|
||||
|
||||
| 대상 시스템 | 상호작용 유형 | 방향 |
|
||||
|-----------|-------------|------|
|
||||
| {시스템명} | {데이터 공유 / 이벤트 발행 / 상태 참조} | {A→B / B→A / 양방향} |
|
||||
|
||||
---
|
||||
|
||||
### 2-2. {시스템 B}
|
||||
|
||||
**목적**: {핵심 재미(02번 문서)와 어떻게 연결되는가}
|
||||
|
||||
**기본 메커니즘**:
|
||||
|
||||
{시스템이 어떻게 동작하는지 서술}
|
||||
|
||||
**데이터 파라미터**:
|
||||
|
||||
| 파라미터 | 기준값 | SOT 테이블 | 비고 |
|
||||
|---------|-------|-----------|------|
|
||||
| {파라미터명} | {기준값} | {데이터 테이블명} | {비고} |
|
||||
|
||||
**상태 전이**:
|
||||
|
||||
```
|
||||
{초기 상태} → {트리거} → {결과 상태}
|
||||
```
|
||||
|
||||
**시스템 간 상호작용**:
|
||||
|
||||
| 대상 시스템 | 상호작용 유형 | 방향 |
|
||||
|-----------|-------------|------|
|
||||
| {시스템명} | {유형} | {방향} |
|
||||
|
||||
---
|
||||
|
||||
## 3. 열린 결정 항목
|
||||
|
||||
| # | 항목 | 배경 | PD님 결정 필요 시점 |
|
||||
|---|------|------|-------------------|
|
||||
| 1 | {결정 필요 항목} | {왜 결정이 필요한가} | {Phase N / 특정 설계 착수 전} |
|
||||
| 2 | {결정 필요 항목} | {왜 결정이 필요한가} | {Phase N / 특정 설계 착수 전} |
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
# {프로젝트명} — 컨텐츠 설계
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 기획팀장
|
||||
>
|
||||
> **선행 조건**: `02_핵심_재미_정의.md` PD님 승인 완료 (C7 게이트 통과) 후 착수
|
||||
|
||||
---
|
||||
|
||||
## 1. 컨텐츠 카테고리 맵
|
||||
|
||||
> 이 게임에 존재하는 모든 컨텐츠 유형을 분류한다. 각 카테고리는 하나의 데이터 테이블로 관리된다.
|
||||
|
||||
| 카테고리 | 설명 | 예상 볼륨 | SOT 테이블명 |
|
||||
|---------|------|---------|------------|
|
||||
| {카테고리 A} | {이 카테고리가 포함하는 컨텐츠 설명} | {~N종} | {테이블명.xlsx/json} |
|
||||
| {카테고리 B} | {이 카테고리가 포함하는 컨텐츠 설명} | {~N종} | {테이블명.xlsx/json} |
|
||||
| {카테고리 C} | {이 카테고리가 포함하는 컨텐츠 설명} | {~N종} | {테이블명.xlsx/json} |
|
||||
|
||||
---
|
||||
|
||||
## 2. 카테고리별 상세
|
||||
|
||||
---
|
||||
|
||||
### 2-1. {카테고리 A}
|
||||
|
||||
**구조 설명**:
|
||||
|
||||
{이 카테고리의 컨텐츠가 어떤 구조로 구성되는가. 유저가 어떻게 접하는가}
|
||||
|
||||
**ID 규칙**:
|
||||
|
||||
```
|
||||
{카테고리 접두사}_{분류 코드}_{일련번호}
|
||||
예: {A_001, B_01_003 등 구체적 패턴 서술}
|
||||
```
|
||||
|
||||
**필드 구조 (주요 컬럼)**:
|
||||
|
||||
| 컬럼명 | 타입 | 설명 | 필수 |
|
||||
|-------|------|------|------|
|
||||
| id | string | 고유 식별자 (ID 규칙 준수) | ✅ |
|
||||
| name | string | 표시 이름 | ✅ |
|
||||
| {필드명} | {타입} | {설명} | {✅/선택} |
|
||||
| {필드명} | {타입} | {설명} | {✅/선택} |
|
||||
|
||||
---
|
||||
|
||||
### 2-2. {카테고리 B}
|
||||
|
||||
**구조 설명**:
|
||||
|
||||
{이 카테고리의 컨텐츠 구조 서술}
|
||||
|
||||
**ID 규칙**:
|
||||
|
||||
```
|
||||
{ID 패턴 서술}
|
||||
```
|
||||
|
||||
**필드 구조 (주요 컬럼)**:
|
||||
|
||||
| 컬럼명 | 타입 | 설명 | 필수 |
|
||||
|-------|------|------|------|
|
||||
| id | string | 고유 식별자 | ✅ |
|
||||
| name | string | 표시 이름 | ✅ |
|
||||
| {필드명} | {타입} | {설명} | {✅/선택} |
|
||||
|
||||
---
|
||||
|
||||
## 3. 데이터 테이블 마스터 목록
|
||||
|
||||
> 이 게임의 모든 데이터 테이블 목록. 추가/삭제 시 본 목록을 SOT로 갱신한다.
|
||||
|
||||
| 테이블명 | 주요 컬럼 | 행 수(추정) | SOT 포맷 | 비고 |
|
||||
|---------|---------|-----------|---------|------|
|
||||
| {테이블 A} | id, name, {컬럼들} | ~{N}행 | Excel / JSON | {비고} |
|
||||
| {테이블 B} | id, name, {컬럼들} | ~{N}행 | Excel / JSON | {비고} |
|
||||
| {테이블 C} | id, name, {컬럼들} | ~{N}행 | Excel / JSON | {비고} |
|
||||
|
||||
> **SOT 포맷 선택 기준**:
|
||||
> - **Excel**: 기획자가 직접 편집하는 수치/내용 테이블
|
||||
> - **JSON**: 런타임 직접 로드, 빌드 자동화 대상 테이블
|
||||
> - 동일 데이터를 두 포맷으로 이중 관리하는 경우 **반드시 한쪽을 SOT로 지정**하고 다른 쪽은 생성(변환) 파일로 표시한다
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
# {프로젝트명} — 밸런스 프레임워크
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 기획팀장
|
||||
>
|
||||
> **선행 조건**: `02_핵심_재미_정의.md` PD님 승인 완료 (C7 게이트 통과) + `03_시스템_설계.md` 초안 완료 후 착수
|
||||
|
||||
---
|
||||
|
||||
## 1. 밸런싱 철학
|
||||
|
||||
> 밸런싱의 목적은 수치 균형이 아니라 **핵심 재미의 보장**이다.
|
||||
> 참조: [`02_핵심_재미_정의.md`](./02_핵심_재미_정의.md) — 핵심 재미 정의 및 재미 판단 기준
|
||||
|
||||
**이 게임의 밸런싱이 달성해야 할 상태**:
|
||||
|
||||
1. {핵심 재미와 연결된 밸런싱 목표 1}
|
||||
2. {핵심 재미와 연결된 밸런싱 목표 2}
|
||||
3. {핵심 재미와 연결된 밸런싱 목표 3}
|
||||
|
||||
**밸런싱 금지 패턴**:
|
||||
|
||||
- {이 게임에서 피해야 할 밸런싱 실수 1}
|
||||
- {이 게임에서 피해야 할 밸런싱 실수 2}
|
||||
|
||||
---
|
||||
|
||||
## 2. 앵커 포인트
|
||||
|
||||
> 밸런싱의 기준점. 모든 수치는 앵커에서 상대적으로 산출된다.
|
||||
> **앵커는 단 하나여야 한다.** 복수 앵커는 모순을 만든다.
|
||||
|
||||
| 앵커 항목 | 기준값 | 측정 방법 | SOT |
|
||||
|---------|-------|---------|-----|
|
||||
| {주 앵커: 예: "유저가 N회 시도 시 성공률"} | {기준값} | {어떻게 측정/검증하는가} | {데이터 테이블명} |
|
||||
|
||||
**앵커에서 파생되는 보조 기준값**:
|
||||
|
||||
| 항목 | 산식 | 기준값 |
|
||||
|------|------|-------|
|
||||
| {파생 항목 1} | {앵커 기준 산식} | {값} |
|
||||
| {파생 항목 2} | {앵커 기준 산식} | {값} |
|
||||
|
||||
---
|
||||
|
||||
## 3. 밸런싱 순서
|
||||
|
||||
> 시스템 간 종속 관계에 따라 밸런싱 순서를 정한다.
|
||||
> 종속 관계를 무시하고 병렬 밸런싱하면 후반에 전체를 재조정해야 한다.
|
||||
|
||||
```
|
||||
[1단계] {기초 프레임 확정}
|
||||
└─ {예: 앵커 수치 고정, 기본 전투/루프 수치 설정}
|
||||
|
||||
[2단계] {핵심 시스템 밸런싱}
|
||||
└─ {예: 핵심 재미가 발생하는 시스템의 주요 파라미터}
|
||||
|
||||
[3단계] {보조 시스템 조정}
|
||||
└─ {예: 보상·성장·경제 시스템을 핵심 시스템에 맞게 조정}
|
||||
|
||||
[4단계] {컨텐츠 단위 검증}
|
||||
└─ {예: 개별 컨텐츠 수치를 프레임 내에서 검증}
|
||||
```
|
||||
|
||||
**단계 간 전환 조건**:
|
||||
|
||||
| 전환 | 조건 |
|
||||
|------|------|
|
||||
| 1단계 → 2단계 | {충족해야 할 검증 기준} |
|
||||
| 2단계 → 3단계 | {충족해야 할 검증 기준} |
|
||||
| 3단계 → 4단계 | {충족해야 할 검증 기준} |
|
||||
|
||||
---
|
||||
|
||||
## 4. 시뮬레이션 전략
|
||||
|
||||
> ⚠️ **단일 시뮬레이터 원칙**
|
||||
> 런타임(게임 본체)과 시뮬레이터(외부 계산 도구)는 **반드시 동일한 데이터 소스를 사용**해야 한다.
|
||||
> 시뮬레이터가 별도 수치를 관리하면 "시뮬에서는 되는데 게임에서는 안 된다"는 이원화 문제가 발생한다.
|
||||
> **시뮬레이터 SOT = 런타임 SOT** (같은 테이블을 읽어야 한다)
|
||||
|
||||
| 대상 | 도구 | 검증 기준 | SOT 데이터 |
|
||||
|------|------|---------|----------|
|
||||
| {시뮬 대상 1} | {Python / Excel / 게임 내 도구 등} | {판단 기준} | {데이터 테이블명} |
|
||||
| {시뮬 대상 2} | {도구} | {판단 기준} | {데이터 테이블명} |
|
||||
|
||||
---
|
||||
|
||||
## 5. 핵심 수치 대시보드
|
||||
|
||||
> 밸런스 건강 상태를 모니터링하는 주요 지표. 이탈 발생 시 즉시 조정 착수.
|
||||
|
||||
| 지표 | 산식 | 정상 범위 | 이탈 시 조치 |
|
||||
|------|------|---------|------------|
|
||||
| {지표 1} | {산식} | {하한 ~ 상한} | {조정 방향} |
|
||||
| {지표 2} | {산식} | {하한 ~ 상한} | {조정 방향} |
|
||||
| {지표 3} | {산식} | {하한 ~ 상한} | {조정 방향} |
|
||||
|
||||
> **대시보드 갱신 시점**: {밸런스 수치 변경 시마다 / 특정 Phase 완료 시 / 정기 검토 시}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
# {프로젝트명} — UX 흐름
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 기획팀장
|
||||
>
|
||||
> **선행 조건**: `02_핵심_재미_정의.md` PD님 승인 완료 + `03_시스템_설계.md` 초안 완료 후 착수
|
||||
|
||||
---
|
||||
|
||||
## 1. 화면 맵
|
||||
|
||||
> 게임 전체 화면 구조를 최상위 레벨에서 표현한다.
|
||||
|
||||
```
|
||||
[앱 시작]
|
||||
│
|
||||
▼
|
||||
[{메인/로비 화면}]
|
||||
├── [{게임 핵심 화면}] ──→ [{결과 화면}] ──→ [메인 복귀]
|
||||
├── [{설정 화면}]
|
||||
├── [{상점/수익화 화면}]
|
||||
└── [{기타 보조 화면}]
|
||||
```
|
||||
|
||||
> 화살표 방향 = 화면 전환 방향. 순환 구조는 명시적으로 표시한다.
|
||||
|
||||
---
|
||||
|
||||
## 2. 화면별 정의
|
||||
|
||||
| 화면 | 진입 조건 | 주요 기능 | 이탈 경로 |
|
||||
|------|---------|---------|---------|
|
||||
| {메인/로비} | 앱 시작, 결과 화면에서 복귀 | {핵심 액션 목록} | {게임 시작, 설정, 상점} |
|
||||
| {게임 핵심 화면} | 게임 시작 버튼 | {인게임 주요 기능} | {일시정지, 게임 종료} |
|
||||
| {결과 화면} | 게임 종료 조건 충족 | {결과 표시, 보상 수령} | {재시작, 메인 복귀} |
|
||||
| {설정} | 설정 버튼 | {옵션 조정} | {닫기(이전 화면)} |
|
||||
| {상점} | 상점 버튼 | {상품 목록, 구매} | {닫기(이전 화면)} |
|
||||
| {기타 화면} | {진입 조건} | {기능} | {이탈 경로} |
|
||||
|
||||
---
|
||||
|
||||
## 3. 핵심 조작 흐름
|
||||
|
||||
> 핵심 재미가 발생하는 플레이 시퀀스를 유저 액션과 시스템 응답을 교대로 서술한다.
|
||||
|
||||
### 흐름 A: {핵심 재미 발생 시나리오 — 예: 주요 게임 루프}
|
||||
|
||||
```
|
||||
유저: {유저가 하는 행동}
|
||||
시스템: {시스템이 즉시 반응하는 것}
|
||||
|
||||
유저: {다음 행동}
|
||||
시스템: {시스템 반응 + 피드백}
|
||||
|
||||
유저: {결정적 행동}
|
||||
시스템: {핵심 재미가 발생하는 시스템 반응}
|
||||
→ [결과 화면으로 전환]
|
||||
```
|
||||
|
||||
### 흐름 B: {보조 시나리오 — 예: 구매, 설정 변경 등}
|
||||
|
||||
```
|
||||
유저: {유저 액션}
|
||||
시스템: {반응}
|
||||
|
||||
유저: {다음 액션}
|
||||
시스템: {반응}
|
||||
→ [이전 화면 복귀]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. UI 컴포넌트 목록
|
||||
|
||||
> 재사용되는 UI 컴포넌트를 정의한다. 개발팀에 전달하는 사양 기준.
|
||||
|
||||
| 컴포넌트 | 사용 화면 | 상태 | 비고 |
|
||||
|---------|---------|------|------|
|
||||
| {컴포넌트명 A} | {사용하는 화면 목록} | {활성/비활성/선택됨 등} | {애니메이션, 특이사항} |
|
||||
| {컴포넌트명 B} | {사용 화면} | {상태 목록} | {비고} |
|
||||
| {컴포넌트명 C} | {사용 화면} | {상태 목록} | {비고} |
|
||||
|
||||
> **컴포넌트 사양 원칙**:
|
||||
> - 동일 기능을 여러 화면에서 반복 구현하지 않는다. 공통 컴포넌트로 추출한다.
|
||||
> - 상태 목록이 3개를 초과하면 별도 명세 문서로 분리한다.
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
# {프로젝트명} — 수익화 설계
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 기획팀장
|
||||
>
|
||||
> **선행 조건**: `02_핵심_재미_정의.md` PD님 승인 완료 (C7 게이트 통과) 후 착수
|
||||
|
||||
---
|
||||
|
||||
## 1. 수익화 원칙
|
||||
|
||||
> ⚠️ **핵심 재미 훼손 금지**
|
||||
> 수익화 설계의 모든 결정은 [`02_핵심_재미_정의.md`](./02_핵심_재미_정의.md)의 재미 판단 기준으로 검증한다.
|
||||
> **수익화가 핵심 재미를 약화시키면 기각한다.** 매출 기여도가 높아도 예외 없음.
|
||||
|
||||
**이 게임의 수익화 방향**:
|
||||
|
||||
1. {수익화 원칙 1}: {핵심 재미와의 관계}
|
||||
2. {수익화 원칙 2}: {핵심 재미와의 관계}
|
||||
3. {수익화 원칙 3}: {핵심 재미와의 관계}
|
||||
|
||||
**수익화 금지 패턴**:
|
||||
|
||||
- {핵심 재미를 해치는 수익화 패턴 1}: {왜 금지인가}
|
||||
- {핵심 재미를 해치는 수익화 패턴 2}: {왜 금지인가}
|
||||
|
||||
---
|
||||
|
||||
## 2. 재화 체계
|
||||
|
||||
> 게임 내 모든 재화를 정의한다. 재화 간 교환·획득·소비 경로가 명확해야 한다.
|
||||
|
||||
| 재화명 | 유형 | 주요 획득 경로 | 주요 소비처 | 이월 가능 |
|
||||
|-------|------|-------------|-----------|---------|
|
||||
| {재화 A} | 유료 / 무료 / 혼합 | {플레이 / 구매 / 이벤트 등} | {어디에 쓰는가} | 예 / 아니오 |
|
||||
| {재화 B} | 유료 / 무료 / 혼합 | {획득 경로} | {소비처} | 예 / 아니오 |
|
||||
| {재화 C} | 유료 / 무료 / 혼합 | {획득 경로} | {소비처} | 예 / 아니오 |
|
||||
|
||||
**재화 흐름 다이어그램**:
|
||||
|
||||
```
|
||||
[유저 행동/구매] → {재화 A} → [소비처 X]
|
||||
→ [소비처 Y]
|
||||
|
||||
[플레이 보상] → {재화 B} → [소비처 Z]
|
||||
↘ {재화 C로 교환}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 상품 구조
|
||||
|
||||
> 유료 상품의 유형과 가격 구조를 정의한다.
|
||||
|
||||
| 유형 | 구성 | 가격대 | 과금 유도 타이밍 | 비고 |
|
||||
|------|------|-------|--------------|------|
|
||||
| {상품 유형 A} | {포함 내용} | {가격 범위} | {언제 제시되는가} | {비고} |
|
||||
| {상품 유형 B} | {포함 내용} | {가격 범위} | {유도 타이밍} | {비고} |
|
||||
| {상품 유형 C} | {포함 내용} | {가격 범위} | {유도 타이밍} | {비고} |
|
||||
|
||||
**과금 유도 타이밍 원칙**:
|
||||
|
||||
- {타이밍 원칙 1}: {핵심 재미와의 관계, 과금 압박이 재미를 해치지 않는 이유}
|
||||
- {타이밍 원칙 2}: {원칙}
|
||||
|
||||
---
|
||||
|
||||
## 4. 광고 정책
|
||||
|
||||
> 광고 노출이 핵심 재미를 방해하지 않도록 정책을 명확히 정의한다.
|
||||
|
||||
| 유형 | 보상 | 빈도 / 노출 시점 | 강제 여부 | 비고 |
|
||||
|------|------|--------------|---------|------|
|
||||
| {광고 유형 A: 예: 보상형 동영상} | {보상 내용} | {빈도 또는 노출 조건} | 자발적 | {비고} |
|
||||
| {광고 유형 B: 예: 전면 광고} | 없음 | {노출 빈도/시점} | 강제 | {건너뛰기 조건} |
|
||||
| {광고 유형 C} | {보상} | {조건} | {강제/자발} | {비고} |
|
||||
|
||||
**광고 제한 규칙**:
|
||||
|
||||
- {핵심 재미 진행 중(예: 게임 플레이 중) 강제 광고 금지}
|
||||
- {광고 노출 최소 간격: N분 / N회 플레이당 1회 등}
|
||||
- {기타 제한 사항}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
# {프로젝트명} — 라이브 운영 계획
|
||||
|
||||
> **버전**: v1
|
||||
> **작성일**: {날짜}
|
||||
> **담당**: 기획팀장
|
||||
>
|
||||
> **선행 조건**: `02_핵심_재미_정의.md` PD님 승인 완료 + `07_수익화_설계.md` 확정 후 착수
|
||||
|
||||
---
|
||||
|
||||
## 1. 운영 주기
|
||||
|
||||
> 라이브 서비스의 리듬을 정의한다. 유저가 "다음에 또 돌아올 이유"를 만드는 구조.
|
||||
|
||||
### 주간 운영 프레임
|
||||
|
||||
| 주기 | 내용 | 목적 |
|
||||
|------|------|------|
|
||||
| 매주 | {주간 반복 요소: 예: 주간 챌린지, 리셋 보상} | {D7 리텐션 자극} |
|
||||
| 격주 | {격주 요소} | {목적} |
|
||||
| {기타 주기} | {내용} | {목적} |
|
||||
|
||||
### 월간 운영 프레임
|
||||
|
||||
| 주기 | 내용 | 목적 |
|
||||
|------|------|------|
|
||||
| 매월 | {월간 반복 요소: 예: 월간 패스, 컨텐츠 추가} | {D30 리텐션 자극} |
|
||||
| {기타} | {내용} | {목적} |
|
||||
|
||||
### 시즌 프레임
|
||||
|
||||
| 시즌 길이 | 시즌 컨텐츠 구성 | 시즌 종료 처리 |
|
||||
|---------|--------------|-------------|
|
||||
| {N주 / N개월} | {시즌 전용 요소 목록} | {리셋 여부, 이월 보상 처리} |
|
||||
|
||||
---
|
||||
|
||||
## 2. 이벤트 프레임워크
|
||||
|
||||
> 이벤트 유형을 표준화하여 제작·재활용 효율을 높인다.
|
||||
|
||||
| 이벤트 유형 | 내용 | 보상 구조 | 재활용 가능 여부 | 제작 비용 |
|
||||
|-----------|------|---------|--------------|---------|
|
||||
| {이벤트 A: 예: 로그인 연속 보상} | {설명} | {보상 방식} | 높음 (수치·기간만 변경) | 낮음 |
|
||||
| {이벤트 B: 예: 한정 컨텐츠} | {설명} | {보상 방식} | 중간 (아트 신규 필요) | 중간 |
|
||||
| {이벤트 C: 예: 커뮤니티 이벤트} | {설명} | {보상 방식} | 낮음 (매번 신규 기획) | 높음 |
|
||||
|
||||
**이벤트 설계 원칙**:
|
||||
|
||||
- {원칙 1: 예: 이벤트 보상이 핵심 재미를 우회하지 않는다}
|
||||
- {원칙 2: 예: 이벤트 참여가 강제가 아닌 자발적 동기에서 발생한다}
|
||||
- {원칙 3: 예: 이벤트 미참여 유저가 게임에서 불이익을 받지 않는다}
|
||||
|
||||
---
|
||||
|
||||
## 3. KPI 정의
|
||||
|
||||
> 라이브 서비스 건강 상태를 판단하는 핵심 지표.
|
||||
|
||||
| KPI | 정의 | 측정 방법 | 목표 범위 | 이탈 시 조치 |
|
||||
|-----|------|---------|---------|------------|
|
||||
| **DAU** | 일간 활성 유저 수 | {측정 도구/방법} | {목표 범위} | {조치 방향} |
|
||||
| **D1 리텐션** | 첫 플레이 다음날 재방문율 | {측정 방법} | {목표 범위 %} | {튜토리얼·첫 루프 재검토} |
|
||||
| **D7 리텐션** | 7일 후 재방문율 | {측정 방법} | {목표 범위 %} | {주간 운영 요소 점검} |
|
||||
| **D30 리텐션** | 30일 후 재방문율 | {측정 방법} | {목표 범위 %} | {중장기 컨텐츠 검토} |
|
||||
| **ARPDAU** | 일간 활성 유저 1인당 평균 매출 | {측정 방법} | {목표 범위} | {수익화 설계 점검} |
|
||||
| **세션 길이** | 1회 플레이 평균 시간 | {측정 방법} | `{N}분 ~ {N}분` | {게임 루프 길이 조정} |
|
||||
| **전환율** | 무료→유료 전환 비율 | {측정 방법} | {목표 범위 %} | {과금 진입점·상품 구성 검토} |
|
||||
|
||||
**KPI 해석 원칙**:
|
||||
|
||||
- KPI 이탈 자체가 "문제"가 아니라 **근원 원인을 파악하는 신호**로 취급한다
|
||||
- KPI 개선을 위해 핵심 재미를 희생하는 수정은 금지한다 (C7 재미 우선)
|
||||
- 복수 KPI가 동시 이탈 시 상호 관계를 분석하여 근본 원인을 식별한다
|
||||
Loading…
Reference in New Issue