November 15, 2025 (5mo ago) — last updated December 7, 2025 (4mo ago)

클래스 vs 구조체: 언제 각각을 사용해야 할까

클래스와 구조체를 비교: 값 타입과 참조 타입을 언제 사용할지, 메모리와 성능이 어떻게 다른지, 더 나은 설계를 위한 실용적인 규칙을 알아보세요.

← Back to blog
Cover Image for 클래스 vs 구조체: 언제 각각을 사용해야 할까

클래스와 구조체를 비교: 값 타입과 참조 타입을 언제 사용할지, 메모리와 성능이 어떻게 다른지, 더 나은 설계를 위한 실용적인 규칙을 알아보세요.

Classes vs Structs: When to Use Each

Summary: Compare classes vs structs—value vs reference, memory, performance, and design guidance to choose the right type for efficient code.

Introduction

Deciding between classes and structs is less about syntax and more about semantics. The key question is whether you need value semantics (copying data) or reference semantics (shared identity). That difference affects memory use, performance, mutability, and architecture. This guide explains those trade-offs and gives practical rules for choosing the right type.

The core distinction: value vs reference semantics

프로그래머가 대형 화면에서 클래스와 구조체에 대한 코드 블록을 비교하고 있다.

When you strip away language syntax, classes versus structs is a conversation about value types versus reference types. Think of a struct like a photocopied notepad: you give someone your notes and they get their own copy. They can scribble on it without changing your original. That’s value semantics—safe, isolated copies. A class is like a shared document: you send a link and everyone edits the same live object. That’s reference semantics—shared identity and shared state.

Key differences at a glance

CharacteristicStructs (Value Types)Classes (Reference Types)
Data handling데이터는 전달될 때 복사됩니다참조(포인터)가 전달됩니다
Memory allocation종종 인라인 또는 스택에 저장됩니다힙에 할당됩니다
Lifecycle짧게 유지되는 일시적 복사본장기간 유지되는 공유 인스턴스
Identity데이터 동등성으로 정의됩니다데이터와 독립적인 고유한 정체성
Inheritance보통 상속 없음상속과 다형성 지원
Primary use case작고 자체 포함된 값동작을 가진 복잡한 엔티티

These principles have practical consequences for latency, memory usage, and correctness. Choosing deliberately will make your code more predictable and easier to maintain.

How memory allocation impacts performance

스택과 힙 메모리 할당의 차이를 보여주는 다이어그램.

The stack and the heap are where most of this decision’s performance effects come from.

The stack: fast and predictable

The stack is a LIFO memory region where function-local data is pushed and popped. Allocating on the stack is very cheap because it’s just pointer arithmetic. For small value types, allocation and deallocation are nearly free.

The heap: flexible but costlier

The heap lets objects outlive a single function call, but heap allocation is slower and may trigger garbage collection or manual deallocation. Reference types introduce an extra indirection: the stack holds a pointer to heap data. Repeated heap allocations increase GC pressure and can cause pauses in managed runtimes1.

C# example

// Value Type - lives inline (often on the stack)
public struct PointStruct {
    public int X;
    public int Y;
}

// Reference Type - object lives on the heap
public class PointClass {
    public int X;
    public int Y;
}

public void ProcessPoints() {
    PointStruct p1 = new PointStruct { X = 10, Y = 20 };
    PointClass p2 = new PointClass { X = 10, Y = 20 };
}

In tight loops, thousands of heap allocations for small objects can significantly increase GC activity; structs in arrays often achieve much better cache locality and lower GC pressure2.

How languages treat classes and structs

다양한 프로그래밍 언어의 코드 스니펫을 나란히 보여주는 분할 화면, 클래스와 구조체를 설명하고 있다.

Different languages emphasize different defaults. The best choice depends on language idioms as much as on raw performance.

C++: nearly identical keywords

In C++, struct and class are almost the same; the only technical difference is default access (public for struct, private for class). Use struct for plain-data aggregates and class for encapsulated types and complex behaviour3.

C#: a clear value/reference split

C# makes the distinction explicit: struct is a true value type, and class is a reference type. Use structs for small, immutable values (coordinates, colors) and classes for entities with identity and mutable shared state.

Swift: prefer value types

Swift encourages a value-first approach. Apple’s guidance and the Swift community favour struct by default and reserve class for cases that require reference semantics, such as shared mutable state or interaction with Objective-C APIs4.

Rust: ownership and safety

