DevDino

[Unity 기술면접] C# string은 왜 불변(Immutable) 객체일까? 본문

Unity/기술면접

[Unity 기술면접] C# string은 왜 불변(Immutable) 객체일까?

데브다이노 2026. 1. 2. 18:26

"C#에서 string이 왜 불변 객체인가요?"

C# string은 왜 불변(Immutable) 객체일까?

 

string의 불변성(Immutability)이란?

C#의 string 객체는 한 번 생성되면 메모리상의 값을 절대 수정할 수 없습니다.
우리가 문자열을 수정하거나 합치는 것처럼 보이는 모든 연산은 사실상 새로운 string 객체메모리에 할당하여 반환하는 방식으로 동작합니다.

 

C#은 왜 string을 불변으로 설계했을까?

- 메모리 최적화 (String Pool): 값이 변하지 않음을 보장하므로, 똑같은 문자열 리터럴을 여러 번 선언해도 힙(Heap) 메모리에는 하나만 생성하여 참조를 공유할 수 있습니다.


- 멀티스레드 안정성(Thread-Safe): 여러 스레드에서 동시에 접근하더라도 값이 변하지 않으므로 동기화(Lock) 과정 없이 안전하게 사용할 수 있습니다.


- 보안 및 자료구조의 안정성: 값이 도중에 위변조될 위험이 없어 보안에 유리하며, 해시(Hash) 코드가 변하지 않아 DictionaryHashSet의 Key로 사용하기에 완벽합니다.

 

불변성이 성능에 미치는 영향

불변성은 안전성 측면에서 훌륭하지만, 문자열을 자주 변경하는 환경에서는 치명적인 성능 저하를 유발할 수 있습니다.

string s = "";
for (int i = 0; i < 1000; i++ )
    s += i;  // 루프를 돌 때마다 새로운 string 객체가 힙 메모리에 계속 생성됨 

위와 같이 문자열을 반복해서 결합하면, 사용되지 않는 수많은 가비지(Garbage) 객체가 쌓이게 됩니다.
유니티에서는 이러한 힙 메모리 할당(GC Alloc)의 폭증이 곧 GC(Garbage Collector) 스파이크를 유발하고, 결과적으로 게임의 프레임 드랍(끊김 현상)으로 이어지게 됩니다.

StringBuilde의 활용

문자열을 여러 번 수정하고 조립해야하는 상황에서는, 새 객체를 계속 생성하지 않고 내부 버퍼를 사용하여 문자열을 조작하는 StringBuilder가 훨씬 효율적입니다.

using System.Text;
// ...
StringBuilder sb = new StringBuilder();
for (int i = 0;i < 1000; i++)
    sb.Append(i);  // 새로운 객체 할당 없이 내부 버퍼에서 문자열 결합

요약
string은 불변 객체이므로 스레드 안정성과 메모리 공유(String Pool) 이점을 가진다.
하지만 문자열 변경 연산이 잦을 경우, 과도한 GC Alloc으로 인해 프레임이 저하될 수 있다.
따라서 반복적인 문자열 조립이 필요한 경우에는 반드시 StringBuilder를 사용해야 한다.

참고
.NET에서 StringBuilder 클래스 사용