기본을 간과하지 마세요: C#에서 Type 이해하기

발행: (2026년 2월 2일 오후 04:31 GMT+9)
13 분 소요
원문: Dev.to

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

  • 원시 타입은 값 타입의 하위 집합입니다.
  • 기본값을 가집니다 (int0, boolfalse 등).
  • 빠르고 효율적입니다.
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
}
  • structenum은 사용자 정의 값 형식을 만들 수 있는 유일한 방법입니다.
  • 값 형식은 스택(또는 객체 내부에 인라인) 에 저장되며, 참조 형식(클래스)과 동작이 다릅니다.
  • structenum은 다른 타입을 상속할 수 없으며, 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#에서 가장 중요한 구분 중 하나는 데이터가 어디에 저장되는가 입니다:

AspectValue TypesReference Types
Location스택(또는 다른 객체 내부에 인라인)힙(가비지 컬렉터가 관리)
Assignment실제 데이터를 복사참조(포인터)를 복사
Default value0으로 초기화(0, false 등)null
Nullability래핑하지 않으면 null 불가(int?)null 가능
InheritanceSystem.ValueType(sealed) 상속System.Object 상속

이러한 차이를 이해하면 보다 효율적이고 예측 가능하며 버그 없는 C# 코드를 작성할 수 있습니다.

Source:

값 형식과 참조 형식의 차이점

값 형식과 참조 형식의 주요 차이점은 메모리에서 저장되는 방식과 위치입니다.

값 형식 – 스택에 저장

값 형식은 보통 빠르고 단순한 메모리 영역인 스택에 저장됩니다. 값 형식 변수를 만들면 데이터가 바로 그 변수 안에 존재합니다.

Value type memory layout

예시

int number = 5;
int age    = 20;

각 변수는 값을 직접 보유합니다.

참조 형식 – 참조와 객체 위치

참조 형식은 실제 객체 데이터에 저장하지만, 참조(객체를 가리키는 변수)는 여러 위치에 저장될 수 있습니다:

참조가 선언된 위치참조가 저장되는 위치
메서드 내부의 로컬 변수스택
클래스/구조체의 필드포함 객체 내부(보통 힙)
static 필드특수 정적 메모리 영역

참조가 어디에 저장되든, 항상 힙에 있는 객체 데이터를 가리킵니다.

Reference type memory layout 1

Reference type memory layout 2

예시

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)의 자체 복사본을 가집니다

Value type copy illustration

레퍼런스 타입 복사

Person p1 = new Person();
Person p2 = p1; // p2는 p1과 같은 객체를 가리킵니다

Reference type copy illustration

p1p2는 메모리에서 같은 객체를 참조합니다. 어느 변수로 객체를 변경하든 다른 변수로 접근할 때 그 변경이 반영됩니다.

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# 코드를 작성할 수 있습니다. 즐거운 코딩 되세요!

Back to Blog

관련 글

더 보기 »

연산자

Java에서 연산자란 무엇인가요? 연산자는 변수와 값에 대한 연산을 수행하는 기호입니다. Java에서 연산자의 종류 - Arithmetic Operators - Assignment Operators …