CodeGym /행동 /C# SELF /자동 프로퍼티와 init-only setter

자동 프로퍼티와 init-only setter

C# SELF
레벨 17 , 레슨 2
사용 가능

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; }
    }
}
private 필드가 있는 수동 프로퍼티

이런 코드는 진짜 "노잼" (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;

도식적으로

방법 문법 값 접근
필드
public string Name;
직접 접근 가능
수동 프로퍼티
public string Name { get; set; } + private string name;
get/set으로 접근
자동 프로퍼티
public string Name { 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; }
private setter — 클래스 내부에서만 변경 가능

이러면 클래스 내부(메소드나 생성자 등)에서만 값을 바꿀 수 있어.

쓰기 전용: 비추

이론상 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; }
}
init-setter 프로퍼티

이제 이렇게 쓸 수 있어:

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;
}
기본값이 있는 init-only 프로퍼티

이제 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이 실제로 접근 가능한지 꼭 확인해.

2
과제
C# SELF, 레벨 17, 레슨 2
잠금
init-only 프로퍼티 사용하기
init-only 프로퍼티 사용하기
2
과제
C# SELF, 레벨 17, 레슨 2
잠금
자동 프로퍼티와 초기값
자동 프로퍼티와 초기값
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION