기본을 간과하지 마세요: C#에서 Type 이해하기
I’m happy to translate the article for you, but I don’t see the article’s text in your message—only the source link. Could you please paste the content you’d like translated (or the specific sections you want)? Once I have the text, I’ll provide a Korean translation while preserving the original formatting, markdown, and code blocks.
소개
C#에서 타입을 이해하는 것은 가장 중요한 기본 중 하나입니다. 모든 타입은 어떤 것이든 궁극적으로 System.Object 라는 “최고 관리자” 타입과 연결됩니다. 이는 내부적으로 모든 타입이 몇 가지 공통된 특징을 공유한다는 의미입니다.
Example
// This class automatically inherits from System.Object
class Music { }
// This is the same as above, just written out
class Opera : System.Object { }
무엇을 만들든, 모든 것은 System.Object에서 시작합니다. 이를 통해 모든 객체는 ToString() 및 GetHashCode()와 같은 유용한 메서드를 사용할 수 있습니다.
C#의 타입: 기본
C#에서 타입은 두 가지 주요 카테고리로 구분됩니다:
- 값 타입
- 참조 타입
또한 프리미티브 타입이라는 특별한 그룹이 있는데, 이는 가장 기본적인 내장 타입입니다.
하나씩 살펴보겠습니다!
원시 타입
원시 타입은 C#에 내장된 가장 단순한 타입들입니다. 컴파일러가 사용하기 쉽고 .NET 프레임워크의 타입에 직접 매핑됩니다.
예시: int, double, bool, char, byte, short, long, float, decimal
- 원시 타입은 값 타입의 하위 집합입니다.
- 기본값을 가집니다 (
int는0,bool은false등). - 빠르고 효율적입니다.
int count = 5; // int는 원시 타입입니다
bool isOn = true; // bool은 원시 타입입니다
Source: …
값 형식
값 형식은 실제 데이터를 보유합니다. 이들은 스택이라고 하는 빠른 접근 영역에 저장됩니다. 값 형식을 다른 변수에 할당하면 값이 복사됩니다.
예시: 모든 기본 형식, struct, enum
- 값 형식은 값을 항상 가지고 있습니다. 값을 설정하지 않아도 기본값이 존재합니다.
null이 될 수 없습니다(nullable 형식을 사용하지 않는 한).- 할당은 참조가 아니라 값을 복사합니다.
모든 값 형식(struct, enum, 기본 형식)은 System.ValueType을 상속합니다.
int number = 10; // 값 형식, 설정하지 않으면 기본값은 0
int copy = number; // 값을 복사 (10)
값 형식이 sealed인 이유
- 레이아웃 불변성: 메모리 레이아웃이 고정되어 있어, 상속을 허용하면 크기와 구조가 예측 불가능해집니다.
- 성능: sealed 특성 덕분에 런타임이 저장 및 접근을 최적화할 수 있습니다.
- 단순성: 값 형식을 상속하면 할당, 박싱, 언박싱이 복잡해집니다.
다음 코드는 컴파일되지 않습니다:
struct BasePoint { public int X, Y; }
// 오류! sealed 타입은 상속할 수 없습니다
struct DerivedPoint : BasePoint { public int Z; }
값 형식을 기준 타입으로 사용해 참조 타입을 정의할 수도 없습니다:
struct BaseStruct { }
// 오류! 값 형식은 상속할 수 없습니다
class MyClass : BaseStruct { }
사용자 정의 값 형식 만들기
struct 사용
struct는 사용자가 정의하는 값 형식입니다. 아래는 간단한 2‑D 점 예시입니다:
public struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
Point a = new Point(1, 2);
Point b = a; // 값을 복사 (참조가 아님)
b.X = 10;
// a.X는 여전히 1, b.X는 10
enum 사용
모든 열거형은 추상 System.Enum 타입을 상속하며, System.Enum 자체는 System.ValueType을 상속합니다. enum도 만들 수 있는 또 다른 값 형식입니다:
public enum DayOfWeek
{
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
struct와enum은 사용자 정의 값 형식을 만들 수 있는 유일한 방법입니다.- 값 형식은 스택(또는 객체 내부에 인라인) 에 저장되며, 참조 형식(클래스)과 동작이 다릅니다.
struct나enum은 다른 타입을 상속할 수 없으며,System.ValueType외의 타입을 상속받을 수도 없습니다.
널러블 값 형식
때때로 값 형식이 null을 가질 수 있기를 원합니다(예: 값이 아직 설정되지 않은 경우). C#에서는 nullable 형식을 사용하여 이를 할 수 있습니다:
int? score = null; // 'score' can now be null
if (score == null)
{
Console.WriteLine("No score yet!");
}
Reference Types
Reference types는 데이터에 대한 참조(주소)를 저장합니다. 실제 데이터는 heap에 존재하며, 변수는 그 데이터를 가리키는 역할만 합니다. 참조 타입을 다른 변수에 할당하면 실제 데이터를 복사하는 것이 아니라 참조를 복사합니다.
예시: class, string, array, delegate, interface, object
- Reference types는
null이 될 수 있습니다(어떤 객체도 가리키지 않을 수 있음). - 할당되지 않은 상태에서 참조 타입을 사용하면
NullReferenceException이 발생합니다. - 할당은 데이터가 아니라 참조(주소)를 복사합니다.
string name; // 기본값은 null입니다
// 값을 할당하기 전에 'name'을 사용하면 오류가 발생합니다
// Console.WriteLine(name.Length); // NullReferenceException!
메모리 할당 방식: 값 형식 vs. 참조 형식
C#에서 가장 중요한 구분 중 하나는 데이터가 어디에 저장되는가 입니다:
| Aspect | Value Types | Reference Types |
|---|---|---|
| Location | 스택(또는 다른 객체 내부에 인라인) | 힙(가비지 컬렉터가 관리) |
| Assignment | 실제 데이터를 복사 | 참조(포인터)를 복사 |
| Default value | 0으로 초기화(0, false 등) | null |
| Nullability | 래핑하지 않으면 null 불가(int?) | null 가능 |
| Inheritance | System.ValueType(sealed) 상속 | System.Object 상속 |
이러한 차이를 이해하면 보다 효율적이고 예측 가능하며 버그 없는 C# 코드를 작성할 수 있습니다.
Source: …
값 형식과 참조 형식의 차이점
값 형식과 참조 형식의 주요 차이점은 메모리에서 저장되는 방식과 위치입니다.
값 형식 – 스택에 저장
값 형식은 보통 빠르고 단순한 메모리 영역인 스택에 저장됩니다. 값 형식 변수를 만들면 데이터가 바로 그 변수 안에 존재합니다.

예시
int number = 5;
int age = 20;
각 변수는 값을 직접 보유합니다.
참조 형식 – 참조와 객체 위치
참조 형식은 실제 객체 데이터를 힙에 저장하지만, 참조(객체를 가리키는 변수)는 여러 위치에 저장될 수 있습니다:
| 참조가 선언된 위치 | 참조가 저장되는 위치 |
|---|---|
| 메서드 내부의 로컬 변수 | 스택 |
| 클래스/구조체의 필드 | 포함 객체 내부(보통 힙) |
static 필드 | 특수 정적 메모리 영역 |
참조가 어디에 저장되든, 항상 힙에 있는 객체 데이터를 가리킵니다.


예시
class Pet { public string Name; }
class Person { public Pet pet; }
void Example()
{
Person p = new Person(); // 'p'는 로컬 변수(스택에 저장된 참조)
p.pet = new Pet(); // 'pet'은 필드(힙에 있는 Person 객체 내부에 저장된 참조)
}
p(Person객체에 대한 참조)는 로컬 변수이므로 스택에 존재합니다.Person객체 자체는 힙에 존재합니다.Person객체 안의pet필드는 또 다른 힙에 할당된 객체(Pet)를 가리키는 참조를 보유합니다.
무엇을 복사하면 어떻게 될까?
값 타입 복사
int a = 10;
int b = a; // b는 값(10)의 자체 복사본을 가집니다

레퍼런스 타입 복사
Person p1 = new Person();
Person p2 = p1; // p2는 p1과 같은 객체를 가리킵니다

p1과 p2는 메모리에서 같은 객체를 참조합니다. 어느 변수로 객체를 변경하든 다른 변수로 접근할 때 그 변경이 반영됩니다.
Summary
- Primitive types (
int,bool, etc.) are built‑in value types. → 원시 타입(int,bool등)은 내장 값 형식이다. - Value types hold the actual data and live on the stack. → 값 형식은 실제 데이터를 보유하고 스택에 존재한다.
- Reference types hold a reference (address). The reference may be stored on the stack, heap, or in a static area, but the object data always lives on the heap. → 참조 형식은 참조(주소)를 보유한다. 이 참조는 스택, 힙, 혹은 정적 영역에 저장될 수 있지만 객체 데이터는 항상 힙에 존재한다.
- Assigning a value type copies the data; assigning a reference type copies the address. → 값 형식을 할당하면 데이터를 복사하고, 참조 형식을 할당하면 주소를 복사한다.
- All types in C# ultimately derive from
System.Object. → C#의 모든 형식은 궁극적으로System.Object에서 파생된다.
초보자를 위한 추가 팁
NullReferenceException은 아직 인스턴스화되지 않은 참조 형식을 사용하려고 했다는 의미입니다.null이 될 수 있는 값 형식이 필요할 때는 nullable 값 형식(int?,double?, …)을 사용하세요.- 값 형식을 메서드에 전달하면 그 값이 복사되고, 참조 형식을 전달하면 참조가 복사됩니다.
이 기본 사항을 이해하면 더 안전하고 효율적인 C# 코드를 작성할 수 있습니다. 즐거운 코딩 되세요!