# {프로젝트명} — 코딩 컨벤션 > **버전**: 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) 패턴 정립 |