BurningTimesAi/프로젝트/_템플릿/개발/03_코딩_컨벤션.md

7.3 KiB

{프로젝트명} — 코딩 컨벤션

버전: 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* 접두사: MyCoroutineCoroutineRunner 사용
  • u* 소문자 접두사: uScrollViewMgrScrollViewController
  • Mgr 접미사: UIAtlasMgrUIAtlasManager
  • Base 접미사 (추상 클래스): CustomParserBaseabstract class CustomParser
  • Info 접미사 (데이터 클래스): GachaGradeInfoGachaGrade
  • Handler 접미사 (스케줄러): SchedulHandlerGameScheduler

2. 파일 구조

// 헤더 주석 (선택, 복잡한 파일만)
// 파일명: 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 싱글톤

// 씬 라이프사이클과 동기화되는 서비스에 사용
// Update/OnDestroy 훅이 필요한 경우
public class GameManager : MonoSingleton<GameManager>
{
    // [SingletonOption(Persistent = true)] 로 DontDestroyOnLoad 제어
    protected override void OnAwake()
    {
        // 초기화 코드
    }
}

// 사용
GameManager.Instance.StartGame();

3.2 ServiceLocator — 순수 C# 서비스 DI

// 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 — 전역 코루틴 관리

// 키 기반 중복 제어, 일시정지·재시작 지원
// MonoBehaviour 없이 코루틴 실행 가능

// 시작 (키로 중복 방지)
CoroutineRunner.Start("LoadData", LoadDataCoroutine());

// 중지
CoroutineRunner.Stop("LoadData");

// 완료 시 자동 해제

3.4 Log — 중앙 로거

// Debug.Log 직접 호출 금지 → Log 클래스 사용
Log.Info("GameManager", "게임 시작");
Log.Warn("DataManager", $"데이터 키 없음: {key}");
Log.Error("ServerManager", "서버 연결 실패", exception);

// 카테고리 필터링 → 빌드 변형별 로그 레벨 제어 가능

3.5 EventBus — 타입 안전 이벤트

// 이벤트 정의 (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) 패턴 정립