[C#]Boxing/Unboxing (박싱/언박싱)

2022. 4. 12. 22:45Programming language/C#

    목차

이 글은 이전에 운영하던 깃 블로그에서 옮겨온 글입니다.

 

서론

 C#을 이용하여 코딩을 하면서, 혹은 유니티 스크립트를 짤 때 'object'라는 자료형을 자주 봤을 겁니다. 이 자료형은 어떤 타입의 변수든 할당하여 사용할 수 있는 녀석입니다.

object number = 10; 
objcet str = "CodingGom";

위처럼 같은 자료형인 것 같은데, 다른 값을 사용할 수 있습니다. 마치 C/C++의 'auto' 나 C#의 'var'처럼 말이다.

물론 같은 것 이라거나, 비슷한 개념이라는 건 아닙니다. 전혀 다른 개념이죠. auto, var 키워드는 타입을 추론하는 자동 변수들입니다. 런타임이 아닌 컴파일 단계에서 타입이 정해지도록 지정해 놓는 녀석들인 것이죠. 즉, 타입을 '명시적'으로 지정하지 않아도 대입된 값에 따라 컴파일러가 추론을 해주도록 하는 것들입니다.

 

 여기서 키워드는 '명시적'이다 라는 겁니다. 명시적이라는 말의 사전적 뜻은 '내용이나 을 분명하게 드러내 보이는. 또는 그런 것'입니다. object 타입은 어떤 값이든 대입할 때는 '명시적'으로 타입을 지정하지 않아도 되지만, 사용할 때는 타입을 '명시' 해주어야 한다. 아래의 예를 보면 이해에 도움이 될 것입니다.

object obj = 30.0f; 

float temp1 = obj; // error 

float temp2 = (float)obj; // non-error

차이점이 보이나요? object 타입의 값을 사용할 때는 항상 '명시적'으로 타입을 지정해줘야 합니다. 자, 그럼 왜 이렇게 되는 것일까요?


Boxing / Unboxing (박싱 / 언박싱)

 물건을 담을 상자가 하나 있다고 가정해 보겠습니다. 이 상자에는 어떤 물건이든 담을 수 있을 것입니다. 사실 담는 물건이 중요한 건지 상자가 중요한 게 아닐 테니 말이죠. 상자에 어떤 걸 담느냐에 따라 상자의 가치는 변합니다.

 

 여기서 상자가 object 타입의 변수이고, 담는 물건이 object 타입을 결정할 값입니다. 즉, 상자인 object 타입의 변수에 어떤 (가치) 물건을 담 든 잘 사용할 수 있다는 것입니다. 상자는 단지 물건을 담고(참조) 있을 뿐이니 말이죠. 사용할 때 어떤 물건인지 알려주면(명시적 타입 지정) 됩니다.

 

 Boxing(박싱) 이란 단어 그대로 물건(값 형식)을 박스(참조 형식)에 넣어주는것을 말합니다. (값 형식 => 참조 형식)
Unboxing(언박싱) 이란 단어 그대로 박스(참조 형식)에서 물건(값 형식)을 꺼내는 것을 말합니다.
"이 상자에는 어떤 가치(타입) 의 물건이 들어있으니 꺼내라"라는 것이죠. (참조 형식 => 값 형식)

 objcet 형이 이러한 작동이 가능한 이유는, 모든 타입(int, float, string, char, 구조체…)의 최상위 부모이기 때문입니다.(object = System.Object / 상속) c/c++에서 최상위 부모로 포인터를 받고, 캐스팅해서 사용했던 포인터의 개념을 생각하면 쉬울 것 같습니다.


어떤 타입이든 넣고 사용할때만 명시해서 사용하고 싶을 때 object 타입을 사용하면 참 편리할 것입니다.


Boxing / Unboxing (박싱 / 언박싱)의 단점

 몸에 좋은 약은 쓰고, 달콤한건 몸에 해롭다는 말이 있습니다. (달콤한 게 정신건강에는 좋은 거 같은데...)
아무리 편리하다고 해도, 편리에는 그만한 비용이 따르게 됩니다. 사용할 때마다 타입을 캐스팅해서 써야 하기 때문에 Boxing / Unboxing (박싱 / 언박싱)은 부하가 걸리는 주된 원인이 되기도 합니다.

 위에서 설명하길 Boxing / Unboxing (박싱 / 언박싱) 은 참조 형식 <=> 값 형식 의 과정이라고 했습니다. 즉, 힙과 스택을 오가며 메모리 복사가 일어난다는 것입니다.

 Boxing 과정에서는 스택에 저장되어있는 값을 힙에 복사하고, 힙에 복사된 값을 object가 참조합니다. Unboxing 은 참조하고 있는 object를 타고 가, 힙에 있는 값을 복사하여 스택으로 가져와 사용합니다. 이과정이 상당히 비싼 비용을 지불해야 하죠… 성능적으로…


마무리

 Boxing / Unboxing (박싱 / 언박싱) 은 편할지 모르지만, 비용이 비싸서 잘못 사용할 경우 성능 부하가 걸립니다. 메모리 복사가 빈번하게 일어나다 보니 그에 따른 비용과 임시 값들을 사용하기 때문에 가비지 컬렉션에도 걸립니다. 당연한 이야기지만 Boxing 되지 않은 변수는 Unboxing 해서 사용할 수 없습니다. 있지도 않은 상자를 풀어헤칠 수는 없으니 말이죠.

반응형
LIST

'Programming language > C#' 카테고리의 다른 글

[C#]닷넷(.Net)의 구성 요소  (0) 2022.08.09
[C#]닷넷(.Net)에 관하여  (0) 2022.08.07
[C#]컬렉션(Collection)  (0) 2022.04.19
[C#]제네릭(Generic)  (0) 2022.04.14
[C#]가비지 컬렉터(Garbage collector)  (0) 2022.04.12