[Swift] Class vs Struct 언제 사용할까?

ClassStrcutiosSwift
avatar
2025.03.17
·
9 min read

Swift에서는 데이터를 저장하고 조작할 때 Class(클래스)와 Struct(구조체)를 사용할 수 있다. 둘은 비슷하면서도 중요한 차이점을 가지고 있기에, 코드의 가독성과 성능을 위해 잘 선택해서 사용해야 한다. 이번 글에서는 Class와 Struct의 차이점과 각각을 언제 사용해야 하는지를 정리해본다.

Class와 Struct의 주요 차이점

특성

Class

Struct

메모리 할당

Heap (참조 타입)

Stack (값 타입)

복사 방식

참조 복사 (Reference)

값 복사 (Copy)

상속

가능

불가능

mutating 키워드

불필요

필요

참조 카운팅 (ARC)

사용함

사용하지 않음

Equatable 자동 구현

직접 구현

가능

가장 큰 차이점은 class는 참조 타입(Reference Type)이고, struct는 값 타입(Value Type)이라는 것이다.

Class와 Struct의 동작 방식

Class

person1과 person2가 같은 인스턴스를 참조하므로, 하나를 변경하면 다른 하나도 영향을 받는다.

class Person {
    var name: String
    init(name: String) { self.name = name }
}

var person1 = Person(name: "춘장")
var person2 = person1
person2.name = "메주"

print(person1.name) // "메주"
print(person2.name) // "메주"

Struct

값이 복사되므로 person1과 person2는 서로 영향을 주지 않는다.

struct Person {
    var name: String
}

var person1 = Person(name: "춘장")
var person2 = person1
person2.name = "감태"

print(person1.name) // "춘장"
print(person2.name) // "감태"

Class? Struct? 언제 사용할까?

Class

  • 객체 간 데이터 공유가 필요할 때

    • 여러 객체가 같은 데이터를 공유하고 변경해야 하는 경우

    • 예를 들어, 네트워크 요청을 처리하는 URLSession 인스턴스나, 앱의 전역 설정을 관리하는 UserDefaults 객체처럼 여러 부분에서 동일한 상태를 유지해야 할 때

  • 상속이 필요할 때

    • Class는 Struct와 달리 상속이 가능하므로, 공통된 기능을 가진 객체들을 계층적으로 설계할 수 있음

    • 예를 들어, UIKit의 UIView, UIViewController는 공통적인 속성과 메서드를 공유하는 상속 구조를 가짐

  • Identity(고유성)가 중요한 경우

    • 값이 같더라도 동일한 객체인지 구분해야 하는 경우

    • 예를 들어, 앱 내에서 사용자의 로그인 세션을 관리할 때, 같은 사용자 정보라도 서로 다른 인스턴스로 존재할 필요 없이 하나의 객체로 공유되어야 함

  • ARC(자동 메모리 관리)가 필요한 경우

    • 객체의 라이프사이클을 관리할 때 (네트워크 세션, 데이터 관리 객체 등)

    • Class는 자동 참조 카운팅(ARC)을 통해 객체가 더 이상 필요하지 않을 때 메모리를 자동 해제함

  • 여러 개의 인스턴스를 참조해야 하는 경우

    • 같은 객체를 여러 곳에서 참조해야 할 때 Class가 유리함

    • 예를 들어, 싱글톤 패턴을 사용하는 객체들은 앱 전역에서 동일한 인스턴스를 유지해야 하므로 Class로 구현

Struct

  • 값을 복사하여 사용하는 것이 적절한 경우

    • Swift의 기본 타입(Int, Double, String, Array, Dictionary 등)이 Struct인 이유와 동일하게, 값 타입은 복사되어 전달되므로 원본 데이터를 변경하지 않고도 안전하게 사용 가능

    • 예를 들어, IntString을 함수에 전달할 때 원본 값이 변경되지 않으며, ArrayDictionary도 Struct이므로 값이 변경될 때마다 새로운 복사본이 생성됨

    • 이는 데이터 변경이 독립적으로 이루어지도록 보장하는 중요한 원칙임

  • 객체 간 공유가 필요하지 않은 경우

    • Strcut는 값 타입이므로, 하나의 인스턴스가 변경되더라도 다른 인스턴스에 영향을 주지 않음

    • 예를 들어, CGPoint, CGRect와 같은 UI 요소는 독립적으로 사용되며, 참조 공유가 필요하지 않기 때문에 Strcut로 구현됨

    • 이러한 요소들이 값 타입으로 동작하면, UI가 변경될 때 불필요한 복잡성이 줄어들고, 예기치 않은 부작용을 방지할 수 있다.

  • 스레드 안정성이 필요한 경우

    • Struct는 값 복사가 이루어지므로 멀티스레드 환경에서도 안전하게 사용 가능

    • 예를 들어, 여러 스레드에서 동일한 데이터를 동시에 읽고 수정해야 하는 경우, Struct를 사용하면 각 스레드가 독립적인 복사본을 가지므로 데이터 충돌(Race Condition)이 발생하지 않음

    • 반면 Class는 같은 객체를 참조하므로, 동기화 작업을 추가적으로 고려해야 함

  • 불변성을 유지해야 하는 경우

    • Struct는 값 타입이므로, 인스턴스가 변경될 때마다 새로운 복사본이 생성되며 원본 데이터는 변경되지 않음

    • 예를 들어, SwiftUI의 View는 Struct로 구현되어 있으며, 상태가 변경될 때마다 새로운 View가 생성되는 방식으로 동작함

    • 이는 UI 업데이트를 단순화하고, Side Effect 없이 상태 변화를 쉽게 추적할 수 있도록 도움

  • 값을 비교하는 것이 중요한 경우

    • Struct는 값 자체를 저장하며, Equatable 프로토콜을 자동으로 채택할 수 있어 쉽게 비교 가능

    • 예를 들어, 두 개의 CGRect 또는 Data 값을 비교할 때, 같은 값을 가지면 같은 것으로 간주되므로 간단한 == 연산으로 비교할 수 있음

Apple의 Swift 공식 문서에서도 기본적으로 Struct를 사용하고, 필요할 때만 Class를 사용하라고 권장한다. Struct는 값 타입이므로 데이터 변경이 독립적으로 이루어져 예측 가능성이 높고, 메모리 관리가 간단하기 때문이다. 반면 Class는 참조 타입으로 객체 공유가 필요하거나 상속이 필요한 경우에만 사용하는 것이 적절하다.







- 컬렉션 아티클