본문 바로가기
C#

C# 에서 readonly 는 참조 타입에서 어떻게 동작할까?

by Oz Driver 2025. 4. 1.

C#에서 readonly 키워드는 필드가 "한 번만 초기화될 수 있다"는 의미를 갖습니다. 많은 개발자들이 이 키워드를 단순히 "변경 불가"로 이해하지만, 참조 타입에 적용되었을 때는 조금 다르게 동작한다는 점을 놓치는 경우가 많습니다.

이 글에서는 readonly 키워드가 값 타입과 참조 타입에서 어떻게 다르게 작동하는지, 그리고 참조는 고정되지만 내부 값은 바뀔 수 있다는 사실을 예제와 함께 정리합니다.

 

 

값 타입에서의 readonly

readonly가 값 타입(int, float, bool 등) 에 붙으면, 해당 변수는 초기화된 값을 절대 변경할 수 없습니다.

readonly int number = 10;
number = 20; // ❌ 컴파일 오류 - 값 변경 불가

 

값 타입은 변수 자체가 데이터를 직접 저장하기 때문에, readonly는 값 자체를 고정합니다.

 

 

참조 타입에서의 readonly

private readonly string[] wordList;

 

참조 타입 (배열, 클래스 등) 에 readonly를 붙이면, 변수에 저장된 참조(주소)를 변경할 수 없게 됩니다. 즉, 한 번 어떤 객체나 배열을 참조하게 되면, 다른 객체로 바꾸는 것은 불가능합니다.

하지만 참조 대상(객체, 배열)의 내부 값은 여전히 변경 가능합니다!

 

생성자에서만 초기화 가능

public WordWarrior()
{
    wordList = new string[] { "apple", "banana" }; // ✅ 생성자 안에서는 초기화 가능
}

public void ResetWords()
{
    wordList = new string[] { "grape", "lemon" }; // ❌ 오류: 생성자 밖에서는 재할당 불가
}

 

readonly 필드는 생성자 내부에서만 한 번 초기화할 수 있습니다. 이후에는 참조를 변경할 수 없습니다.

 

참조 대입은 불가능

readonly string[] currentWords = new string[] { "sun", "moon", "stars" };

string[] newWords = new string[] { "ocean", "mountain" };

currentWords = newWords; // ❌ 불가능: 참조 자체를 바꿀 수 없음

 

readonly는 참조 변수의 주소값을 변경할 수 없도록 제한합니다. 따라서 다른 참조 변수나 새로운 배열을 대입하는 것도 불가능합니다.

 

배열 내부 값은 수정 가능

wordList[0] = "updated"; // ✅ 가능

 

참조는 바꿀 수 없어도, 참조하고 있는 배열의 내부 데이터는 얼마든지 수정 가능합니다. 이 점에서 readonly는 "불변"과는 다르며, 단지 참조의 이동만 막는 역할을 한다고 이해하면 됩니다.

 

 

핵심 정리

* readonly 는 변수의 값을 바꾸지 못하게 막는 키워드입니다.

* 값 타입(int, float 등) 은 변수 자체가 데이터를 담고 있어서 값 변경이 금지됩니다.

* 참조 타입(array, class 등) 은 변수의 값이 주소이기 때문에 참조(주소)만 고정되고, 참조 대상의 내부 값은 변경 가능합니다.

* 생성자에 한해서 한 번 변경할 수 있기 때문에, 초기화는 보통 생성자에서 수행합니다.

 

 

그렇다면, const 와의 차이점

const는 컴파일 시점에 값이 고정되는 상수입니다. 
선언과 동시에 반드시 값을 설정해야 하며, 숫자나 문자열 같은 단순한 값에만 사용할 수 있습니다.

반면 readonly는 런타임에 한 번만 값을 설정할 수 있고, 배열이나 클래스처럼 조금 더 복잡한 타입에도 사용할 수 있는 장점이 있습니다.

 

예를 들면,

const string[] colors = { "red", "green" }; // ❌ 불가능

 

그래서 const는 절대 변하지 않는 숫자나 문자열 같은 값에, readonly 는 한 번 설정해두고 유지되어야 하는 배열이나 객체에 적합합니다.

 

 

마무리

readonly는 단순히 "변경 금지" 키워드가 아닙니다. 값 타입과 참조 타입에서 전혀 다르게 작동하며, 특히 참조 타입에서는 내부 값을 얼마든지 바꿀 수 있다는 점을 기억해야 합니다. 값 자체가 중요한 경우에는 const를 사용하고, 객체 참조만 고정하고 내부는 유연하게 관리하고 싶을 때는 readonly를 사용하는 것이 적절합니다.