핵심 개념 정리
가장 근본적인 차이는 "어떤 타입인가?" 입니다.
- 클래스 (Class)는 참조 타입 (Reference Type)입니다.
- 구조체 (Struct)는 값 타입 (Value Type)입니다.
이 차이점 때문에 아래와 같은 여러 파생적인 특징들이 나타납니다.
구분 항목 | 클래스 (Class) | 구조체 (Struct) |
타입 종류 | 참조 타입 (Reference Type) | 값 타입 (Value Type) |
메모리 할당 | 힙 (Heap) 영역에 할당 | 스택 (Stack) 영역에 할당 |
데이터 전달 | 주소값(참조)을 복사 | 데이터 전체를 복사 |
상속 | 다른 클래스 상속 가능 | 상속 불가능 (인터페이스 구현은 가능) |
Null 할당 | null 할당 가능 | null 할당 불가능 (Nullable<T> 제외) |
생성자 | 매개변수 없는 기본 생성자 자동 지원 | C# 10부터 매개변수 없는 생성자 선언 가능 |
주요 용도 | 복잡한 데이터와 행위를 갖는 객체 | 좌표, 색상 등 작고 단순한 데이터 덩어리 |
값 타입 vs 참조 타입 (메모리 할당 & 데이터 전달)
- 구조체 (값 타입) : 변수가 데이터 그 자체를 가집니다. 변수가 선언된 곳(주로 스택)에 메모리가 할당되고 모든 데이터가 그 안에 저장됩니다. 다른 변수에 할당하면, 데이터 전체가 '새로운 공간에 복사' 됩니다.
public struct MyPoint { public int X; } MyPoint p1 = new MyPoint { X = 10 }; MyPoint p2 = p1; // p1의 모든 데이터를 복사해서 p2를 새로 만듦 p2.X = 20; // p1.X는 여전히 10, p2.X는 20 (서로 다른 데이터) Console.WriteLine($"p1.X : {p1.X}, p2.X : {p2.X}");
- 클래스 (참조 타입) : 변수는 데이터가 실제 저장된 힙(Heap) 메모리의 주소(참조)만 가집니다. 다른 변수에 할당하면 이 '주소값만 복사' 됩니다. 결국, 여러 변수가 힙에 있는 '하나의 동일한 데이터'를 가리키게 됩니다.
public class MyObject { public int Value; } MyObject o1 = new MyObject { Value = 10 }; MyObject o2 = o1; // o1이 가리키는 객체의 '주소'를 복사 o2.Value = 20; // o1과 o2는 같은 객체를 가리키므로, 둘 다 20으로 변경됨 Console.WriteLine($"o1.Value : {o1.Value}, o2.Value : {o2.Value}");
상속 (Inheritance)
- 클래스 : 객체 지향 프로그래밍(OOP)의 핵심 기능인 상속을 완벽하게 지원합니다. 부모 클래스의 기능을 물려받아 확장하거나 재정의(override)할 수 있습니다.
- 구조체 : 상속이 불가능합니다. 어떤 클래스나 구조체도 상속받을 수 없습니다. 다만, 인터페이스(Interface)는 구현할 수 있어 특정 규격이나 기능을 갖도록 강제할 수는 있습니다.
게임 개발 관점
- 구조체(Struct)를 사용해야 할 때:
- Vector3(위치), Quaternion(회전), Color(색상) 등 작고 단순하며 값 자체로 의미 있는 데이터를 다룰 때 사용합니다.
- 이러한 데이터들은 게임 루프 내에서 수시로 생성되고, 계산되고, 파괴됩니다. 만약 이것들을 클래스로 만든다면, 매번 힙(Heap) 메모리에 할당되고 해제될 때마다 가비지 컬렉터(GC)가 동작하게 됩니다. 이 과정이 누적되면 게임 중간에 렉이 걸리는 현상, 즉 GC 스파이크(Spike)를 유발하여 심각한 성능 저하의 원인이 됩니다.
- 구조체를 사용하면 스택(Stack)에 빠르고 가볍게 할당/해제되므로 GC 부담이 없어 성능에 매우 유리합니다.
- 클래스(Class)를 사용해야 할 때:
- Player, Monster, Item 등 게임 세계에서 고유한 정체성(Identity)을 가지고, 복잡한 데이터와 행동(메서드)을 가지는 객체를 표현할 때 사용합니다.
- 이 객체들은 하나의 실체로서 존재하며, 여러 다른 코드에서 이 객체를 참조하여 상태를 변경하거나 상호작용해야 합니다. 이때는 참조를 전달하는 클래스가 적합합니다.
결론적으로, "재사용되는 복잡한 객체는 클래스로, 일회성으로 자주 쓰이는 작은 데이터 묶음은 구조체로" 설계하는 것이 게임 클라이언트 성능 최적화의 중요한 원칙 중 하나입니다.
'CS > C#_C++' 카테고리의 다른 글
C++ 캐스팅 연산자 (0) | 2025.10.07 |
---|---|
C++ STL(Standard Template Library) (0) | 2025.10.04 |
C# 박싱(Boxing) 언박싱(Unboxing) (0) | 2025.10.03 |
C# GC(Garbage Collection) (0) | 2025.10.02 |
(공통)C++과 C# 언어 특성 비교 (0) | 2025.10.02 |