[C#] 박싱, 언박싱 정리

Lumos Velog·2025년 7월 24일
0

박싱(Boxing)

박싱이란 값 타입(Value Type) 데이터를 참조 타입(Reference Type)으로 변환하는 과정이다.
쉽게 말해, 스택(Stack)에 존재하는 값을 힙(Heap)에 복사해서, 객체(Object)처럼 사용하는 것.


예시

int num = 123;           // 값 타입 (스택에 저장)
object obj = num;        // 박싱 발생 (힙에 int 값을 복사, obj는 참조 타입)

이 코드를 실행하면, 다음과 같은 일이 발생한다.

  • num이라는 int 값(값 타입)이 있다.

  • object는 참조 타입이기 때문에, 값을 직접 가질 수 없다.

  • 이 때, CLR(Common Language Runtime)이 num의 값을 힙 영역에 새로 복사해서, 그 참조를 obj에 저장한다.

  • 결국 obj는 int 값을 담은 객체를 가리키게 된다.


동작 구조

  • 값 타입(예: int, double, struct 등)을 object, 인터페이스 타입 등에 할당하거나, 메서드에 파라미터로 넘길 때 박싱 발생.

  • 박싱이 일어나면 값이 힙에 새로운 객체로 복사됨.

  • 이 과정에서 런타임 오버헤드(추가적인 메모리 사용 및 성능 저하)가 발생할 수 있음.




언박싱(Unboxing)

언박싱은 참조 타입(object 등)에 저장된 값을 원래의 값 타입으로 다시 꺼내오는 과정이다.
즉, 힙에 저장된 값을 다시 스택에 복사하는 것.

예시

object obj = 123;           // 박싱
int num = (int)obj;         // 언박싱
  • obj는 힙에 저장된 int 값을 가리킨다.

  • (int)obj를 통해 언박싱을 수행하면, 힙에 있는 int 값이 다시 스택에 복사된다.

  • 반드시 명시적 형변환(캐스팅)이 필요하다. (암시적으로 불가능)


동작 구조

  • 언박싱 시, object(혹은 인터페이스)의 참조가 원래의 값 타입인지 검사한다.

  • 만약 타입이 다르면 InvalidCastException이 발생한다.

  • 타입이 맞으면, 힙에 있던 값을 스택에 복사.




주의사항

  • 성능이슈
    박싱/언박싱은 암묵적으로 힙 메모리 할당과 복사, 그리고 타입 체크가 이루어져 성능 저하의 원인이 된다.
    박싱이 빈번히 발생하는 코드(예: 박싱된 값의 반복적 사용, 컬렉션에서 값 타입을 object로 다루는 경우 등)는 최적화 필요.

  • 자주 발생하는 상황
    Object 타입 컬렉션 사용 - C# 2.0 이전에는 List 등 컬렉션이 object 기반이었기 때문에 값 타입을 넣으면 항상 박싱/언박싱 발생.
    예시: ArrayList list = new ArrayList(); list.Add(1);
    또 값 타입이 인터페이스로 변환될 때 박싱이 발생할 수 있고 메서드 파라미터가 object일 때, 값 타입 인자를 object 파라미터로 전달 시 박싱한다.

  • 줄이는 방법
    제네릭은 컴파일 타임에 타입이 결정되므로, 박싱/언박싱이 발생하지 않는다.
    또 object, 인터페이스 대신 구체적 값 타입 사용하면 줄일 수 있다.

  • 예외
    박싱된 값을 잘못된 타입으로 언박싱 시
    런타임 예외(InvalidCastException)가 발생한다.
object obj = 123;
double d = (double)obj;    // 예외 발생


가급적 박싱/언박싱을 피하기 위해 제네릭, 구체적 타입 사용을 권장한다.
내부 동작, 성능 이슈, 예외 발생 케이스까지 잘 이해해야 효율적이고 안정적인 C# 코드를 작성할 수 있다.



0개의 댓글