From 9ce50ce6cddf3643433aae1449468c2e08494a99 Mon Sep 17 00:00:00 2001 From: swrring Date: Thu, 16 Apr 2026 20:19:51 +0900 Subject: [PATCH] =?UTF-8?q?feat(template):=20=EB=B2=94=EC=9A=A9=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=2017=EA=B0=9C=20=ED=8C=8C=EC=9D=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=E2=80=94=20=EC=8B=A0=EA=B7=9C=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EC=A0=9D=ED=8A=B8=20=EA=B8=B0=EB=B0=98=20=EC=85=8B=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기획 8개(게임컨셉·핵심재미·시스템·컨텐츠·밸런스·UX·수익화·라이브) + 개발 6개(아키텍처·기술스택·코딩컨벤션·데이터파이프라인·빌드배포·QA) + 관리 2개(시작체크리스트·Unity셋업가이드) + README. C7 게이트(재미정의 PD승인 전 착수금지), 보안 안티패턴 3건, NerdNavis.Framework C+H1 연동 절차, 시뮬레이터 이원화 방지 등 수상한잡화점 교훈을 구조적으로 내장. Co-Authored-By: Claude Opus 4.6 (1M context) --- 프로젝트/_템플릿/README.md | 47 +++ 프로젝트/_템플릿/개발/01_아키텍처_설계.md | 164 ++++++++++ 프로젝트/_템플릿/개발/02_기술스택_결정.md | 94 ++++++ 프로젝트/_템플릿/개발/03_코딩_컨벤션.md | 223 +++++++++++++ 프로젝트/_템플릿/개발/04_데이터_파이프라인.md | 219 +++++++++++++ 프로젝트/_템플릿/개발/05_빌드_배포.md | 159 +++++++++ 프로젝트/_템플릿/개발/06_QA_테스트_전략.md | 213 ++++++++++++ 프로젝트/_템플릿/관리/Unity_셋업_가이드.md | 308 ++++++++++++++++++ .../_템플릿/관리/프로젝트_시작_체크리스트.md | 217 ++++++++++++ 프로젝트/_템플릿/기획/01_게임_컨셉.md | 60 ++++ 프로젝트/_템플릿/기획/02_핵심_재미_정의.md | 79 +++++ 프로젝트/_템플릿/기획/03_시스템_설계.md | 96 ++++++ 프로젝트/_템플릿/기획/04_컨텐츠_설계.md | 86 +++++ 프로젝트/_템플릿/기획/05_밸런스_프레임워크.md | 100 ++++++ 프로젝트/_템플릿/기획/06_UX_흐름.md | 86 +++++ 프로젝트/_템플릿/기획/07_수익화_설계.md | 83 +++++ 프로젝트/_템플릿/기획/08_라이브_운영_계획.md | 74 +++++ 17 files changed, 2308 insertions(+) create mode 100644 프로젝트/_템플릿/README.md create mode 100644 프로젝트/_템플릿/개발/01_아키텍처_설계.md create mode 100644 프로젝트/_템플릿/개발/02_기술스택_결정.md create mode 100644 프로젝트/_템플릿/개발/03_코딩_컨벤션.md create mode 100644 프로젝트/_템플릿/개발/04_데이터_파이프라인.md create mode 100644 프로젝트/_템플릿/개발/05_빌드_배포.md create mode 100644 프로젝트/_템플릿/개발/06_QA_테스트_전략.md create mode 100644 프로젝트/_템플릿/관리/Unity_셋업_가이드.md create mode 100644 프로젝트/_템플릿/관리/프로젝트_시작_체크리스트.md create mode 100644 프로젝트/_템플릿/기획/01_게임_컨셉.md create mode 100644 프로젝트/_템플릿/기획/02_핵심_재미_정의.md create mode 100644 프로젝트/_템플릿/기획/03_시스템_설계.md create mode 100644 프로젝트/_템플릿/기획/04_컨텐츠_설계.md create mode 100644 프로젝트/_템플릿/기획/05_밸런스_프레임워크.md create mode 100644 프로젝트/_템플릿/기획/06_UX_흐름.md create mode 100644 프로젝트/_템플릿/기획/07_수익화_설계.md create mode 100644 프로젝트/_템플릿/기획/08_라이브_운영_계획.md diff --git a/프로젝트/_템플릿/README.md b/프로젝트/_템플릿/README.md new file mode 100644 index 0000000..e4b0dfa --- /dev/null +++ b/프로젝트/_템플릿/README.md @@ -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 참조 diff --git a/프로젝트/_템플릿/개발/01_아키텍처_설계.md b/프로젝트/_템플릿/개발/01_아키텍처_설계.md new file mode 100644 index 0000000..068ce07 --- /dev/null +++ b/프로젝트/_템플릿/개발/01_아키텍처_설계.md @@ -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` (Persistent) | ✅ | +| `DataManager` | DataTable 로딩·캐시 관리 | `MonoSingleton` (Persistent) | ✅ | +| `UIManager` | UI View 스택·전환 관리 | `MonoSingleton` (Persistent) | ✅ | +| `AudioManager` | BGM/SFX 재생 | `NerdNavis.Audio` 위임 | ✅ | +| `ServerManager` | 서버 통신 추상화 | `ServiceLocator` | ✅ | +| `SaveManager` | 세이브/로드 | `ServiceLocator` + `NerdNavis.Save` | ✅ | +| `{Game}Manager` | 핵심 게임 로직 매니저 ({장르} 특화) | `MonoSingleton` or `ServiceLocator` | 상황별 | + +**라이프사이클 선택 기준**: +- `MonoSingleton`: 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 | {날짜} | 개발팀장 | 템플릿 초안 | diff --git a/프로젝트/_템플릿/개발/02_기술스택_결정.md b/프로젝트/_템플릿/개발/02_기술스택_결정.md new file mode 100644 index 0000000..610b5c6 --- /dev/null +++ b/프로젝트/_템플릿/개발/02_기술스택_결정.md @@ -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건 반영 | diff --git a/프로젝트/_템플릿/개발/03_코딩_컨벤션.md b/프로젝트/_템플릿/개발/03_코딩_컨벤션.md new file mode 100644 index 0000000..a314012 --- /dev/null +++ b/프로젝트/_템플릿/개발/03_코딩_컨벤션.md @@ -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 — MonoBehaviour 싱글톤 + +```csharp +// 씬 라이프사이클과 동기화되는 서비스에 사용 +// Update/OnDestroy 훅이 필요한 경우 +public class GameManager : MonoSingleton +{ + // [SingletonOption(Persistent = true)] 로 DontDestroyOnLoad 제어 + protected override void OnAwake() + { + // 초기화 코드 + } +} + +// 사용 +GameManager.Instance.StartGame(); +``` + +### 3.2 ServiceLocator — 순수 C# 서비스 DI + +```csharp +// MonoBehaviour와 독립된 서비스, 인터페이스 바인딩, 테스트 Mock 주입 시 사용 +// Bootstrap 씬에서 등록 +ServiceLocator.Register(new JsonSaveProvider()); +ServiceLocator.Register(new PlayFabNetworkService()); + +// 사용처 +var save = ServiceLocator.Resolve(); +save.Save(playerData); + +// 테스트 시 Mock 교체 +ServiceLocator.Register(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(OnPlayerDied); +private void OnPlayerDied(PlayerDiedEvent e) { /* ... */ } + +// 발행 +EventBus.Publish(new PlayerDiedEvent { PlayerId = 1, Cause = "Fall" }); + +// 구독 해제 (OnDestroy에서 반드시 해제) +EventBus.Unsubscribe(OnPlayerDied); +``` + +**금지**: 문자열 키 이벤트 (`EventBus.Raw` 하위 특수 용도만 허용). + +--- + +## 4. 금지 사항 + +| 금지 항목 | 사유 | 대안 | +|-----------|------|------| +| **수치 하드코딩** | 수정 시 코드 수정 필요, 기획-개발 분리 파괴 | DataTable 참조 (04_데이터_파이프라인 참조) | +| **암호키 평문 하드코딩** | IL2CPP 빌드도 메모리 덤프로 추출 가능 (수상한잡화점 Critical) | 서버 측 키 관리 또는 런타임 유도 (02_기술스택 참조) | +| **`Resources.Load` 남용** | 빌드 시 모든 Resources/ 포함 → 빌드 크기 증가 | Addressables | +| **문자열 이벤트 키** | 컴파일 타임 검증 불가, 오타 런타임 버그 | `EventBus` 타입 이벤트 | +| **`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) 패턴 정립 | diff --git a/프로젝트/_템플릿/개발/04_데이터_파이프라인.md b/프로젝트/_템플릿/개발/04_데이터_파이프라인.md new file mode 100644 index 0000000..6c14d26 --- /dev/null +++ b/프로젝트/_템플릿/개발/04_데이터_파이프라인.md @@ -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 + { + // Dictionary 인덱스 — 자주 쓰는 키 기준으로 추가 정의 + private Dictionary _byId; + + protected override void BuildIndex(List 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>(_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 | {날짜} | 개발팀장 | 템플릿 초안. 수상한잡화점 데이터 파이프라인 패턴 + 시뮬레이터 이원화 방지 규칙 반영 | diff --git a/프로젝트/_템플릿/개발/05_빌드_배포.md b/프로젝트/_템플릿/개발/05_빌드_배포.md new file mode 100644 index 0000000..e26a9d3 --- /dev/null +++ b/프로젝트/_템플릿/개발/05_빌드_배포.md @@ -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건 체크리스트 반영 | diff --git a/프로젝트/_템플릿/개발/06_QA_테스트_전략.md b/프로젝트/_템플릿/개발/06_QA_테스트_전략.md new file mode 100644 index 0000000..f9fb699 --- /dev/null +++ b/프로젝트/_템플릿/개발/06_QA_테스트_전략.md @@ -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(mock); + + var resolved = ServiceLocator.Resolve(); + + Assert.AreEqual(mock, resolved); + } +} +``` + +### 1.2 Unit Test — PlayMode + +| 대상 | 예시 | 실행 모드 | +|------|------|----------| +| `MonoSingleton` | 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` | 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 체크리스트 정립 | diff --git a/프로젝트/_템플릿/관리/Unity_셋업_가이드.md b/프로젝트/_템플릿/관리/Unity_셋업_가이드.md new file mode 100644 index 0000000..94aeb56 --- /dev/null +++ b/프로젝트/_템플릿/관리/Unity_셋업_가이드.md @@ -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) + ├── DataManager (MonoSingleton) + ├── UIManager (MonoSingleton) + └── ServiceLocatorBootstrap (MonoBehaviour) + └── Awake()에서 ServiceLocator.Register(...) +``` + +### 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 + { + 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(new JsonSaveProvider()); + var resolved = ServiceLocator.Resolve(); + Debug.Assert(resolved != null); + ``` +- [ ] **6. Log.Info/Log.Warn 출력 테스트** — 콘솔에 로그 출력 확인 + +--- + +## 변경 이력 + +| 버전 | 일자 | 작성자 | 내용 | +|------|------|--------|------| +| v1 | {날짜} | 개발팀장 | 템플릿 초안. C+H1 배포 방식 + 셋업 검증 6항 정립 | diff --git a/프로젝트/_템플릿/관리/프로젝트_시작_체크리스트.md b/프로젝트/_템플릿/관리/프로젝트_시작_체크리스트.md new file mode 100644 index 0000000..c84a514 --- /dev/null +++ b/프로젝트/_템플릿/관리/프로젝트_시작_체크리스트.md @@ -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) 기본 구현 +- [ ] `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 게이트 반영 | diff --git a/프로젝트/_템플릿/기획/01_게임_컨셉.md b/프로젝트/_템플릿/기획/01_게임_컨셉.md new file mode 100644 index 0000000..f7461d3 --- /dev/null +++ b/프로젝트/_템플릿/기획/01_게임_컨셉.md @@ -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 / 특정 설계 착수 전} | diff --git a/프로젝트/_템플릿/기획/02_핵심_재미_정의.md b/프로젝트/_템플릿/기획/02_핵심_재미_정의.md new file mode 100644 index 0000000..fadc576 --- /dev/null +++ b/프로젝트/_템플릿/기획/02_핵심_재미_정의.md @@ -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. 검증 방법 + +> 각 개발 단계에서 핵심 재미가 실제로 전달되고 있는지 확인하는 방법. + +| 단계 | 검증 방식 | 기대 신호 | 실패 신호 | +|------|----------|----------|----------| +| **프로토타입** | {검증 방법} | {성공 시 나타나는 반응} | {실패 시 나타나는 반응} | +| **알파** | {검증 방법} | {성공 시 나타나는 반응} | {실패 시 나타나는 반응} | +| **베타** | {검증 방법} | {성공 시 나타나는 반응} | {실패 시 나타나는 반응} | diff --git a/프로젝트/_템플릿/기획/03_시스템_설계.md b/프로젝트/_템플릿/기획/03_시스템_설계.md new file mode 100644 index 0000000..063fcc9 --- /dev/null +++ b/프로젝트/_템플릿/기획/03_시스템_설계.md @@ -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 / 특정 설계 착수 전} | diff --git a/프로젝트/_템플릿/기획/04_컨텐츠_설계.md b/프로젝트/_템플릿/기획/04_컨텐츠_설계.md new file mode 100644 index 0000000..25808dc --- /dev/null +++ b/프로젝트/_템플릿/기획/04_컨텐츠_설계.md @@ -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로 지정**하고 다른 쪽은 생성(변환) 파일로 표시한다 diff --git a/프로젝트/_템플릿/기획/05_밸런스_프레임워크.md b/프로젝트/_템플릿/기획/05_밸런스_프레임워크.md new file mode 100644 index 0000000..bc23d3e --- /dev/null +++ b/프로젝트/_템플릿/기획/05_밸런스_프레임워크.md @@ -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 완료 시 / 정기 검토 시} diff --git a/프로젝트/_템플릿/기획/06_UX_흐름.md b/프로젝트/_템플릿/기획/06_UX_흐름.md new file mode 100644 index 0000000..945e160 --- /dev/null +++ b/프로젝트/_템플릿/기획/06_UX_흐름.md @@ -0,0 +1,86 @@ +# {프로젝트명} — UX 흐름 + +> **버전**: v1 +> **작성일**: {날짜} +> **담당**: 기획팀장 +> +> **선행 조건**: `02_핵심_재미_정의.md` PD님 승인 완료 + `03_시스템_설계.md` 초안 완료 후 착수 + +--- + +## 1. 화면 맵 + +> 게임 전체 화면 구조를 최상위 레벨에서 표현한다. + +``` +[앱 시작] + │ + ▼ +[{메인/로비 화면}] + ├── [{게임 핵심 화면}] ──→ [{결과 화면}] ──→ [메인 복귀] + ├── [{설정 화면}] + ├── [{상점/수익화 화면}] + └── [{기타 보조 화면}] +``` + +> 화살표 방향 = 화면 전환 방향. 순환 구조는 명시적으로 표시한다. + +--- + +## 2. 화면별 정의 + +| 화면 | 진입 조건 | 주요 기능 | 이탈 경로 | +|------|---------|---------|---------| +| {메인/로비} | 앱 시작, 결과 화면에서 복귀 | {핵심 액션 목록} | {게임 시작, 설정, 상점} | +| {게임 핵심 화면} | 게임 시작 버튼 | {인게임 주요 기능} | {일시정지, 게임 종료} | +| {결과 화면} | 게임 종료 조건 충족 | {결과 표시, 보상 수령} | {재시작, 메인 복귀} | +| {설정} | 설정 버튼 | {옵션 조정} | {닫기(이전 화면)} | +| {상점} | 상점 버튼 | {상품 목록, 구매} | {닫기(이전 화면)} | +| {기타 화면} | {진입 조건} | {기능} | {이탈 경로} | + +--- + +## 3. 핵심 조작 흐름 + +> 핵심 재미가 발생하는 플레이 시퀀스를 유저 액션과 시스템 응답을 교대로 서술한다. + +### 흐름 A: {핵심 재미 발생 시나리오 — 예: 주요 게임 루프} + +``` +유저: {유저가 하는 행동} +시스템: {시스템이 즉시 반응하는 것} + +유저: {다음 행동} +시스템: {시스템 반응 + 피드백} + +유저: {결정적 행동} +시스템: {핵심 재미가 발생하는 시스템 반응} + → [결과 화면으로 전환] +``` + +### 흐름 B: {보조 시나리오 — 예: 구매, 설정 변경 등} + +``` +유저: {유저 액션} +시스템: {반응} + +유저: {다음 액션} +시스템: {반응} + → [이전 화면 복귀] +``` + +--- + +## 4. UI 컴포넌트 목록 + +> 재사용되는 UI 컴포넌트를 정의한다. 개발팀에 전달하는 사양 기준. + +| 컴포넌트 | 사용 화면 | 상태 | 비고 | +|---------|---------|------|------| +| {컴포넌트명 A} | {사용하는 화면 목록} | {활성/비활성/선택됨 등} | {애니메이션, 특이사항} | +| {컴포넌트명 B} | {사용 화면} | {상태 목록} | {비고} | +| {컴포넌트명 C} | {사용 화면} | {상태 목록} | {비고} | + +> **컴포넌트 사양 원칙**: +> - 동일 기능을 여러 화면에서 반복 구현하지 않는다. 공통 컴포넌트로 추출한다. +> - 상태 목록이 3개를 초과하면 별도 명세 문서로 분리한다. diff --git a/프로젝트/_템플릿/기획/07_수익화_설계.md b/프로젝트/_템플릿/기획/07_수익화_설계.md new file mode 100644 index 0000000..e005169 --- /dev/null +++ b/프로젝트/_템플릿/기획/07_수익화_설계.md @@ -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회 등} +- {기타 제한 사항} diff --git a/프로젝트/_템플릿/기획/08_라이브_운영_계획.md b/프로젝트/_템플릿/기획/08_라이브_운영_계획.md new file mode 100644 index 0000000..8eb2feb --- /dev/null +++ b/프로젝트/_템플릿/기획/08_라이브_운영_계획.md @@ -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가 동시 이탈 시 상호 관계를 분석하여 근본 원인을 식별한다