7.3 KiB
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*접두사:MyCoroutine→CoroutineRunner사용u*소문자 접두사:uScrollViewMgr→ScrollViewControllerMgr접미사:UIAtlasMgr→UIAtlasManagerBase접미사 (추상 클래스):CustomParserBase→abstract class CustomParserInfo접미사 (데이터 클래스):GachaGradeInfo→GachaGradeHandler접미사 (스케줄러):SchedulHandler→GameScheduler
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) 패턴 정립 |