Rust uses struct plus an ownership and borrowing model to provide memory safety without a garbage collector. Behaviour is attached via impl blocks, and the compiler enforces ownership and borrowing rules at compile time, preventing many shared-state bugs before runtime5.

struct Player {
    username: String,
    level: u32,
    is_active: bool,
}

impl Player {
    fn level_up(&mut self) {
        self.level += 1;
    }
}

Rust’s approach gives you the performance of direct memory control with compile-time safety guarantees.

When to choose a struct for better performance

Choose a struct when the type is small, self-contained, and treated like a value rather than an identity. Typical candidates:

  • Geometric points (Point2D)
  • Color values (RGB/RGBA)
  • Small configuration payloads
  • Lightweight computation inputs

Benefits include fewer heap allocations, improved cache locality, and less GC pressure in managed runtimes. Improved cache locality can yield large speedups in data-heavy loops because memory access patterns become much more CPU-friendly2.

When to choose a class to model complex behaviour

Choose a class when an object has a stable identity, shared mutable state, or when you need inheritance or complex lifecycle management. Typical candidates:

  • User profiles or domain entities
  • Database or network connection objects
  • Services and managers that coordinate state

Classes are the foundation of many object-oriented patterns. Inheritance and polymorphism make it easier to model complex relationships and behaviours.

Decision checklist: struct vs class

ConsiderationUse struct (value)Use class (reference)
Identity데이터가 정체성이다객체는 고유한 정체성을 가진다
Mutability불변이거나 작고 격리된 상태공유되는 가변 상태
Behavior데이터에 묶인 단순한 로직복잡한 상호작용과 동작
Lifecycle수명이 짧고 로컬 범위수명이 길고 애플리케이션 전역
Sharing복사해도 안전함참조로 공유해야 함

Common questions

Can a struct have methods?

Yes. Modern languages like C#, Swift, and Rust allow structs to have methods, initializers, and protocol or interface conformance. The main difference is still how they’re copied and passed.

Are structs always faster?

No. Small structs often outperform heap-allocated objects, but large structs can become expensive to copy. Always measure: profile real workloads before making broad changes.

Do structs support inheritance?

Usually not. Structs rarely support inheritance, but many languages let structs implement interfaces or protocols, enabling flexible composition without deep inheritance chains.

Practical Q&A

Q: When should I refactor a class into a struct?

A: Refactor when the type is a small, immutable value without unique identity, and you want fewer heap allocations and clearer value semantics.

Q: How do I avoid GC pauses in managed languages?

A: Reduce short-lived heap allocations by preferring structs for small values, reusing objects, and using object pools; measure GC behavior under load1.

Q: What’s the easiest rule of thumb?

A: If the object represents “a value” use a struct; if it represents “a thing with identity” use a class.

Three concise Q&A sections

Q&A 1 — Performance trade-off

Q: Will switching to structs always improve speed? A: No. Use structs for small, frequently created values to reduce GC pressure and improve cache locality; avoid large structs that are expensive to copy.

Q&A 2 — Safety and correctness

Q: Do structs reduce bugs from shared state? A: Yes. Value semantics prevent accidental shared mutation, which reduces concurrency and state-related bugs when values are copied instead of shared.

Q&A 3 — Design and architecture

Q: When is a class a better model than a struct? A: Use a class when identity, long-lived lifecycle, or inheritance and polymorphism are required.


At Clean Code Guy, we help teams refactor for scalability and maintainability. Learn more at https://cleancodeguy.com.

1.
Microsoft Docs. “Garbage collection performance and tuning.” https://learn.microsoft.com/dotnet/standard/garbage-collection/
2.
Ulrich Drepper. “What Every Programmer Should Know About Memory.” https://people.freebsd.org/~lstewart/articles/cpumemory.pdf
3.
cppreference.com. “class vs struct.” https://en.cppreference.com/w/cpp/language/class
4.
Apple. “Structures and Classes” (Swift Programming Language). https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
5.
The Rust Programming Language. “Ownership.” https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html
← Back to blog
🙋🏻‍♂️

AI가 코드를 작성합니다.
당신이 그것을 지속시킵니다.

AI 가속 시대에 클린 코드는 단순히 좋은 관행이 아닙니다 — 확장되는 시스템과 자체 무게로 붕괴되는 코드베이스의 차이입니다.

클래스 vs 구조체: 언제 각각을 사용해야 할까 | Clean Code Guy