[C#] 값 형식과 참조형식


값 형식 : 변수가 값을 담는 데이터 형식.

참조 형식 : 변수가 값 대신 값이 있는 곳의 위치(참조)를 담는 데이터 형식.


이 둘을 이해하려면 두 가지 메모리 영역에 대해 알고있어야 한다.

바로 스택(Stack)힙(Heap)이다.


이 메모리 영역 중 값 형식과 관련이 있는 것은 스택 메모리 영역이고,

참조 형식과 관련 있는 것은 메모리 영역이다.



1. 스택과 값 형식.


스택에 대해 이야기 해보자.

스택의 구조는 마치 책상 위에 쌓인 책이라고 생각하면 된다.




맨 밑에 있는 책을 읽고 싶다면, 위에 있는 책들을 모두 걷어낸 후에나 가능할 것이다.

스택 메모리도 이렇게 동작한다. 다음과 같은 코드를 작성했다고 하자.


1
2
3
4
5
{ // 코드 블록 시작
    int a = 10;
    int b = 20;
    int c = 30;
} // 코드 블록 끝
cs



이렇게 선언된 세 변수 a,b,c는 차례대로 스택에 쌓였다가 코드 블록이 끝나면서 스택에서 걷혀 제거된다.

※ 블록을 닫는 괄호 "}"을 만나는 순간 스택에 있는 데이터들이 c,b,a의 순서대로 걷혀진다.



값 형식의 변수는 모두 이 스택에 저장된다.

다시 말해 코드 블록 안에서 생성된 모든 값 형식의 변수들은 중괄호 "}"을 만나면 메모리에서 제거된다.




2. 힙과 참조 형식


메모리 관리가 깔끔한 스택에 반해 힙은 데이터를 스스로 제거할 수 있는 매커니즘을 가지고 있지 않다.

대신 청소부 같은 존재를 고용하고 있는데, 그 청소부의 이름은 가비지 컬렉터(Garbage Collector)이다.

힙에 더 이상 사용하지 않는 객체가 있으면 그 객체를 쓰레기로 간주하고 수거해 가는 기능을 가지고 있다.


그렇다면 왜 굳이 가비지 컬렉터가 필요한 힙 영역을 사용하는 걸까?

스택에 쌓인 데이터들은 코드 블록이 사라지는 시점에서 함께 제거된다.

이것은 스택에 장점이기도 하지만, 동시에 한계이기도 하다.


코드 블록이 끝나는 시점과 상관없이 데이터를 유지하고 싶을 때는 스택의 구조가 발목을 잡는 요소가 된다.


그래서 또 다른 메모리 영역인 힙을 제공하는 것이다.

힙은 코드 블록이 종료되는 것과 관계없이 그 데이터를 게속 유지할 수 있다. 

그리고 이 데이터는 프로그래머가 더 이상 사용하지 않을 때가 됐을 때 가비지 컬렉터가 수거해 제거 한다.


참조 형식의 변수는 힙과 스택을 함께 사용하는데, 힙 영역에는 데이터를 저장하고, 스택 영역에는 데이터가 저장된

힙의 메모리의 주소를 저장한다. 그래서 참조 형식이라는 이름이 붙은 것이다.


참조 형식으로 변수를 선언해보자.

1
2
3
4
{
    object a = 10;
    object b = 20;
}
cs


실제 값 10과 20은 힙 영역에 저장하고, a와 b는 값이 저장된 힙의 주소만 스택에 저장하게 된다.



블록이 끝난 시점에서 스택의 값은 사라진다. 하지만 힙에 남은 값을 사라지지 않는다.



힙의 남은 값은 더 이상 데이터를 참조하는 곳이 없을 때 가비지 컬렉터가 수거해 간다.