값 형식과 참조 형식 (Value Type & Reference Type)

C#의 값 형식과 참조 형식을 학습합니다. Stack과 Heap 메모리의 차이와 데이터가 저장되고 복사되는 방식을 이해합니다.

15. 값 형식과 참조 형식 (Value Type & Reference Type)

메모리(memory) 구조 이해하기

C#에서는 데이터를 저장하는 방식에 따라 **값 형식(Value Type)**과 **참조 형식(Reference Type)**으로 나뉩니다.

Stack과 Heap

Stack (스택)

  • Last In First Out (LIFO): 마지막에 들어온 것이 먼저 나감
  • 값 형식 데이터가 저장되는 곳
  • 빠른 접근 속도
  • 작은 크기의 데이터에 적합

Heap (힙)

  • 참조 형식 데이터가 저장되는 곳
  • 동적으로 크기가 변할 수 있는 데이터
  • 메모리(memory) 주소(참조)를 통해 접근

값 형식 (Value Type)

값 형식은 Stack에 저장되며, 데이터(값)를 직접 저장하는 방식입니다.

값 형식의 특징

  • 데이터를 직접 복사
  • 변수(variable)에 값을 할당하면 값 자체가 복사됨
  • 한 변수(variable)를 변경해도 다른 변수(variable)에 영향 없음

값 형식 예시

int a = 5;
int b = a;  // b에 a의 값(5)이 복사됨

b = 10;     // b만 10으로 변경

Debug.Log(a);  // 5 출력 (a는 변경되지 않음)
Debug.Log(b);  // 10 출력

Unity에서 값 형식

  • Vector3 (구조체(struct))
  • int, float, bool 등 기본 타입(type)
  • 구조체(struct)
Vector3 position1 = new Vector3(1, 2, 3);
Vector3 position2 = position1;  // 값이 복사됨

position2.x = 10;  // position2만 변경됨
// position1은 여전히 (1, 2, 3)

참조 형식 (Reference Type)

참조 형식은 Heap에 저장되며, 메모리(memory) 주소(참조)를 통해 접근하는 방식입니다.

참조 형식의 특징

  • 메모리(memory) 주소를 저장
  • 변수(variable)에 할당하면 같은 메모리(memory) 주소를 참조
  • 한 변수(variable)를 변경하면 다른 변수(variable)도 영향받음

참조 형식 예시

int[] myArray = { 1, 2 };
int[] myArray2 = myArray;  // 같은 메모리 주소를 참조

myArray2[1] = 7;  // myArray2를 변경

Debug.Log(myArray[1]);   // 7 출력 (myArray도 변경됨!)
Debug.Log(myArray2[1]);  // 7 출력

이유: 두 배열(array)이 같은 메모리(memory) 주소를 바라보고 있기 때문입니다.

Unity에서 참조 형식

  • GameObject (클래스(class))
  • string
  • 배열 (int[], string[])
  • 리스트 (List<T>)
  • 클래스(class)
GameObject obj1 = new GameObject("Player");
GameObject obj2 = obj1;  // 같은 객체를 참조

obj2.name = "Enemy";  // obj2의 이름 변경
// obj1.name도 "Enemy"로 변경됨!

new 키워드의 차이

값 형식에서의 new

Vector3 pos = new Vector3(1, 2, 3);
  • Stack에 값을 생성
  • 단순히 초기값을 설정하는 역할

참조 형식에서의 new

GameObject obj = new GameObject();
  • Heap에 객체(object)를 생성
  • 메모리(memory) 할당과 초기화를 수행

값 형식 vs 참조 형식 비교

특징 값 형식 (Value Type) 참조 형식 (Reference Type)
저장 위치 Stack Heap
저장 내용 값 자체 메모리(memory) 주소 (참조)
복사 방식 값 복사 참조 복사
변경 영향 독립적 공유됨
예시 int, Vector3 GameObject, string[]

실전 활용 예시

값 형식 활용

// 플레이어 위치 저장
Vector3 playerPos = new Vector3(0, 0, 0);
Vector3 savedPos = playerPos;  // 값 복사

playerPos.x = 10;  // playerPos만 변경
// savedPos는 여전히 (0, 0, 0)

참조 형식 활용

// 여러 스크립트가 같은 리스트 공유
List<int> scores = new List<int>() { 100, 200 };
List<int> highScores = scores;  // 같은 리스트 참조

highScores.Add(300);  // highScores에 추가
// scores에도 300이 추가됨!

주의사항

  1. 참조 형식은 메모리(memory) 주소를 공유하므로, 한 곳에서 변경하면 다른 곳도 영향받음
  2. 값 형식은 값 자체를 복사하므로, 각각 독립적으로 동작
  3. Unity에서 GameObject는 참조 형식이므로 주의해서 사용

← 목차로 돌아가기