C#

값 타입 vs 참조 타입 – 구조체와 클래스, 뭐가 다른데?

Juan_ 2025. 6. 5. 22:17
728x90

value type vs reference type – 구조체랑 클래스, 뭐가 다른데?

개발하다 보면 어느 순간 마주친다.

"이거 struct로 만들까? class로 할까?"

나도 그랬다.

처음엔 뭐든 다 class로 만들었다.

왜냐? struct는 잘 모르겠고, 그냥 new만 치면 class가 자동으로 뜨니까…

근데 프로젝트가 커지고 퍼포먼스를 고민하기 시작하면, 진지하게 이 차이를 알아야 할 때가 온다.

오늘은 이 차이를 눈에 쏙 들어오게 정리해보자.


문제 상황: "분명 바꿨는데 값이 왜 안 바뀌지?"


struct PointStruct
{
    public int X;
    public int Y;
}

class PointClass
{
    public int X;
    public int Y;
}

var ps1 = new PointStruct { X = 1, Y = 2 };
var ps2 = ps1;
ps2.X = 99;

Console.WriteLine(ps1.X); // 결과: 1

var pc1 = new PointClass { X = 1, Y = 2 };
var pc2 = pc1;
pc2.X = 99;

Console.WriteLine(pc1.X); // 결과: 99

겉보기엔 다 비슷한데, struct는 안 바뀌고 class는 바뀌었다.

이유는 간단하다. 값 타입은 복사, 참조 타입은 주소 공유이기 때문이다.


value type – 복사해서 넘긴다

값 타입은 데이터를 그대로 복사해서 넘긴다. 함수 안에서 바꿔도 원본은 안 바뀐다.

  • 스택(stack)에 저장됨
  • 복사해서 전달되기 때문에 안전함
  • 작고 단순한 데이터에 적합

대표적인 예:

  • int, double, bool
  • DateTime, TimeSpan
  • 사용자 정의 struct

struct Score
{
    public int Math;
    public int English;
}

값 타입은 "독립적"이다.

누가 내 복사본을 바꿔도 나는 그대로다.


reference type – 주소를 넘긴다

참조 타입은 데이터를 복사하지 않는다.

주소(참조)를 넘기기 때문에 함수 안에서 바꾸면 원본도 같이 바뀐다.

  • 힙(heap)에 저장됨
  • 참조만 전달되므로 메모리 사용은 효율적
  • 구조가 크거나 상태를 공유해야 할 때 적합

대표적인 예:

  • string, object
  • List<T>, 사용자 정의 class

class User
{
    public string Name;
    public int Age;
}

참조 타입은 "공유되는 객체"다.

내가 바꾸면 남도 바뀐다.


실무 예시: 상태 공유 or 복사?


void UpdateUser(User u)
{
    u.Name = "홍길동";
}

void UpdateScore(Score s)
{
    s.Math = 100;
}

var user = new User { Name = "철수", Age = 30 };
UpdateUser(user);
Console.WriteLine(user.Name); // 홍길동

var score = new Score { Math = 80, English = 90 };
UpdateScore(score);
Console.WriteLine(score.Math); // 80 ← 안 바뀜

✔ class는 참조가 넘어가서 원본이 바뀜
✔ struct는 복사라서 원본은 그대로


언제 struct를 써야 할까?

  • 크기가 작고, 필드가 몇 개 안 될 때
  • 상태 변경 없이 읽기 위주일 때
  • 수천 개씩 반복해서 만들어야 할 때 (GC 부담 줄이기)
  • 불변(immutable) 데이터일 때

예: 좌표, 색상, 사이즈, 시간


public readonly struct Color
{
    public byte R { get; }
    public byte G { get; }
    public byte B { get; }

    public Color(byte r, byte g, byte b)
    {
        R = r;
        G = g;
        B = b;
    }
}

언제 class가 필요할까?

  • 필드가 많거나 상태가 복잡할 때
  • 변경이 자주 일어날 때
  • 다른 클래스와 연결되어야 할 때 (참조 공유)
  • 상속이 필요할 때

예: 사용자, 세션, 주문서, UI 모델 등


class Session
{
    public string UserId;
    public DateTime LoginTime;
    public bool IsExpired;
}

struct 썼다가 낭패 보는 경우

  • 16바이트 이상 구조체 (복사 성능 저하)
  • 자주 복사되는 상황인데 struct로 작성함
  • 내부 상태를 변경해야 하는데 struct로 만들어버림
  • LINQ, EF 등 참조 기반 라이브러리에서 예상치 못한 동작 발생

언제 어떤 걸 써야 할까?

구분 value type (struct) reference type (class)
메모리 위치 스택
전달 방식 값 복사 참조 공유
GC 영향 없음 있음
상속 가능? 불가 가능
크기 제한 작은 데이터에 적합 제한 없음
공유 필요 불필요 필요할 수 있음
추천 예시 좌표, 시간, 색상 사용자, DB 모델, UI 객체

마무리하며

struct와 class는 단순히 문법이 다른 게 아니라, 설계 방식 자체가 다르다.

  • "독립적이고 작고, 빠르게 복사될 값" → struct
  • "상태를 공유하거나, 복잡하고 유연한 구조" → class

단순하게 "성능이 struct가 더 좋다"가 아니다.

잘못 쓰면 오히려 성능이 떨어진다. 특히 큰 구조체는 복사 비용이 크다.

중요한 건 설계 의도에 맞게 선택하는 것.

그게 실무에서 진짜로 struct vs class를 구분할 줄 아는 개발자다.

728x90