-
C# 프로그래밍의 기초: 불변 문자열 (Immutable String)2024년 08월 17일
- 유니얼
-
작성자
-
2024.08.17.:28
728x90C#에서 문자열(string)은 불변(immutable) 객체로 설계되어 있습니다. 즉, 한 번 생성된 문자열의 내용을 변경할 수 없습니다. 문자열을 수정하는 것처럼 보이는 작업들은 실제로는 새로운 문자열 객체를 생성하는 것이며, 기존 문자열은 그대로 유지됩니다. 이번 글에서는 불변 문자열의 개념을 이해하고, 이를 통해 문자열이 어떻게 처리되는지, 성능 최적화 방법을 알아보겠습니다.
참고 링크
https://docs.unity3d.com/kr/2020.3/Manual/BestPracticeUnderstandingPerformanceInUnity5.html
불변 문자열이란?
불변(immutable) 객체란, 객체가 한 번 생성된 이후 그 값을 변경할 수 없는 객체를 의미합니다. C#의 문자열은 불변 객체이므로, 문자열을 수정하는 모든 작업은 새로운 문자열 객체를 생성하고, 기존 문자열은 그대로 유지됩니다. 이러한 불변성은 안전한 코드 작성을 가능하게 하지만, 빈번한 수정 작업이 발생할 경우 성능과 메모리 측면에서 비효율적일 수 있습니다.
예제 코드
아래는 C#에서 문자열이 불변임을 보여주는 예제 코드입니다:
using System; namespace Chapter3_String { /// <summary> /// Immutable String (불변 문자열) 학습 자료 /// /// C#에서 문자열이 불변(immutable) 객체임을 이해하는 것이 중요합니다. /// 불변 객체는 생성된 이후에 그 값을 변경할 수 없습니다. /// 문자열을 변경하는 것처럼 보이는 작업은 실제로는 새로운 문자열 객체를 생성하는 것입니다. /// </summary> public class Class5 { public void Run() { // 원래 문자열 생성 string original = "Hello"; Console.WriteLine($"원래 문자열: {original}"); // 출력: Hello // 문자열에 " World" 추가 (새로운 문자열 객체가 생성됨) string modified = original + " World"; Console.WriteLine($"수정된 문자열: {modified}"); // 출력: Hello World // 원래 문자열은 여전히 변경되지 않았음을 확인 Console.WriteLine($"수정 후 원래 문자열: {original}"); // 출력: Hello // 문자열이 불변이기 때문에, 원래 문자열은 변경되지 않았습니다. // 수정된 문자열은 실제로 새로운 문자열 객체입니다. // 추가 설명: // C#에서 문자열(string)은 불변(immutable) 객체입니다. // 이는 한 번 생성된 문자열 객체의 내용을 변경할 수 없음을 의미합니다. // 문자열을 변경하는 것처럼 보이는 작업(예: 문자열 연결, 부분 문자열 변경)은 // 실제로는 새로운 문자열 객체를 생성하고, 기존의 문자열은 그대로 유지됩니다. // 메모리 측면: // 문자열이 불변이기 때문에, 각 수정 작업은 새로운 메모리 공간에 문자열을 할당합니다. // 이는 문자열의 빈번한 수정이 필요한 경우 성능과 메모리 사용 측면에서 비효율적일 수 있습니다. // 이 경우, StringBuilder를 사용하여 문자열을 효율적으로 조작하는 것이 좋습니다. } } }
이 예제에서는 문자열이 불변임을 쉽게 확인할 수 있습니다. 원래 문자열 original은 "Hello"로 유지되며, modified는 "Hello World"라는 새로운 문자열 객체를 생성합니다. 기존의 문자열 original은 변경되지 않았음을 확인할 수 있습니다.
성능과 메모리 측면에서의 고려사항
불변 문자열의 장점은 안전한 코드 작성이 가능하다는 점입니다. 불변성 덕분에 참조된 객체가 의도치 않게 변경되는 상황을 방지할 수 있습니다. 그러나 빈번한 문자열 수정이 필요한 경우, 성능과 메모리 사용 측면에서 비효율적일 수 있습니다. 각 수정 작업마다 새로운 문자열 객체가 생성되고, 이로 인해 메모리 공간이 더 많이 사용됩니다.
예제: 반복적인 문자열 수정
// 반복 횟수 설정 int iterations = 10000; // 1. 문자열 연결 성능 테스트 (불변 문자열 사용) Stopwatch sw1 = Stopwatch.StartNew(); string concatenatedString = ""; for (int i = 0; i < iterations; i++) { concatenatedString += "Frame " + i + " "; } sw1.Stop(); Console.WriteLine($"불변 문자열 사용 시 연결 시간: {sw1.ElapsedMilliseconds} ms"); // 출력 : 불변 문자열 사용 시 연결 시간: 105 ms
위 코드는 += 연산자를 통해 문자열을 계속 연결하는 방식입니다. 그러나 문자열이 불변 객체이기 때문에, 각 연산마다 새로운 문자열 객체가 생성됩니다. 이로 인해 성능이 저하될 수 있습니다.
성능 최적화를 위한 StringBuilder 사용
빈번한 문자열 수정이 필요한 경우, StringBuilder 클래스를 사용하는 것이 성능 면에서 더 효율적입니다. StringBuilder는 가변 객체로, 문자열을 수정할 때 새로운 객체를 생성하지 않고 내부적으로 문자열을 변경할 수 있기 때문에 메모리 효율성과 성능이 높아집니다.
// 반복 횟수 설정 int iterations = 10000; // 2. StringBuilder를 사용한 문자열 연결 Stopwatch sw2 = Stopwatch.StartNew(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < iterations; i++) { sb.Append("Frame ").Append(i).Append(" "); } string optimizedString = sb.ToString(); // StringBuilder는 새로운 객체를 생성하지 않음 sw2.Stop(); Console.WriteLine($"StringBuilder 사용 시 연결 시간: {sw2.ElapsedMilliseconds} ms"); // 출력 : StringBuilder 사용 시 연결 시간: 0 ms
StringBuilder를 사용하면, 문자열을 반복해서 수정할 때 새로운 메모리 할당이 없기 때문에 성능이 크게 향상됩니다.
결론
C#에서 문자열이 불변이라는 사실은 매우 중요한 개념입니다. 문자열을 수정하는 모든 작업은 새로운 문자열 객체를 생성하며, 이는 안전한 코드 작성을 가능하게 합니다. 하지만 성능과 메모리 사용 측면에서는 주의가 필요합니다. 특히 빈번한 문자열 조작이 필요할 때는 StringBuilder와 같은 가변 객체를 사용하는 것이 더 나은 선택일 수 있습니다.
자세한 내용은 Unity 매뉴얼의 문자열과 텍스트 취급에 대한 성능 최적화 가이드를 참고할 수 있습니다. C#의 불변 문자열 특성 때문에 빈번한 수정이 필요한 경우 성능 문제가 발생할 수 있으며, Unity와 같은 환경에서도 이를 최적화하기 위해 StringBuilder의 사용을 권장하고 있습니다.
.
반응형다음글이전글이전 글이 없습니다.댓글