C# 코딩 스타일 Rule 가이드
C# 코딩 스타일 Rule 가이드
Microsoft .NET Runtime Coding Style을 기준으로 정리한 실무 적용 가이드
이 글은 현재 공개된 dotnet/runtime C# Coding Style 문서를 확인하고, Microsoft의 .NET 코드 스타일 및
.editorconfig, dotnet format 관련 공식 문서와 교차 확인하여 작성했습니다.
1. 먼저 결론 — .NET Runtime의 핵심 철학
```.NET Runtime의 C# 스타일 가이드는 기본적으로 Visual Studio의 기본적인 코드 스타일을 따르되, 저장소 전체에서 일관된 규칙을 유지하는 것을 중요하게 봅니다.
따라서 중요한 것은 특정 개발자가 선호하는 스타일을 적용하는 것이 아니라 팀 전체가 동일한 규칙으로 코드를 작성하고 자동 포맷터가 이를 지속적으로 유지하도록 만드는 것입니다.
파일마다 다른 코딩 스타일을 만들지 않습니다.
코드를 처음 보는 개발자도 쉽게 읽을 수 있어야 합니다.
사람의 기억보다 EditorConfig와 Formatter를 우선합니다.
기존 파일의 스타일이 다르면 해당 파일의 기존 스타일을 우선할 수 있습니다.
2. 전체 Rule 한눈에 보기
```| Rule | 핵심 규칙 | 실무 적용 |
|---|---|---|
| 01 | Allman Brace | 중괄호는 다음 줄 |
| 02 | 4 Space | Tab 대신 공백 4칸 |
| 03 | Field Naming | _camelCase / s_ / t_ |
| 04 | this 최소화 | 필요한 경우에만 사용 |
| 05 | Accessibility 명시 | public/private/internal 등 명시 |
| 06 | using 정렬 | System.* 우선 |
| 07 | Blank Line | 불필요한 빈 줄 금지 |
| 08 | Whitespace | 불필요한 공백 제거 |
| 09 | Existing Style | 기존 파일 스타일 우선 |
| 10 | var | 타입이 명확할 때 제한적으로 사용 |
| 11 | Language Keyword | int/string 등 사용 |
| 12 | Constants | PascalCase |
| 13 | Methods | PascalCase |
| 14 | nameof | 가능하면 문자열 대신 nameof |
| 15 | Fields 위치 | 타입 선언 상단 |
| 16 | Non-ASCII | Runtime 저장소에서는 Unicode escape 선호 |
| 17 | goto label | 한 단계 덜 들여쓰기 |
| 18 | if 문 | 한 줄 if 작성 방식 제한 |
| 19 | Private/Internal Type | 가능하면 sealed/static |
| 20 | Primary Constructor | 매개변수는 camelCase |
3. Brace — Allman Style
```.NET Runtime은 Allman style을 사용합니다. 즉, 여는 중괄호를 같은 줄에 붙이지 않고 다음 줄에 배치합니다.
if (isValid) {
DoSomething();
```
} if (isValid)
```
{
DoSomething();
} 4. 들여쓰기 — 4 Spaces
```Tab을 사용하지 않고 공백 4칸을 기본으로 합니다.
public void Process()
```
{
if (condition)
{
Execute();
}
}
5. Field Naming — _camelCase / s_ / t_
```| 종류 | 규칙 | 예 |
|---|---|---|
| private instance | _camelCase | _repository |
| internal instance | _camelCase | _logger |
| static | s_ | s_instance |
| thread static | t_ | t_buffer |
| public field | PascalCase | Count |
가능하면 필드는
readonly를 사용합니다.
특히 DI를 사용하는 ASP.NET Core 서비스에서는 생성자 주입 필드를
private readonly로 만드는 패턴이 매우 자연스럽습니다.
public sealed class UserService
```
{
private readonly IUserRepository _userRepository;
private readonly ILogger _logger;
```
public UserService(
IUserRepository userRepository,
ILogger logger)
{
_userRepository = userRepository;
_logger = logger;
}
```
}
6. this. 사용은 최소화
```
필드와 매개변수의 이름이 충돌하는 상황을 피하기 위해
무조건 this.를 붙이는 방식은 사용하지 않습니다.
private readonly IUserRepository _repository;
```
public UserService(IUserRepository repository)
{
_repository = repository;
}
즉, _repository와 repository처럼 필드와 매개변수의
명명 규칙 자체를 구분하여 this. 의존성을 줄이는 것입니다.
7. 접근 제한자는 항상 명시
```
기본 접근 제한자에 의존하지 않고 public, private,
protected, internal 등을 명시합니다.
string _name;
```
abstract class BaseService
{
} private string _name;
```
public abstract class BaseService
{
} 또한 modifier 순서에서도 접근 제한자를 가장 앞에 둡니다.
public abstract class BaseService
```
{
}
8. using 정렬
```
using은 namespace 내부가 아니라 파일 상단에 배치하며,
System.* 계열을 우선합니다.
using System; ``` using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging;```
실제 프로젝트에서는 .editorconfig의 using 정렬 설정과 IDE 자동 정렬을 사용하는 것이 좋습니다.
9. var 사용 규칙
```여기서 많은 개발자가 오해하기 쉽습니다. .NET Runtime 스타일은 var를 무조건 금지하지 않습니다. 타입이 오른쪽 표현식에서 명확하게 드러나는 경우 제한적으로 허용합니다.
var stream = new FileStream(path, FileMode.Open); ``` var builder = new StringBuilder();
var stream = OpenStandardInput(); ``` var result = GetResult();
핵심은 "var를 쓰느냐 안 쓰느냐"가 아니라 "코드를 읽는 사람이 타입을 즉시 알 수 있는가"입니다.
```10. C# Keyword를 BCL 타입명보다 우선
```| 지양 | 권장 |
|---|---|
Int32 | int |
String | string |
Single | float |
Int32.Parse() | int.Parse() |
11. Method / Constant Naming
```메서드와 local function은 PascalCase를 사용합니다. 상수 역시 PascalCase를 사용합니다.
private const int DefaultTimeoutSeconds = 30; ``` public async TaskGetUserAsync(int userId) { ... } private static bool IsValidUser(User user) { ... }
12. nameof를 적극 사용
```
매개변수명이나 멤버명을 문자열로 직접 작성하는 대신,
가능한 경우 nameof()를 사용합니다.
throw new ArgumentNullException("user");
throw new ArgumentNullException(nameof(user));
이렇게 하면 변수명을 변경했을 때 문자열을 수동으로 수정해야 하는 문제를 줄일 수 있습니다.
```13. Field는 타입 선언부 상단
```타입 내부에서 필드는 상단에 배치하여 클래스의 상태를 먼저 파악할 수 있도록 합니다.
public sealed class OrderService
```
{
private readonly IOrderRepository _repository;
private readonly ILogger _logger;
```
public OrderService(
IOrderRepository repository,
ILogger logger)
{
_repository = repository;
_logger = logger;
}
public async Task GetAsync(int orderId)
{
...
}
```
}
14. if 단일문 규칙
```특히 중요한 부분입니다. Runtime 규칙에서는 다음과 같은 한 줄짜리 if를 사용하지 않습니다.
if (source == null) throw new ArgumentNullException(nameof(source));
대신 다음과 같이 작성합니다.
if (source == null)
```
{
throw new ArgumentNullException(nameof(source));
}
Runtime 규칙에서는 단일문에 대한 중괄호 생략을 일부 허용하지만,
if / else if / else가 섞인 compound statement에서는 일관성이 중요합니다.
팀 프로젝트에서는 if에는 항상 braces를 사용하도록 통일하는 것이 실무적으로 더 안전합니다.
15. private/internal Type은 sealed/static 고려
```
구현 세부사항인 private/internal 타입을 상속 가능하게 열어둘 필요가 없다면
sealed 또는 static을 사용하는 것을 권장합니다.
private sealed class CacheEntry
```
{
}
private static class CacheHelper
{
}
```
이것은 단순한 스타일 문제가 아니라 해당 타입이 의도적으로 상속을 지원하는지 코드를 통해 명확하게 표현하는 효과도 있습니다.
```16. Primary Constructor
```최신 C#에서는 Primary Constructor를 사용할 수 있습니다. Runtime 규칙에서는 primary constructor parameter를 일반적인 매개변수처럼 camelCase로 작성합니다.
public sealed class UserService( IUserRepository repository, ILogger```logger) ``` { public async Task GetAsync(int userId) { return await repository.GetAsync(userId); } }
타입이 충분히 크거나 constructor parameter가 여러 곳에서 사용되어 가독성이 떨어진다면 명시적인 필드로 저장하는 방식이 더 적절할 수 있습니다.
17. 최신 .NET 프로젝트에서는 EditorConfig가 핵심
```여기서부터가 실제 개발팀에서 가장 중요합니다. Coding Style을 문서로만 정해 놓으면 시간이 지나면서 반드시 코드 스타일이 흔들립니다.
Microsoft 공식 문서에서도 .editorconfig를 통해
프로젝트 또는 저장소 단위의 코드 스타일을 지정할 수 있도록 안내하고 있습니다.
- Repository Root에
.editorconfig배치 - Visual Studio / Rider / VS Code에서 해당 설정 사용
- CI에서
dotnet format검증 - Pull Request 전에 Formatting 오류 제거
18. .editorconfig에서 특히 중요한 설정
```root = true ``` [*] indent_style = space indent_size = 4 [*.cs] dotnet_sort_system_directives_first = true dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning csharp_style_var_for_built_in_types = false:suggestion csharp_style_var_when_type_is_apparent = true:suggestion csharp_style_var_elsewhere = false:suggestion csharp_prefer_braces = true:suggestion csharp_using_directive_placement = outside_namespace:warning csharp_new_line_before_open_brace = all csharp_new_line_before_else = true csharp_new_line_before_catch = true csharp_new_line_before_finally = true```
단, 위 설정은 예시입니다. 실제 프로젝트에서는 현재 사용 중인 .NET SDK, Visual Studio/Rider 버전, 기존 프로젝트의 .editorconfig를 확인한 후 적용해야 합니다.
```19. dotnet format으로 자동 검증
```
dotnet format은 프로젝트의 .editorconfig 설정을 읽어
코드 포맷과 스타일을 검사하거나 수정할 수 있는 .NET CLI 도구입니다.
dotnet format변경 여부 검증
dotnet format --verify-no-changes
특히 CI에서는 --verify-no-changes 방식으로
개발자가 포맷 규칙을 지키지 않은 경우 빌드를 실패시키는 정책을 구성할 수 있습니다.
20. ASP.NET Core 실무 프로젝트에 적용한다면
```실제 ASP.NET Core 프로젝트에서는 단순히 Runtime 문서를 복사하기보다 다음과 같은 규칙을 프로젝트 표준으로 잡는 것을 추천합니다.
PascalCase
PascalCase
camelCase
_camelCase
s_camelCase
PascalCase
21. ASP.NET Core + Clean Architecture에서의 예
```예를 들어 Application 계층의 Service라면 다음과 같은 형태가 Runtime 스타일과 잘 맞습니다.
using Microsoft.Extensions.Logging;
```
namespace GW.Application.Users;
public sealed class UserService
{
private readonly IUserRepository _userRepository;
private readonly ILogger _logger;
```
public UserService(
IUserRepository userRepository,
ILogger logger)
{
_userRepository = userRepository;
_logger = logger;
}
public async Task GetAsync(
int userId,
CancellationToken cancellationToken)
{
if (userId <= 0)
{
throw new ArgumentOutOfRangeException(nameof(userId));
}
User? user = await _userRepository.GetAsync(
userId,
cancellationToken);
if (user == null)
{
return null;
}
return new UserDto
{
UserId = user.UserId,
UserName = user.UserName
};
}
```
}
22. AI Coding 시대에는 이 규칙이 더 중요하다
```최근에는 사람이 모든 코드를 직접 작성하기보다 GitHub Copilot, Claude Code, Cursor, ChatGPT 등의 AI Coding Agent가 코드 생성에 참여하는 경우가 많습니다.
이때 Coding Style을 자연어로만 설명하면 AI가 작업할 때마다 조금씩 다른 스타일을 만들어낼 가능성이 있습니다.
- .editorconfig — 기계가 강제하는 규칙
- Analyzer / IDE Rules — 코드 품질 및 스타일 검사
- dotnet format — 자동 포맷
- Project Coding Guidelines — 팀의 추가 규칙
- AI Agent Instructions — AI가 위 규칙을 따르도록 지시
즉 AI에게 단순히
"C# 코딩 스타일을 지켜라"라고 하는 것보다
실제 Repository의 .editorconfig와 프로젝트 규칙을 기준으로
코드를 생성하도록 하는 것이 훨씬 안정적입니다.
23. 실무용 C# Coding Rule Checklist
```24. 특히 주의해야 할 부분
```Runtime Coding Style ≠ 모든 .NET 프로젝트의 절대 법칙
이것이 가장 중요한 부분입니다.
dotnet/runtime은 Microsoft가 개발하는 매우 큰 핵심 런타임 저장소입니다.
따라서 해당 저장소의 규칙에는 Runtime 프로젝트의 특수한 유지보수 환경을 반영한 규칙도 포함되어 있습니다.
예를 들어 파일 스코프 namespace처럼 최신 C#에서 일반적으로 많이 사용하는 스타일과 특정 저장소의 기존 스타일은 서로 다를 수 있습니다.
따라서 기존 프로젝트에 적용할 때는 현재 프로젝트의 .editorconfig → 기존 코드 스타일 → 팀 Coding Rule → AI Rule 순으로 통합하는 것이 안전합니다.
25. 최종 정리
```C# 스타일의 핵심은 "예쁜 코드"가 아니다
Microsoft .NET Runtime의 Coding Style을 보면 각각의 규칙 자체보다 코드베이스 전체의 일관성이 더 중요하다는 것을 알 수 있습니다.
특히 현대적인 .NET 개발에서는 다음 구조로 가져가는 것을 권장합니다.
그리고 AI Coding Agent를 함께 사용한다면 AI에게 별도의 장황한 스타일 설명을 반복하는 것보다 Repository의 .editorconfig와 Coding Guidelines를 단일 기준으로 삼게 하는 것이 장기적으로 훨씬 안정적인 방법입니다.
26. 공식 출처
```- Microsoft .NET Runtime — C# Coding Style: dotnet/runtime C# Coding Style
- Microsoft Learn — dotnet format: dotnet format 공식 문서
- Microsoft Learn — .NET Code Style Rules: .NET Code Style Rules
- Microsoft Learn — .NET Formatting Options: .NET 서식 지정 옵션
이 글의 Runtime Coding Style 설명은 2026년 9월 14일 확인 기준입니다. Microsoft 및 .NET 프로젝트의 Coding Style, EditorConfig, Analyzer 설정은 향후 변경될 수 있으므로 실제 프로젝트 적용 전 공식 저장소와 Microsoft Learn의 최신 내용을 다시 확인하는 것을 권장합니다.
#CSharp #CSharpCodingStyle #DotNet #DotNetRuntime #ASPNetCore #NET8 #NET9 #NET10 #EditorConfig #DotNetFormat #VisualStudio #CodingConvention #CleanArchitecture #AICoding
대화 참여하기