N Log

Getter, Setter

들어가는 말

클래스의 멤버 변수를 private 접근 제어자(Access Modifier)로 선언하면 외부에서 멤버 변수에 직접 접근할 수 없다.
이를 통해 내부 구현을 숨기고 데이터를 보호하는 정보 은닉(Information Hiding)을 구현할 수 있다.
하지만 이로 인해 외부에서 값을 읽거나 수정할 수 있는 방법이 사라진다.
이 글에서는 이러한 문제를 해결하기 위한 getter, setter 함수에 대해 전통적인 방법부터 C#에서 제공하는 방식을 알아보자.

1. 함수를 이용한 전통적인 방식

get은 “가져오다”라는 의미의 동사이고, set은 “설정하다”라는 의미의 동사이다.
-er는 동작을 수행하는 주체를 나타내는 접미사다.
따라서 Getter는 “값을 가져오는 역할을 하는 것”, Setter는 “값을 설정하는 역할을 하는 것”이라는 의미다.

Getter와 Setter는 별도의 특별한 문법이 아니라 단순한 메서드로 구현된다.
이 방식은 특정 언어에 종속되지 않으며, 어떤 객체지향 언어에서도 동일하게 사용할 수 있다.

public class Box
{
    private int _size;

    public Box(int size)
    {
        SetSize(size);
    }

    public int GetSize()
    {
        return _size;
    }

    public void SetSize(int size)
    {
        if (size <= 0)
            throw new ArgumentException("Size must be greater than 0.");
        _size = size;
    }
}
Box box = new Box(5);

Console.WriteLine(box.GetSize()); // 5

box.SetSize(10);
Console.WriteLine(box.GetSize()); // 10

box.SetSize(-1); // ArgumentException thrown

메서드 이름은 예제처럼 GetSize, SetSize 형태로 작성할 수도 있고, getSize, setSize처럼 작성할 수도 있다.
이는 언어나 팀의 코딩 컨벤션에 따라 달라지며, 문법적으로 강제되는 부분이 아니다.

1-1. 문제점: 반복적이고 장황한 코드

이 방식은 필드 하나마다 Getter와 Setter 메서드를 각각 작성해야 한다.
IDE의 자동 생성 기능으로 쉽게 만들 수 있지만, 필드가 하나 추가될 때마다
두 개의 메서드가 함께 추가되어 클래스 파일의 코드가 점점 길어진다.
이러한 문제를 해결하기 위해 프로그래밍 언어 또는 라이브러리 차원에서 다양한 방법이 제공된다.

2. C# 프로퍼티

C#은 getter/setter 패턴을 프로퍼티(Property) 문법으로 제공한다.
프로퍼티를 사용하면 마치 필드처럼 값에 접근할 수 있으면서, 실제 내부적으로는 정의된 getter와 setter 메서드를 통해 읽기/쓰기 동작이 수행된다.

2-1. Full Property (C# 1.0, 2002)

값을 실제로 저장하는 _size 같은 필드를 backing field라고 부르며, 프로퍼티는 이 값을 읽고 설정하는 역할을 한다.
value는 setter에 전달되는 암시적(묵시적) 매개변수다.

public class Box
{
    private int _size; // backing field
    public int Size
    {
        get { return _size; }
        set
        {
            if (value <= 0)
                throw new ArgumentException("Size must be greater than 0.");
            _size = value;
        }
    }

    public Box(int size)
    {
        Size = size;
    }
}
Box box = new Box(5);

Console.WriteLine(box.Size); // 5

box.Size = 10;
Console.WriteLine(box.Size); // 10

box.Size = -1; // ArgumentException thrown

2-2. Auto-implemented Property (C# 3.0, 2007)

getter/setter에 별도 로직이 필요 없다면, backing field 선언 없이 간략하게 작성 할 수 있다.
내부적으로 컴파일러가 자동으로 backing field를 생성하지만, 프로그래머가 직접 접근할 수는 없다.

public class Person
{
    public string Name { get; set; };
}
Person p = new Person();

p.Name = "Tom";
Console.WriteLine(p.Name); // "Tom"

2-3. Field Backed Property (C# 14, 2025)

기존 두 가지 방식에는 각각 아쉬운 점이 있다.
Full Property는 로직을 추가할 수 있지만 backing field와 프로퍼티를 선언해야 해서 코드가 길어진다.
Auto-implemented Property는 간결하지만 로직을 추가할 수 없다.

  • field : 컴파일러가 생성한 backing field에 접근하는 키워드
  • value : setter에 전달되는 암시적 매개변수
public class Person
{
    public string Name
    {
        get;
        set => field = value.Trim();
    }
}
Person p = new Person();

p.Name = " Tom "
Console.WriteLine(p.Name); // "Tom"

2-4. 차이점 정리

방법 필드 선언 로직 추가 코드 길이
Full Property 수동 가능
Auto-implemented Property 자동 불가능 짧음
Field-backed Property 자동 가능 짧음

3. 참고