ITEM 9 :: EFFECTIVE C#
안녕하세요, 9번째 시간입니다. 어느덧 내일이면 두자리수가 되어버리네요!
이번 챕터에는 박싱과 언박싱이라는 단어가 나옵니다. 아주 쉽게 이해만하려면 형변환의 일종으로 보면 되고, 조금 깊게 보려면 내부적으로 돌아가는 상황을 알아야 합니다. 하지만, 그렇게 어렵지 않으므로, 시작해보겠습니다! 가시죠!
설명
-
먼저, 각 타입의 원형이 존재하는지부터 봐야 한다. C#이전의 C에서는 값 타입은 주로 값을 저장할 때 쓰는 저장소이며, 해당하는 타입만을 받아들일 수 있어 다형적이지 못하다.
-
하지만, C#부터는 모든 타입의 최상위 타입이 System.Object로써 존재한다. 모든 값 타입은 Object형에 포함된다는 소리이다.
-
이는 자바와 어느정도 비슷한 양상을 띈다.
-
여기서 박싱과 언박싱이 나온다. 박싱은 값 타입의 객체를 타입이 정해져 있지 않은 임의의 참조 타입 내부에 포함시키는 방법이다.
-
조금 어렵게 느껴질 수도 있는데, 쉽게 말해서, 값 타입의 객체를 임의의 참조 타입인 Object형으로 변환한다는 의미이다.
-
언박싱은 박싱의 과정을 보면 쉽게 유추해낼 수 있다. 즉, Object형으로 변환된 객체를 다시 값 타입의 객체로 변환하는 것을 의미한다.
-
따라서, 이 박싱과 언박싱을 이용하면 모든 타입에 대한 형변환이 가능해짐을 의미한다.
-
하지만, 그 사용을 권하지는 않는다. 왜냐하면, 박싱과 언박싱은 성능에 좋지 않은 영향을 미치기 때문이다.
-
그 영향의 예로, 박싱과 언박싱을 수행하는 과정에서 생기는 임시 객체의 부하나, 컴파일러가 내부적으로 박싱과 언박싱을 시도하면서 생기는 시스템적인 부하가 있다. 그 외에도 있을 수 있고.
-
이 과정을 조금 자세히 보도록 하자.
박싱과 언박싱
-
값 타입을 참조 타입으로 변경하는, ‘박싱’을 하는 과정에서는 새롭게 생성된 참조 타입의 객체가 힙에 생성되며, 값 타입의 복사본이 새롭게 생성된 객체의 내부에 저장된다.
-
즉, 단적으로 말해서, 새롭게 생성된 참조 타입의 객체가 커다란 박스라고 치면, 그 안에 작은 박스 형태로, 값 타입의 복사본이 저장된다는 의미이다.
-
이 박스를 ‘컨테이너’라고 한다.
-
여기서 값 타입 객체의 복사본에 접근하기 위해서 모든 메서드들은 컨테이너를 지나쳐 내부의 저장된 값타입으로 전달된다. (이는 아래의 코드를 참고하자)
int i = 25;
object o = i; // 박싱
Console.WriteLine(o.ToString()); //문자열로 25를 출력
//---------------------------------------------------//
object firstParm = 5; //컨테이너를 지나쳐 값 타입에 접근
object o = firstParm;
int i = (int)o; // 언박싱
string output = i.ToString();
//---------------------------------------------------//
-
참고로 위의 코드는 실제 오브젝트형 파일을 출력하려고 할 때, 컴파일러에서 추가적으로 박싱과 언박싱을 시도하는 코드이기도 하다.
-
즉, 특정 객체에 값을 넘길 때, Object형으로 넘기게 되면 내부적으로 자동 값 타입 변환(박싱과 언박싱)이 된다는 말이다.
-
이는 성능상 취약점으로 이어지기 때문에 이를 개선하고 싶다면 오브젝트 타입만을 전달하지 말고, 해당하는 값 타입으로 변환하여 전달하는 것이 좋다. (컴파일러에서 자동적으로 변환하는 것을 막기 위해서)
정리
결론적으로 값 타입은 System.Object 타입이나 여타의 인터페이스 타입으로 변경할 수 있다. 이러한 변환 작업은 암시적으로 이뤄지며, 실제로 어떤 부분에서 이러한 변환 작업이 행해지는지도 찾아내기가 쉽지않다. 수행환경과 개발 언어별로 다양한 규칙이 존재하기 때문인데, 박싱과 언박싱 작업은 부지불식간에 객체에 대한 복사본을 생성하곤 하여, 이로인해 버그가 발생할 수 있고, 값 타입을 다형적으로 처리하는 과정에서 성능상 이슈를 만들어낸다.
따라서, 값 타입을 오브젝트형으로, 오브젝트형을 값타입으로 바꾸는 코드들은 최대한 자제하고, 만약 해야된다면 미리 박싱과 언박싱을 수행하여 컴파일러에서 자동적으로 박싱과 언박싱하는 부분을 줄이자.