C# 코드의 형식을 지정하는 올바른 방법이 하나만 있는 것은 아니지만, 팀 전체에서 일관된 스타일에 동의하면 더 깔끔하고 가독성이 높으며 확장 가능한 코드베이스를 만들 수 있습니다. 잘 정리된 스타일 가이드는 일관성 있는 최종 결과물을 만들기 위해 불일치를 억제하는 데 도움이 될 수 있습니다. 이 페이지에서는 스타일 가이드를 만들 때 명명 규칙 및 코드 서식 지정에 유의해야 할 팁과 주요 고려 사항을 제공합니다.
참고: 여기에 공유된 권장 사항은 Microsoft에서 제공한 권장 사항을 기반으로 합니다. 가장 좋은 코드 스타일 가이드 규칙은 팀의 필요에 가장 적합한 규칙입니다.
여기에서 코드 스타일 가이드 예제를 확인하거나 전체 전자책( C# 스타일 가이드 만들기)을 다운로드할 수 있습니다: 확장되는 깔끔한 코드 작성.
C#은 공백 문자를 사용하여 식별자를 구분하기 때문에 이름에 공백이 있는 변수를 정의할 수 없습니다. 대소문자 체계를 사용하면 소스 코드에서 복합 이름이나 구문을 사용해야 하는 문제를 완화할 수 있습니다.
다음은 잘 알려진 몇 가지 이름 지정 및 대소문자 규칙입니다:
카멜 케이스
카멜 뚜껑이라고도 하는 카멜 케이스는 띄어쓰기나 구두점 없이 대문자 한 개로 단어를 구분하여 문구를 작성하는 방식입니다. 첫 글자는 소문자로 표기합니다.
일반적으로 로컬 변수와 메서드 매개변수는 대문자로 표시됩니다. 예제:
examplePlayerController
maxHealthPoints
endOfFile
파스칼 케이스
파스칼 대소문자는 카멜 대소문자의 변형으로, 첫 글자를 대문자로 표기합니다. Unity 개발에서 클래스 및 메서드 이름에 사용합니다. 공개 필드도 파스칼 대소문자가 될 수 있습니다. 예제:
ExamplePlayerController
MaxHealthPoints
EndOfFile
스네이크 케이스
이 경우 단어 사이의 공백은 밑줄 문자로 대체됩니다. 예제:
example_player_controller
max_health_points
end_of_file
케밥 케이스
여기서 단어 사이의 공백은 대시로 대체됩니다. 그러면 단어가 대시 문자의 일종의 '꼬치'에 나타납니다. 예제:
예제-플레이어-컨트롤러
최대 건강 포인트
파일 끝
케밥 케이스의 문제점은 많은 프로그래밍 언어가 대시를 빼기 기호로 사용한다는 것입니다. 또한 일부 언어에서는 대시로 구분된 숫자를 달력 날짜로 해석합니다.
헝가리어 표기법
변수 또는 함수 이름은 종종 그 의도나 유형을 나타냅니다. 예제:
int iCounter
string strPlayerName
헝가리어 표기법은 오래된 관습이며 Unity 개발에서는 일반적으로 사용되지 않습니다.
변수와 필드에 대해 다음 규칙을 고려하세요:
- 변수 이름에는 명사를 사용합니다: 변수 이름은 특정 사물이나 상태를 나타내므로 명확하고 설명적이어야 합니다. 변수의 유형이 부울인 경우를 제외하고 이름을 지정할 때는 명사를 사용합니다(아래 참조).
- 부울 앞에 동사를 접두사로 붙입니다: 이러한 변수는 참 또는 거짓 값을 나타냅니다. 종종 다음과 같은 질문에 대한 답변이 되기도 합니다: 플레이어가 실행 중인가요? 게임이 끝난 건가요?
- 동사 앞에 접두사를 붙이면 의미를 더 명확하게 알 수 있습니다. 이것은 종종 설명이나 조건(예: isDead, isWalking, hasDamageMultiplier 등)과 짝을 이룹니다.
- 의미 있는 이름을 사용하세요. 수학이 아니라면 축약하지 마세요: 변수 이름을 통해 의도를 알 수 있습니다. 발음하기 쉽고 검색하기 쉬운 이름을 선택하세요.
- 루프와 수학 표현식에는 한 글자 변수를 사용해도 괜찮지만 다른 상황에서는 축약하지 마세요. 모음을 몇 개 생략하여 절약한 시간보다 더 중요한 것은 명확성입니다.
- 빠른 프로토타입 제작을 위해 짧은 '정크' 이름을 임시로 사용한 다음 나중에 더 의미 있는 이름으로 리팩터링할 수 있습니다.
- 공개 필드에는 파스칼 대소문자를 사용하고 비공개 변수에는 카멜 대소문자를 사용합니다: 공개 필드에 대한 대안으로 공개 '게터'가 있는 속성을 사용하세요(이전 및 다음 섹션 참조).
- 너무 많은 접두사나 특수 인코딩을 피하세요: 개인 멤버 변수 앞에 밑줄(_)을 붙여 로컬 변수와 구분할 수 있습니다.
- 또는 이 키워드를 사용하여 컨텍스트에서 멤버 변수와 로컬 변수를 구분하고 접두사를 생략할 수 있습니다. 공개 필드 및 속성에는 일반적으로 접두사가 없습니다.
- 일부 스타일 가이드에서는 개인 멤버 변수(m_), 상수(k_) 또는 정적 변수(s_)에 접두사를 사용하므로 이름을 통해 변수에 대한 자세한 정보를 한눈에 파악할 수 있습니다.
- 많은 개발자가 이러한 기능을 사용하지 않고 대신 에디터에 의존합니다. 그러나 모든 IDE가 강조 표시 및 색상 코딩을 지원하는 것은 아니며 일부 도구는 풍부한 컨텍스트를 전혀 표시하지 못합니다. 팀에서 접두사를 함께 적용하는 방법(또는 적용 여부)을 결정할 때 이 점을 고려하세요.
- 액세스 수준 수정자를 일관되게 지정(또는 생략)하세요: 액세스 수정자를 생략하면 컴파일러는 액세스 수준을 비공개로 가정합니다. 이 방법은 잘 작동하지만 기본 액세스 수정자를 생략하는 방식에 일관성을 유지해야 합니다.
- 나중에 하위 클래스에서 이 기능을 사용하려면 보호됨을 사용해야 한다는 점을 기억하세요.
열거형은 명명된 상수 집합으로 정의된 특수 값 유형입니다. 기본적으로 상수는 0부터 카운트업되는 정수입니다.
열거형 이름과 값에 파스칼 대소문자를 사용합니다. 공용 열거형을 클래스 외부에 배치하여 전역으로 만들 수 있습니다. 열거형 이름에는 단수 명사를 사용합니다.
참고: 비트열거형 열거형에 System.FlagsAttribute 로 표시된 비트 열거형은 이 규칙의 예외입니다. 일반적으로 두 가지 이상의 유형을 나타내므로 복수형을 사용합니다.
클래스와 인터페이스의 이름을 지정할 때는 다음 표준 규칙을 따르세요:
클래스 이름에는 파스칼 대소문자 명사를 사용합니다: 이렇게 하면 수업을 체계적으로 정리할 수 있습니다.
파일에 모노비헤이비어가 있는 경우 소스 파일 이름이 일치해야 합니다: 파일에 다른 내부 클래스가 있을 수 있지만 파일당 하나의 MonoBehaviour만 존재해야 합니다.
인터페이스 이름 앞에 대문자 "I"를 붙입니다: 그 뒤에 기능을 설명하는 형용사를 붙입니다.
C#에서는 실행되는 모든 명령어가 메서드의 컨텍스트에서 수행됩니다.
메서드는 작업을 수행하므로 이 규칙을 적용하여 적절하게 이름을 지정하세요:
이름은 동사로 시작합니다: 필요한 경우 컨텍스트 추가(예: GetDirection, FindTarget 등)
매개변수에는 카멜 케이스를 사용합니다: 메서드에 전달된 매개변수를 로컬 변수처럼 형식화합니다.
bool을 반환하는 메서드는 질문을 해야 합니다: 부울 변수 자체와 마찬가지로, 참/거짓 조건을 반환하는 경우 메서드 앞에 동사를 붙이세요. 이 문구는 질문의 형태로 표현됩니다(예: IsGameOver, HasStartedTurn).
참고: Unity 개발에서 "함수"와 "메서드"라는 용어는 종종 같은 의미로 사용됩니다. 그러나 C#에서는 함수를 클래스에 통합하지 않고는 함수를 작성할 수 없으므로 '메서드'가 올바른 용어입니다.
C#의 이벤트는 관찰자 패턴을 구현합니다. 이 소프트웨어 디자인 패턴은 하나의 객체, 즉 주체(또는 게시자)가 관찰자(또는 구독자)라고 하는 종속 객체 목록을 통지할 수 있는 관계를 정의합니다. 따라서 피사체는 관련된 객체를 긴밀하게 연결하지 않고도 상태 변화를 관찰자에게 브로드캐스트할 수 있습니다.
피사체 및 관찰자의 이벤트 및 관련 메서드에 대한 여러 가지 명명 체계가 존재합니다. 다음 섹션에 소개된 방법을 시도해 보세요.
동사 구를 사용하여 이벤트 이름을 지정합니다. 상태 변화를 정확하게 전달할 수 있는 것을 선택해야 합니다.
현재 또는 과거 분사를 사용하여 이벤트의 이전 또는 이후 상태를 표시합니다. 예를 들어, 문을 열기 전 이벤트에는 "OpeningDoor"를 지정하고, 문을 연 후 이벤트에는 "DoorOpened"를 지정합니다.
이벤트에는 System.Action 델리게이트를 사용합니다. 대부분의 경우 Action<T> 델리게이트가 게임플레이에 필요한 이벤트를 처리할 수 있습니다.
반환 유형이 무효인 서로 다른 유형의 입력 매개변수를 최대 16개까지 전달할 수 있습니다. 미리 정의된 델리게이트를 사용하면 코드가 절약됩니다.
참고: 또한 이벤트 핸들러 또는 EventHandler<TEventArgs> 델리게이트를 사용할 수도 있습니다. 모든 사람이 이벤트를 구현하는 방법에 대해 팀으로 동의합니다.
이벤트 발생 방법(제목에 있는)의 접두사에 "On"을 붙입니다. 이벤트를 호출하는 주체는 일반적으로 "On"이 접두사로 붙은 메서드에서 호출합니다(예: "OnOpeningDoor" 또는 "OnDoorOpened").
이벤트 처리 메서드(관찰자에서)에 주체의 이름과 밑줄(_)을 앞에 붙입니다. 주체의 이름이 "GameEvents"인 경우 옵저버는 "GameEvents_OpeningDoor" 또는 "GameEvents_DoorOpened"라는 메서드를 가질 수 있습니다.
팀을 위한 일관된 네이밍 체계를 결정하고 스타일 가이드에 해당 규칙을 구현하세요.
참고: 이 "이벤트 처리 메서드"를 EventHandler 델리게이트와 혼동해서는 안 됩니다.
필요한 경우에만 커스텀 EventArgs를 생성합니다. 이벤트에 사용자 지정 데이터를 전달해야 하는 경우, 다음에서 상속된 새 유형의 EventArgs를 생성합니다. System.EventArgs 에서 상속받거나 커스텀 구조체에서 상속받습니다.
네임스페이스를 사용하여 클래스, 인터페이스, 열거형 등이 다른 네임스페이스 또는 글로벌 네임스페이스에서 이미 존재하는 것과 충돌하지 않도록 하세요. 네임스페이스는 프로젝트의 최종 버전에 포함되지 않는 Unity 에셋 스토어의 타사 에셋이나 기타 테스트 씬과의 충돌을 방지할 수도 있습니다.
네임스페이스를 적용할 때:
특별한 기호나 밑줄 없이 파스칼 대소문자를 사용합니다.
네임스페이스 접두사를 반복해서 입력하지 않도록 파일 상단에 using 지시문을 추가합니다.
하위 네임스페이스도 만들 수 있습니다. 점(.) 연산자를 사용하여 이름 수준을 구분하여 스크립트를 계층적 카테고리로 구성할 수 있습니다. 예를 들어, 게임의 다양한 논리적 구성 요소를 저장하기 위해 "MyApplication.GameFlow", "MyApplication.AI", "MyApplication.UI" 등을 생성할 수 있습니다.
코드에서 이러한 클래스는 각각 Enemy.Controller1과 Enemy.Controller2로 불립니다. 사용 행을 추가하여 접두사 입력을 절약할 수 있습니다(예: 적; 사용).
컴파일러가 Controller1과 Controller2라는 클래스 이름을 찾으면 Enemy.Controller1과 Enemy.Controller2를 의미한다고 이해합니다.
스크립트에서 다른 네임스페이스에서 같은 이름의 클래스를 참조해야 하는 경우 접두사를 사용하여 구분하세요. 예를 들어 Player 네임스페이스에 Controller1과 Controller2 클래스가 있는 경우 충돌을 피하기 위해 Player.Controller1과 Player.Controller2를 작성할 수 있습니다. 그렇지 않으면 컴파일러가 오류를 보고합니다.
코드 스타일 팁 더 보기
일반 서식 지정에 대한 자세한 내용은 여기를 참조하거나 전자책 전문을 확인하세요. 코드 스타일 가이드 예시를 살펴볼 수도 있습니다.