1. 자동 프로퍼티
C#에서 프로퍼티(property)는 필드와 메소드의 중간쯤 되는 거야. 사실상, 캡슐화를 엄청 편하게 해주는 syntactic sugar라고 보면 돼. 프로퍼티를 그냥 필드처럼 쓰지만, 내부적으로는 아무 로직이나 넣을 수 있어: 데이터 체크, 다른 필드 변경, 메소드 호출, 심지어 네 할머니한테 이메일 보내기도 가능(마지막은 비추). 지난 강의에서는 프로퍼티를 직접 썼었지. 근데 100500개나 되는 단순 객체에 "getter"랑 "setter"만 필요할 때는 금방 질려버려.
자, 자동 프로퍼티 등장! 이걸로 boilerplate 코드에서 해방되고, 값 저장은 C#이 알아서 해줘.
예전 방식: 수동 프로퍼티
필드를 숨기고 프로퍼티로 접근하게 하고 싶으면 보통 이렇게 썼어:
public class Dog
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
이런 코드는 진짜 "노잼" (boilerplate)이야. 사실 get/set에 뭘 더 넣을 필요도 없는데! 그냥 접근만 주면 끝이지.
이제는 이렇게
C#에서는 이제 필드를 직접 안 써도 돼 — 컴파일러가 알아서 해주거든. 그냥 이렇게만 쓰면 돼:
public class Dog
{
public string Name { get; set; }
}
이제 끝. Name 값을 읽고 바꿀 수 있고, 내부적으로는 컴파일러가 private 필드를 만들어서 외부에서 직접 접근 못 하게 해.
실제로 무슨 일이 일어나냐면? 코드에 public string Name { get; set; }가 있으면, 컴파일러가 Name__BackingField 같은 숨겨진 필드를 자동으로 만들어. Name에 접근할 때마다 필요한 getter나 setter를 넣어주지. 필드는 코드에서 직접 못 보지만, 리플렉션으로 찾을 수도 있어(근데 그건 또 다른 얘기).
이 방식의 장점? 첫째, 훨씬 짧고 반복 안 해도 돼. 둘째, 코드가 깔끔해져서 읽고 관리하기 쉬워. 마지막으로, 더 안전해 — 아무도 필드를 직접 못 건드리고, 무조건 프로퍼티로만 접근 가능.
2. 자동 프로퍼티 문법
문법 진짜 간단해:
public class Dog
{
public string Name { get; set; }
public int Age { get; set; }
}
이제 Dog 클래스가 훨씬 간결해졌지! 객체를 만들고 값을 이렇게 줄 수 있어:
Dog myDog = new Dog();
myDog.Name = "바르보스";
myDog.Age = 4;
도식적으로
| 방법 | 문법 | 값 접근 |
|---|---|---|
| 필드 | |
직접 접근 가능 |
| 수동 프로퍼티 | |
get/set으로 접근 |
| 자동 프로퍼티 | |
get/set + 숨겨진 필드 |
3. 접근 커스터마이징: 읽기 전용, 쓰기 전용
읽기 전용: get-only
프로퍼티를 읽기만 하고 싶을 때(예: 반려동물 등록번호), get만 쓰거나 set을 아예 안 쓰거나 private으로 만들면 돼. 이런 값은 생성자나 선언할 때만 할당 가능:
public class Dog
{
public string RegistrationCode { get; }
public Dog()
{
RegistrationCode = "DOG-001"; // 생성자에서 값 할당
}
}
이제 외부에서는 RegistrationCode를 읽기만 가능하고, 바꿀 수 없어. 중요한 데이터를 실수로 바꾸지 못하게 막는 좋은 방법이야.
또 다른 방법: private set
public string Name { get; private set; }
이러면 클래스 내부(메소드나 생성자 등)에서만 값을 바꿀 수 있어.
쓰기 전용: 비추
이론상 set-only 프로퍼티(쓰기 전용)도 만들 수 있지만, 거의 안 쓰고 비추야 — "블랙홀" 객체처럼 뭔가 넣을 수만 있고 다시 꺼낼 수는 없는 거니까.
4. init-only setter
약간의 배경
예전에는 불변 객체(immutable)를 만들려면 get-only 프로퍼티만 쓰고 생성자에서 값 할당했어. 괜찮긴 한데, 항상 편한 건 아니지. 근데 최근 C#에 init-only 프로퍼티 문법이 생겼어.
init-setter의 핵심?
- 객체 생성 시점에만 프로퍼티 값을 할당할 수 있어(즉 생성자 또는 객체 이니셜라이저에서).
- 객체가 만들어진 후에는 읽기 전용이 돼.
- "거의 불변" 클래스, DTO, 설정, 모델에 딱이야.
public class Dog
{
public string Name { get; init; }
public int Age { get; init; }
}
이제 이렇게 쓸 수 있어:
Dog dog = new Dog { Name = "보빅", Age = 2 };
dog.Name = "렉스"; // 오류! 생성 후에는 읽기 전용
생성자에서도 값 할당 가능:
public Dog(string name, int age)
{
Name = name;
Age = age;
}
도식: 언제 할당 가능?
| 어디서 할당? | { get; set; } | { get; private set; } | { get; init; } |
|---|---|---|---|
| 클래스 외부, 생성 후 | ✅ | ❌ | ❌ |
| 생성자에서 | ✅ | ✅ | ✅ |
| 이니셜라이저에서 | ✅ | ❌ | ✅ |
| 클래스 내부 | ✅ | ✅ | ❌ (생성자 제외) |
5. 실전에서 사용하기
Dog 클래스를 자동 프로퍼티와 init-only 프로퍼티로 다시 써보자:
public class Dog
{
// 초기화 때만 할당되는 프로퍼티
public string Name { get; init; }
public int Age { get; init; }
// 현재 상태를 위한 자동 프로퍼티
public bool IsHungry { get; set; }
// 강아지 행동 메소드
public void Bark()
{
Console.WriteLine($"{Name} 말한다: 멍!");
}
}
이제 Dog 객체를 이렇게 만들 수 있어:
Dog dog = new Dog { Name = "샤릭", Age = 3, IsHungry = true };
dog.Bark(); // 출력: 샤릭 말한다: 멍!
dog.IsHungry = false; // 이 프로퍼티는 생성 후에도 변경 가능
dog.Name = "바르보스"; // 오류! 초기화 전용 프로퍼티
6. 자동 프로퍼티의 기본값
C#은 진짜 편하게 해놨어. 프로퍼티에 기본값도 바로 줄 수 있어:
public class Dog
{
public string Name { get; set; } = "이름없음";
public int Age { get; set; } = 0;
}
또는 init으로도 가능:
public class Dog
{
public string Name { get; init; } = "강아지";
public int Age { get; init; } = 0;
}
이제 Name을 지정 안 하면 "강아지"가 기본값이야.
7. 자동 프로퍼티의 접근 제한자 조합
프로퍼티의 get/set에 서로 다른 접근 제한자를 줄 수도 있어:
public class Dog
{
public string Name { get; private set; }
public int Age { get; private set; }
public Dog(string name, int age)
{
Name = name;
Age = age;
}
}
이 경우 Dog 클래스 내부(메소드나 생성자 등)에서만 이름과 나이를 바꿀 수 있어.
수동 vs 자동 프로퍼티 비교
| 방식 | 작성 난이도 | set/get 제어 | 생성 후 변경 가능성 | 모델에서 사용 |
|---|---|---|---|---|
| 수동 프로퍼티 | 길다 | 완전 제어 | 아무거나 | 로직 필요할 때 |
| 자동 프로퍼티 | 짧다 | 없음 | 아무거나 또는 private | 거의 다 |
| init-only 자동 | 짧다 | 없음 | 생성 시에만 | DTO, 설정 |
8. 프로퍼티 사용 시 흔한 실수
실수 1: get-only 프로퍼티에 생성자 외에서 값을 할당하려고 함.
프로퍼티가 get만 있으면, 컴파일러가 생성자나 선언 외에는 값을 못 바꾸게 막아. 까먹으면 컴파일 에러 나니까 주의!
실수 2: 필드와 프로퍼티를 헷갈림.
일반 필드를 자동 프로퍼티로 바꿀 때, 기존 코드에서 필드에 직접 접근하는 부분이 없는지 꼭 확인해야 해. 필드랑 프로퍼티는 완전 다르고, 예전 코드가 남아 있으면 컴파일 에러나 예측 불가한 동작이 나올 수 있어.
실수 3: private set의 의미를 제대로 모름.
프로퍼티에 private set이 있는데, 외부 코드에서 값을 바꾸려고 하면 에러야. 특히 남의 코드 복붙할 때 자주 생기니까, set이 실제로 접근 가능한지 꼭 확인해.
GO TO FULL VERSION