coding-conventions

이 SKILL은 개발되는 모든 .NET 프로젝트에 적용되는 코딩 규약을 정의합니다. .NET 8 이후의 최신 기능(C# 12/13/14, .NET 8/9/10)을 적극적으로 활용하여 가독성, 유지보수성, 성능이 높은 코드를 구현하는 것을 목적으로 합니다.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "coding-conventions" with this command: npx skills add icartsh/icartsh_plugin/icartsh-icartsh-plugin-coding-conventions

Coding Conventions

개요

이 SKILL은 개발되는 모든 .NET 프로젝트에 적용되는 코딩 규약을 정의합니다. .NET 8 이후의 최신 기능(C# 12/13/14, .NET 8/9/10)을 적극적으로 활용하여 가독성, 유지보수성, 성능이 높은 코드를 구현하는 것을 목적으로 합니다.

책임 범위

이 SKILL은 다음 범위를 다룹니다:

  • .NET/C#의 최신 기능(C# 12/13/14, .NET 8/9/10) 활용 방침

  • 명명 규칙 (Type, Member, Variable, Parameter)

  • 코드 레이아웃 및 포맷

  • 언어 기능 사용 방침 (Type inference, Collection, Exception handling)

  • LINQ와 람다식의 모범 사례

  • 모던 C# 구문의 권장 패턴

기본 방침

  • .NET 8 이후의 최신 기능을 적극적으로 사용한다 (C# 12/13/14, .NET 8/9/10)

  • 이전 버전과의 호환성이 필요한 경우를 제외하고 항상 최신 기능을 우선한다

  • 오래된 언어 구문은 피한다

  • 중요: 언더스코어 접두사(_field ) 사용은 절대 금지한다

  • 중요: 중괄호 생략은 절대 금지한다 (1행으로 기술할 수 있는 경우에도 생략 불가)

  • Microsoft 공식 코딩 규약을 따른다

  • 일관성을 유지하고 팀 전체에서 동일한 스타일을 적용한다

.NET/C# 최신 기능 (버전별)

.NET 8 이후 각 버전에서 도입된 주요 기능을 적극적으로 활용합니다. 이전 버전과의 호환성이 필요한 경우를 제외하고 항상 최신 기능을 우선적으로 사용합니다.

C# 12 (.NET 8) - 2023년 11월 공식 릴리스

Primary Constructors

  • 클래스나 struct 선언에서 파라미터를 정의하고 클래스 전체에서 사용할 수 있음

  • 명시적인 필드 선언을 줄이고 초기화를 간소화함

좋은 예:

public class Person(string name, int age) { public string Name => name; public int Age => age;

public void Display()
{
    Console.WriteLine($"{name} is {age} years old");
}

}

나쁜 예:

public class Person { private string name; private int age;

public Person(string name, int age)
{
    this.name = name;
    this.age = age;
}

public string Name => name;
public int Age => age;

}

Collection Expressions

  • 대괄호와 스프레드 연산자를 사용하여 컬렉션을 간결하게 생성함

  • 여러 컬렉션을 결합할 때 유용함

좋은 예:

int[] array = [1, 2, 3, 4, 5]; List<string> list = ["one", "two", "three"];

int[] row0 = [1, 2, 3]; int[] row1 = [4, 5, 6];

// 스프레드 연산자로 결합 int[] combined = [..row0, ..row1];

Default Lambda Parameters

  • 람다식에 기본 파라미터 값을 지정할 수 있음

좋은 예:

var incrementBy = (int source, int increment = 1) => source + increment;

Console.WriteLine(incrementBy(5)); Console.WriteLine(incrementBy(5, 3));

Alias Any Type

  • using 디렉티브로 복잡한 타입에 별칭을 붙일 수 있음

좋은 예:

using Point = (int x, int y); using ProductList = System.Collections.Generic.List<(string Name, decimal Price)>;

Point origin = (0, 0); ProductList products = [("Product1", 100m), ("Product2", 200m)];

C# 13 (.NET 9) - 2024년 11월 공식 릴리스

Params Collections

  • params 수식어를 배열 외의 컬렉션 타입에서도 사용 가능해짐

  • List<T> , Span<T> , ReadOnlySpan<T> , IEnumerable<T> 등에서 사용 가능

좋은 예:

public void ProcessItems(params List<string> items) { foreach (var item in items) { Console.WriteLine(item); } }

// 메모리 효율이 중요한 경우 public void ProcessData(params ReadOnlySpan<int> data) { foreach (var value in data) { Process(value); } }

New Lock Type

  • System.Threading.Lock 타입을 사용하여 더 빠른 스레드 동기화를 구현함

  • 기존 Monitor 기반 락보다 빠름

좋은 예:

private readonly Lock lockObject = new();

public void UpdateData() { lock (lockObject) { // Critical section } }

나쁜 예:

// 기존 object 기반 락 (C# 13에서는 권장되지 않음) private readonly object lockObject = new();

public void UpdateData() { lock (lockObject) { // Critical section } }

Partial Properties and Indexers

  • partial 프로퍼티와 인덱서를 사용할 수 있게 됨

  • 정의와 구현을 분리할 수 있음

좋은 예:

// 정의 부분 public partial class DataModel { public partial string Name { get; set; } }

// 구현 부분 public partial class DataModel { private string name;

public partial string Name
{
    get => name;
    set => name = value ?? throw new ArgumentNullException(nameof(value));
}

}

Implicit Index Access

  • 객체 이니셜라이저에서 ^ 연산자를 사용할 수 있게 됨

좋은 예:

var countdown = new TimerBuffer { buffer = { [^1] = 0, [^2] = 1, [^3] = 2 } };

Ref Struct Enhancements

  • ref struct 타입이 인터페이스를 구현할 수 있게 됨

  • 제네릭 타입에서 ref struct 를 사용할 수 있게 됨 (allows ref struct 제약 조건)

좋은 예:

public ref struct SpanWrapper<T> : IEnumerable<T> { private Span<T> span;

public IEnumerator&#x3C;T> GetEnumerator()
{
    foreach (var item in span)
    {
        yield return item;
    }
}

}

C# 14 (.NET 10) - 2025년 11월 릴리스 예정

Extension Members

  • Extension Members를 활용하여 깔끔한 API 확장을 구현함

  • 원래 타입을 오염시키지 않고 기능을 추가할 수 있음

좋은 예:

extension<TSource>(IEnumerable<TSource> source) { public bool IsEmpty => !source.Any(); public int Count => source.Count(); }

Field-Backed Properties

  • field 키워드를 사용하여 명시적인 backing field를 줄임

  • 검증 로직을 간결하게 기술할 수 있음

  • 언더스코어 접두사를 사용한 명시적인 backing field는 절대 금지

좋은 예:

// C# 14의 field 키워드 사용 public string Name { get; set => field = value ?? throw new ArgumentNullException(nameof(value)); }

// 어쩔 수 없이 명시적인 backing field가 필요한 경우에도 언더스코어 없음 private string name;

public string Name { get => name; set => name = value ?? throw new ArgumentNullException(nameof(value)); }

나쁜 예:

// 언더스코어 접두사는 절대 금지 private string _name;

public string Name { get => _name; set => _name = value ?? throw new ArgumentNullException(nameof(value)); }

Null-Conditional Assignment

  • ?. 를 사용하여 null 체크를 간결하게 기술함

  • 중복되는 null 체크를 줄임

좋은 예:

customer?.Order = GetCurrentOrder();

나쁜 예:

if (customer != null) { customer.Order = GetCurrentOrder(); }

Implicit Span Conversions

  • 성능 중시 코드에서는 Span<T> 와 ReadOnlySpan<T> 를 활용함

  • 배열과 스팬 타입 간의 자동 변환을 이용함

명명 규칙 (Naming Conventions)

Pascal Casing

  • 타입 이름 (class, record, struct, interface, enum)

  • 퍼블릭 멤버 (프로퍼티, 메서드, 이벤트)

  • 네임스페이스

좋은 예:

public class CustomerOrder { public string OrderId { get; set; } public void ProcessOrder() { } }

Camel Casing

  • 로컬 변수

  • 메서드 파라미터

  • 프라이빗 필드 (언더스코어 접두사는 절대 사용하지 않음)

좋은 예:

public class OrderProcessor { // 언더스코어 없음 private string customerName;

// 언더스코어 없음
private int orderCount;

public void ProcessOrder(string orderId)
{
    var customerName = GetCustomerName(orderId);
    string processedResult = Process(customerName);
}

}

나쁜 예:

public class OrderProcessor { // 언더스코어 접두사는 절대 금지 private string _customerName;

// 언더스코어 접두사는 절대 금지
private int _orderCount;

}

Interface 명명

  • 접두사 I 를 사용함

좋은 예:

public interface IOrderProcessor { void Process(Order order); }

타입 파라미터 명명

  • 접두사 T 를 사용함

  • 의미 있는 이름을 붙임

좋은 예:

public class Repository<TEntity> where TEntity : class { public void Add(TEntity entity) { } }

코드 레이아웃 (Code Layout)

들여쓰기

  • 공백(Space) 4개를 사용함

  • 탭(Tab)은 사용하지 않음

중괄호 (Curly Braces)

  • Allman 스타일 (시작 중괄호와 종료 중괄호를 별도의 행에 배치)

  • 중괄호 생략은 절대 금지 (1행으로 기술할 수 있는 경우에도 반드시 중괄호 사용)

좋은 예:

public void ProcessOrder(Order order) { if (order != null) { order.Process(); } }

// 1행이라도 중괄호를 사용함 if (isValid) { Execute(); }

for (int i = 0; i < 10; i++) { Process(i); }

나쁜 예:

// 중괄호 생략 금지 if (isValid) Execute();

// 중괄호 생략 금지 for (int i = 0; i < 10; i++) Process(i);

// 중괄호 생략 금지 if (order != null) order.Process();

행 기술

  • 1행에 하나의 statement만 기술함

  • 1행에 하나의 선언만 기술함

  • 메서드 정의와 프로퍼티 정의 사이에 빈 행을 하나 넣음

좋은 예:

public class Order { public string OrderId { get; set; }

public void Process()
{
    var result = Validate();
    Execute(result);
}

private bool Validate()
{
    return OrderId != null;
}

}

네임스페이스

  • 파일 스코프 네임스페이스(File-scoped namespace)를 사용함

좋은 예:

namespace YourProject.Orders;

public class OrderProcessor { // Implementation }

나쁜 예:

namespace YourProject.Orders { public class OrderProcessor { // Implementation } }

using 디렉티브

  • 네임스페이스 선언 바깥쪽에 배치함

  • 알파벳 순으로 정렬함

좋은 예:

using System; using System.Collections.Generic; using System.Linq;

namespace YourProject.Orders;

타입과 변수

타입 지정

  • 언어 키워드 (string , int , bool )를 사용함

  • 런타임 타입 (System.String , System.Int32 )은 사용하지 않음

좋은 예:

string name = "John"; int count = 10; bool isValid = true;

나쁜 예:

String name = "John"; Int32 count = 10; Boolean isValid = true;

타입 추론 (var)

  • 타입이 할당되는 내용으로부터 명백한 경우에만 var 를 사용함

  • 기본 제공 타입(Built-in type)은 명시적으로 기술함

좋은 예:

// 명백함 var orders = new List<Order>();

// 명백함 var customer = GetCustomer();

// 기본 타입은 명시 int count = 10;

// 기본 타입은 명시 string name = "John";

나쁜 예:

// 기본 타입에서 var는 피함 var count = 10;

// 기본 타입에서 var는 피함 var name = "John";

문자열

문자열 보간 (String Interpolation)

  • 짧은 문자열 결합에는 문자열 보간을 사용함

좋은 예:

string message = $"Order {orderId} processed successfully";

나쁜 예:

string message = "Order " + orderId + " processed successfully";

StringBuilder

  • 루프 내에서 대량의 텍스트를 추가하는 경우 StringBuilder 를 사용함

좋은 예:

var builder = new StringBuilder(); for (int i = 0; i < 1000; i++) { builder.Append($"Line {i}\n"); }

Raw String Literals

  • 이스케이프 시퀀스보다 Raw String Literals를 우선함

좋은 예:

string json = """ { "name": "John", "age": 30 } """;

컬렉션과 객체 초기화

컬렉션 초기화

  • C# 12 이후의 Collection Expressions를 사용함 (앞부분의 "C# 12 최신 기능" 참조)

객체 이니셜라이저 (Object Initializer)

  • 객체 이니셜라이저를 사용하여 생성을 간소화함

좋은 예:

var customer = new Customer { Name = "John", Email = "john@example.com" };

예외 처리 (Exception Handling)

구체적인 예외 캐치

  • 일반적인 System.Exception 대신 구체적인 예외를 캐치함

좋은 예:

try { ProcessOrder(order); } catch (ArgumentNullException ex) { Logger.Error("Order is null", ex); }

나쁜 예:

try { ProcessOrder(order); } catch (Exception ex) // 너무 일반적임 { Logger.Error("Error", ex); }

using 문

  • try-finally 대신 using 문을 사용함

좋은 예:

using var connection = new SqlConnection(connectionString); connection.Open(); // Process

나쁜 예:

SqlConnection connection = null; try { connection = new SqlConnection(connectionString); connection.Open(); // Process } finally { connection?.Dispose(); }

LINQ

의미 있는 변수명

  • 쿼리 변수에는 의미 있는 이름을 사용함

좋은 예:

var activeCustomers = from customer in customers where customer.IsActive select customer;

조기 필터링

  • where 절을 사용하여 조기에 데이터를 필터링함

좋은 예:

var result = customers .Where(c => c.IsActive) .Select(c => c.Name) .ToList();

암시적 타입 지정

  • LINQ 선언에서는 암시적 타입 지정을 사용함

좋은 예:

var query = from customer in customers where customer.IsActive select customer;

람다식 (Lambda Expressions)

이벤트 핸들러

  • 삭제가 필요 없는 핸들러에는 람다식을 사용함

좋은 예:

button.Click += (s, e) => ProcessClick();

파라미터 수식어

  • C# 14 기능을 활용하여 타입 추론을 유지하면서 수식어를 사용함

좋은 예:

TryParse<int> parse = (text, out result) => int.TryParse(text, out result);

주석 (Comments)

단일 행 주석

  • 간결한 설명에는 // 를 사용함

  • 주석 구분자 뒤에 공백을 하나 넣음

  • 주석은 반드시 단독 행에 기술함 (코드와 같은 행에 기술 금지)

  • 주석 앞에는 빈 행을 하나 넣음

좋은 예:

// 고객 주문을 처리함 ProcessOrder(order);

var processor = new OrderProcessor();

// 주문을 실행함 var result = processor.ProcessOrder(order);

나쁜 예:

ProcessOrder(order); // 고객 주문을 처리함 (코드와 같은 행은 금지)

var processor = new OrderProcessor(); // 이 행의 앞에 빈 행이 없음 (나쁜 예) var result = processor.ProcessOrder(order);

XML 문서

  • 퍼블릭 멤버에는 XML 문서를 사용함

좋은 예:

/// <summary> /// 지정된 주문을 처리함 /// </summary> /// <param name="order">처리할 주문</param> /// <returns>처리 결과</returns> public bool ProcessOrder(Order order) { // Implementation }

정적 멤버 (Static Members)

클래스 이름에 의한 호출

  • 정적 멤버는 클래스 이름을 통해 호출함

좋은 예:

var result = OrderProcessor.ProcessOrder(order);

나쁜 예:

var processor = new OrderProcessor();

// 정적 메서드를 인스턴스를 통해 호출하는 것은 오해의 소지가 있음 var result = processor.ProcessOrder(order);

체크리스트 (Checklist)

코드 작성 전

  • .NET/C#의 최신 기능 (C# 12/13/14)을 파악하고 있음

  • 프로젝트의 타겟 프레임워크가 .NET 8 이후로 설정되어 있음

  • 명명 규칙을 이해하고 있음

코드 작성 중

필수 규칙:

  • 언더스코어 접두사를 절대 사용하지 않았음

  • 중괄호를 생략하지 않았음 (1행이라도 반드시 사용함)

  • 주석은 반드시 단독 행에 기술했음 (코드와 같은 행에 기술하지 않았음)

  • 주석 앞에 빈 행을 하나 넣었음

C# 12 이후 기능:

  • Primary Constructors를 사용하고 있음 (해당하는 경우)

  • Collection Expressions를 사용하고 있음

  • Default Lambda Parameters를 활용하고 있음 (해당하는 경우)

  • Alias Any Type으로 복잡한 타입에 별칭을 붙였음 (해당하는 경우)

C# 13 이후 기능:

  • Params Collections를 사용하고 있음 (해당하는 경우)

  • New Lock Type을 사용하고 있음 (스레드 동기화가 필요한 경우)

  • Partial Properties and Indexers를 활용하고 있음 (해당하는 경우)

  • Implicit Index Access를 객체 이니셜라이저에서 사용하고 있음 (해당하는 경우)

C# 14 이후 기능:

  • field 키워드를 사용하여 backing field를 간결하게 기술했음

  • Extension Members를 활용하고 있음 (해당하는 경우)

  • Null-Conditional Assignment를 활용하고 있음

  • Lambda Parameters with Modifiers를 사용하고 있음 (해당하는 경우)

기본 규칙:

  • 파일 스코프 네임스페이스를 사용하고 있음

  • 언어 키워드 (string , int )를 사용하고 있음

  • var 를 적절히 사용하고 있음 (타입이 명백한 경우에만)

  • 문자열 보간을 사용하고 있음

  • Raw String Literals를 사용하고 있음 (해당하는 경우)

  • Object Initializers를 사용하고 있음

  • using 문을 사용하고 있음

  • 구체적인 예외를 캐치하고 있음

  • LINQ 식에서 조기 필터링을 실시하고 있음

  • 의미 있는 변수명을 사용하고 있음

  • 주석이 간결하고 명확함

  • 퍼블릭 멤버에 XML 문서를 기술했음

  • Allman 스타일로 중괄호를 배치했음

  • 들여쓰기에 공백 4개를 사용하고 있음

코드 작성 후

  • 코드가 일관된 스타일로 작성되었음

  • .NET 8 이후의 최신 기능 (C# 12/13/14)을 활용하고 있음

  • 명명 규칙을 따르고 있음

  • 가독성이 높고 유지보수하기 쉬운 코드임

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

error-detective

No summary provided by upstream source.

Repository SourceNeeds Review
General

markdown-pro

No summary provided by upstream source.

Repository SourceNeeds Review
General

file-organizer

No summary provided by upstream source.

Repository SourceNeeds Review