티스토리 뷰

이전 글을 통해서 C#에서 값 형식과 참조 형식에서 어떻게 데이터가 처리가 되고, 메모리 구조에서 어떤식으로 할당/해제 되는지에 대해서 설명드렸습니다. 이에 대한 내용 확인을 원하시면 아래의 링크를 참조해주시기 바랍니다.



이 글에서는 참조 형식을 이용하지만 불변 클래스 기반으로 이루어진 클래스들이 어떻게 처리가 되는지에 대해서 알아보도록 하겠습니다. 그럼 불변클래스(Immutable Class)가 무엇인지 부터 확인을 해볼까요?


1. 불변 클래스란?


불변클래스(Immutable Class)란? 객체의 인스턴스 생성 후 인스턴스가 유지되는 동안 인스턴스가 가지는 값을 변경하지 못하는 클래스를 말합니다. 즉 객체 생성하면서 넣은 값은 인스턴스가 없어질 때 까지 값을 계속 유지하게 되는 클래스입니다. C# 혹은 Java에서 불변 클래스로 유명한 녀석은 String 클래스입니다. 


String 클래스가 메모리 구조에서 어떻게 처리가 되는지를 확인함으로써 불변클래스가 어떻게 처리되는지를 이해할 수 있습니다. 


2. 불변 클래스의 메모리 처리 방식


String 클래스를 처리하는 예제 코드를 살펴보도록 하겠습니다.


class Program

{

static void Main(string[] args)

{

string s = "Hello"; // 1번과정


string ss = s; // 2번 과정


s = s + " " + " and Welcome"; // 3번 과정

}

}


위의 코드에서 1번 과정을 거치게 되면 스택에는 s변수의 값(Hello)에 대한 메모리 주소를 가지고 Heap에는 해당 주소에 맞게 Hello라는 값이 들어가게 됩니다. 




2번 과정을 거치면 ss 변수에 대한 스택메모리에는 Hello의 값을 가지고 있는 주소를 가지게 되고 이에 따라서 ss의 값은 s의 값과 동일한 위치를 참조하게 됩니다. Stack의 메모리 주소에 대한 단순 복사가 일어나는 것은 이 전글의 참조형식의 메모리 할당과 동일합니다. 



하지만 s에 새로운 값을 넣게 되면 어떻게 될까요? s에 새로운 값을 넣으면 힙 메모리의 새로운 장소에 값이 저장이 되게 되고 s에 대한 스택 메모리 값은 새로이 생긴 힙 메모리의 주소를 참조하게 됩니다. 아래의 그림을 통해서 확인할 수 있듯이 s는 6000번지를 참조하게 되고 힙 메모리의 6000번지에는 Hello and Welcome이라는 문자열이 저장됩니다. 따라서 s는 새로운 문자열을 ss는 기존의 Hello 문자열에 대한 주소를 참조하고 있는 것입니다. 



3. 불변 클래스의 장점과 단점


불변 클래스인 문자열 클래스로 선언된 변수에 새로운 값을 넣게 되면 기존에 문자열 클래스가 참조하고 있던 주소에 새로운 값이 들어가는 것이 아니라, 새로운 주소에 새로운 값이 저장이 되게 됩니다. 위와 같은 프로세스로 불변 클래스가 처리되기 때문에 문자열과 같은 불변클래스에 지속적으로 값을 넣는것은 프로세스 처리에 과부하를 줄 수가 있을 뿐 아니라 실행 속도를 저하시키는 단점을 가지고 있습니다.


그럼 이러한 단점을 보완하기 위해서는 어떻게 해야 할까요? 문자열 클래스를 예로 설명하자면 버퍼를 통해서 문자열을 만들어주는 클래스를 활용하는 법이 있습니다. 문자열의 불변 클래스의 단점을 보완하기 위해서 C#과 Java는 StringBuilder와 같은 클래스를 제공해 주고 있습니다. StringBuilder 클래스는 String 클래스와 다르게 불변클래스가 아니기 때문에 하나의 Heap 메모리에 변경되는 값을 저장합니다.


StringBuilder에 대한 MSDN 설명을 참조해보면 아래와 같습니다.

String 개체는 변경할 수 없습니다. System.String 클래스의 메서드 중 하나를 사용할 때마다 공간을 새로 할당해야 하는 새 문자열 개체가 메모리에 생성됩니다. 문자열을 반복적으로 수정해야 하는 경우에는 String 개체를 새로 만드는 작업으로 인한 오버헤드가 클 수도 있습니다. 개체를 새로 만들지 않고 문자열을 수정하려면 System.Text.StringBuilder 클래스를 사용합니다. 예를 들어, StringBuilder 클래스를 사용하면 많은 문자열을 루프에서 연결함으로써 성능을 높일 수 있습니다.


그렇다면 불변클래스를 왜 사용하는 것일까요? 불변클래스의 가장 큰 장점은 Thread-Safe입니다. 객체의 상태와 값이 바뀌지 않기 때문에 어떠한 쓰레드에서 관련 객체를 사용하더라도 안전합니다. 


C#으로 프로그램을 개발하다 보면 UI Thread와 Main Program의 Thread의 충돌이 일어나는 것을 많이 볼 수 있습니다. 이를 해결하기 위해 Invoke 메소드를 사용할 수도 있지만, 불변 클래스 기반이라면 이러한 Thread 사이의 충돌에 대한 염려는 하지 않아도 됩니다. 


이 글에서는 문자열 클래스가 메모리 상 어떻게 처리되고, 이로 인해 불변클래스가 어떻게 처리되는지 간략히 알아보았습니다.


이 글이 도움이 되셨나요?

그렇다면 아래의 그림을 클릭해주세요.


댓글