목차
프로퍼티는 외부에서는 일반 '변수(Field)'처럼 보이지만, 실제로는 내부적으로 '메서드(접근자)'처럼 동작하는 C#의 강력한 기능입니다. 데이터의 안전을 지키면서도 사용의 편의성을 제공하는 '똑똑한 변수'라고 할 수 있습니다.
1. 일반 변수(Field)의 한계
보통 유니티에서 변수를 선언할 때 다음과 같이 작성하는 경우가 많습니다.
// 일반적인 필드(Field) 방식
public float speed;
이렇게 변수를 public으로 열어두면, 외부의 다른 클래스에서 이 변수에 접근해 값을 마음대로 오염(잘못된 값 대입)시킬 수 있는 치명적인 위험이 존재합니다. 프로퍼티는 이 문제를 해결하기 위해 읽기 권한은 열어두되, 수정 권한은 닫거나 제어하는 방식을 사용합니다.
2. 자동 구현 프로퍼티와 접근 제어
별도의 복잡한 로직이 필요 없을 때, 코드를 한 줄로 매우 간결하게 줄여주는 방식입니다.
public float Speed { get; set; }
// 읽기(get)는 누구나, 쓰기(set)는 이 클래스 내부에서만 가능하도록 제한!
public float Speed { get; private set; }
3. 백킹 필드(Backing Field)와 로직 추가
프로퍼티에 단순히 값을 넣고 빼는 것을 넘어, 조건이나 로직(예: 체력이 0 이하로 내려가지 않게 방어)을 추가해야 할 때가 있습니다. 이때는 실제 데이터가 저장될 진짜 변수인 백킹 필드를 숨겨두고 사용합니다.
private int _hp; // 실제 데이터가 저장되는 진짜 변수 (백킹 필드)
public int HP
{
get
{
return _hp;
}
set
{
// 외부에서 대입하려는 값은 'value'라는 키워드에 담겨 옵니다.
if (value < 0)
_hp = 0;
else
_hp = value;
}
}
4. 식 본문 정의 (=> 화살표)
읽기 전용 프로퍼티를 만들거나 코드를 축약할 때 => 기호를 사용합니다. 아래의 두 코드는 내부적으로 완전히 동일하게 동작합니다.
// 1. 화살표 축약형
public int HP => _hp;
// 2. 원래 형태
public int HP
{
get { return _hp; }
}
5. 최신 문법: field 키워드 (C# 13/14)
과거에는 set에 제약 조건(ex: value < 0 방지)을 걸기 위해 반드시 _hp 같은 명시적인 백킹 필드를 따로 선언해야 했습니다. 컴파일러가 자동으로 만들어주는 백킹 필드의 이름이 너무 복잡해서 코드에서 직접 부를 수 없었기 때문입니다.
하지만 C# 13 이후부터는 field 키워드가 도입되어, 별도의 변수 선언 없이도 숨겨진 백킹 필드에 직접 접근해 데이터를 검증하거나 수정할 수 있게 되었습니다.
public int Score
{
get => field;
set
{
if (value < 0)
field = 0;
else
field = value;
}
}
6. 초기화와 필수 조건 제어 (init, required)
데이터가 생성되는 시점을 더욱 엄격하게 통제할 수 있습니다.
- init (초기화 제어): 언제든지 값을 바꿀 수 있는 set과 달리, 객체를 생성하는 순간에만 값을 넣을 수 있고 이후에는 수정이 불가능합니다.
- required (필수 프로퍼티): 객체를 생성할 때 이 프로퍼티의 값을 반드시 넣도록 강제합니다. 누락 시 컴파일 에러를 발생시킵니다.
// 객체 생성 시 Name을 무조건 할당해야 하며, 이후 수정 불가
public required string Name { get; init; }
7. 계산된 프로퍼티 (Computed Property)
자신만의 데이터 저장 공간(백킹 필드, 금고)을 가지지 않고, 누군가 값을 요청(get)할 때마다 내부에 작성된 로직(함수)을 실행하여 즉석에서 결과값을 만들어내는 프로퍼티입니다. (메모리 공간 대신 호출 시점의 CPU 연산을 사용합니다.)
💡 계산된 프로퍼티를 사용하는 3가지 핵심 이유
- 데이터 엇갈림(버그) 원천 차단 (단일 진실 공급원, SSOT) 🛡️
- 원본 데이터(예: HP) 하나만 남기고, 파생되는 상태(예: IsDead)는 원본을 바탕으로 매번 계산해서 가져옵니다.
- 상태를 저장하는 변수를 여러 개 두었을 때, 업데이트를 깜빡해서 발생하는 치명적인 논리 버그를 구조적으로 막아줍니다.
- 관리해야 할 상태의 최소화 (리팩터링 원칙) 🧹
- 마틴 파울러의 소프트웨어 설계 원칙처럼, 기존 변수를 통해 쉽게 계산해낼 수 있는 값은 굳이 새로운 변수로 만들어 메모리에 올려두지 않습니다. 관리할 변수의 개수가 줄어들어 코드가 단순하고 예측 가능해집니다.
- 완벽한 캡슐화와 사용의 편의성 (정보 은닉) 📦
- 외부 스크립트에서는 그저 평범한 변수(player.IsDead)를 읽는 것처럼 아주 쉽게 사용할 수 있습니다. 동시에 내부적으로 어떤 복잡한 계산이나 검증을 거치는지는 완벽하게 숨겨줍니다.
- 외부 스크립트에서는 그저 평범한 변수(player.IsDead)를 읽는 것처럼 아주 쉽게 사용할 수 있습니다. 동시에 내부적으로 어떤 복잡한 계산이나 검증을 거치는지는 완벽하게 숨겨줍니다.
본문은 C# Learn을 바탕으로 공부하고, 제미나이 '학습에 관한 도움 받기'를 통한 공부 후 정리한 내용임을 밝힙니다.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
https://learn.microsoft.com/ko-kr/dotnet/csharp/programming-guide/classes-and-structs/properties
'개념공부' 카테고리의 다른 글
| Reflection (0) | 2026.03.26 |
|---|---|
| C# Type (0327 수정) (0) | 2026.03.26 |
| 동기와 비동기 (0) | 2026.03.12 |
| Delegate,Action,Event,UnityEvent (0) | 2026.03.04 |
| 동적 계획법 (Dynamic Programming, DP) (0) | 2025.03.19 |