## C#의 public sealed record 이해하기
C++에서는 데이터 전달용 객체(DTO)나 VO(Value Object)를 만들 때 struct나 가벼운 class를 정의하고, 대입 연산자나 비교 연산자(==)를 일일이 오버로딩해야 했습니다. C#의 record는 이 번거로운 과정을 컴파일러가 자동으로 처리해 주는 '불변(Immutable) 데이터 모델' 정의 방식입니다.
### 1. 왜 C++의 헤더나 함수 선언처럼 보였을까? (기본 생성자 Syntax)
C#에서는 레코드를 선언할 때 다음과 같이 한 줄로 끝내는 구문(Primary Constructor)을 자주 사용합니다.
// 이 한 줄이 클래스 선언, 멤버 변수 생성, 생성자 구현을 모두 포함합니다.
public sealed record DeviceConfig(int Frequency, int NominalCurrent, string AssignedPhase);
이 형식이 마치 클래스의 본문(Body) 없이 함수 프로토타입만 적어놓은 것처럼 보이기 때문에, C++ 개발자 입장에서는 "함수만 선언해서 쓰는 건가?"라는 오해를 불러일으킬 수 있습니다. 하지만 이는 컴파일러가 컴파일 시점에 완벽한 클래스 구조로 확장해 줍니다.
### 2. 각 키워드의 의미와 C++ 매핑
- record: 내부 멤버들이 기본적으로 readonly(C++의 const)로 동작하며, 값 기반 비교(Value-based equality)를 지원하는 클래스를 생성합니다. (구조체처럼 내부 값이 같으면 == 연산 시 true를 반환합니다.)
- sealed: 이 클래스를 더 이상 상속할 수 없도록 제한합니다. C++11의 final 키워드와 정확히 동일합니다. 가상 함수 테이블 오버헤드를 줄이고 컴파일러 최적화를 도울 수 있어 성능상 유리합니다.
## C++ 개발자를 위한 C# record 핵심 특징 (C++과의 비교)
1. 값 기반 비교 (Value Equality)
C++이나 기존 C# 클래스에서는 두 인스턴스의 참조(주소)가 다르면 내부 값이 같아도 false를 반환하므로 연산자 오버로딩이 필요했습니다. record는 컴파일러가 모든 필드를 비교하는 구문을 자동 생성합니다.
[cite_start]var config1 = new DeviceConfig(60, 100, "PHA-A"); [cite: 56]
[cite_start]var config2 = new DeviceConfig(60, 100, "PHA-A"); [cite: 56]
bool isEqual = (config1 == config2); // True (C++에서는 일일이 연산자 재정의를 해야 했던 부분)
2. 불변성(Immutability)과 안전성
통신 프로토콜 파싱 데이터나 장치 설정 값(Setting)처럼 데이터가 중간에 오염되면 안 되는 아키텍처에 매우 유용합니다. 한 번 생성된 record 객체의 내부 값은 변경할 수 없습니다.
3. 비파괴적 변형 (with 식)
"설정 데이터 중 주파수(Frequency)만 50Hz로 바꾸고 나머지는 그대로 유지한 새 객체"를 만들고 싶을 때, C++에서는 복사 생성자 호출 후 수정해야 하지만 C# 레코드는 with 키워드로 우아하게 처리합니다.
// config1을 복사하되, Frequency만 50으로 변경된 새 인스턴스 생성
var newConfig = config1 with { Frequency = 50 };
## 결론 및 아키텍처 조언
현재 개발 중이신 CMR 프로젝트의 ETCMR Software 및 .NET MAUI 모바일 앱 구조를 보면 , 장치의 세팅(XML 데이터 기반), 상태 값 계측, 블루투스 LE로 송수신되는 패킷 데이터 처리가 핵심으로 보입니다.
검토하신 public sealed record 구조는 바로 이러한 블루투스 통신 패킷 데이터 객체나 장치 설정(System Frequency, Nominal Current 등)의 불변 레코드를 정의하는 데 가장 최적화된 C# 고유의 방식입니다.
'.NET' 카테고리의 다른 글
| ResiliencePipeline 클래스란 무엇인지? (0) | 2026.06.16 |
|---|---|
| C# 숫자 리터럴 중간에 들어간 언더바(_) 사용 (0) | 2026.06.16 |
| IServiceCollection를 확장하는 메서드 (0) | 2026.06.16 |
| MFC 개발자 대상 .NET 8 기반 IPC 샘플 코드 기반 교육 (0) | 2026.06.16 |
| .NET 8 개발 전환을 위한 핵심 개발자 패러다임 시프트 교육 로드맵 (0) | 2026.06.16 |