본문 바로가기
iOS

[Swift] Struct(구조체)? Class(클래스)?

by GODOLs 2024. 6. 15.

목차

    구조체랑 클래스는 생긴건 비슷한데...

    Swift에서 가장 많이 보는 Struct와 Class는 프로그래머가 데이터를 용도에 맞게 묶어 표현하고자 할 때 유용합니다.
    Struct와 Class는 프로퍼티와 메서드를 사용하여 구조화된 데이터와 기능을 가질 수 있습니다다.
    하나의 새로운 사용자 정의 데이터 타입을 만들어 주는 것입니다.

    Struct(구조체)란?

    우선 예시코드를 보겠습니다.

    struct MyInformation{
        var name: String
        var age : Int
    }

    이 Struct는 문자열인 name과, 정수형인 age를 저장 프로퍼티를 가지고 있습니다.

    구조체에서는 인스턴스가 생성되고 초기화된 후 프로퍼티 값에 접근하고 싶다면 '.'을 통해 접근할 수 있습니다.
    만약 구조체를 상수 let으로 선언하면 인스터스 내부의 프로퍼티 값을 바꿀 수 없고 (상수이기 때문에)
    변수 var로 선언하면 인스턴스 내부의 프로퍼티 값을 변경해줄 수 있습니다.

    var godolInfo: MyInformation = MyInformation(name: "godol" age: 21)
    godolInfo.age = 100
    godolInfo.name = "david"
    
    let davidInfo: MyInformation = MyInformation(name: "david" age: 21)
    godolInfo.age = 100 // 변경 불가! 오류!
    godolInfo.name = "godol" // 변경 불가!

    Class(클래스)란?

    Struct와 동일하게 예시 코드를 보겠습니다.

    struct Person{
        var height: Float = 0.0
        var weight : Float = 0.0
    }

    이 Class는 실수형인 height와, weight 를 저장 프로퍼티를 가지고 있습니다.

    클래스를 정의한 후, 인스턴스를 생성하고 초기화하고자 할 때는 기본적인 생성자(Initializer)를 사용합니다.
    하지만 Person 클래스의 기본값 0.0이 지정되어있기 때문에 따로 초깃값을 전달해주지 않아도 됩니다.

    구조체와 동일하게 인스턴스가 생성되고 초기화된 후 프로퍼티 값에 접근하고 싶다면 '.'을 통해 접근할 수 있습니다.
    다만 차이점이 있다면 구조체와 다르게 클래스의 인스턴스는 참조 타입이므로 클래스의 인스턴스를 상수 let으로 선언해도 내부 프로퍼티 값을 변경할 수 있습니다.

    var godol: Person = Person()
    godol.height = 183.5
    godol.weight = 78.2
    
    let david: Person = Person()
    david.height = 183.5
    david.weight = 78.2

    클래스 인스턴스의 소멸

    클래스의 인스턴스는 참조 타입이므로 더는 참조할 필요가 없을 때 메모리에서 해제됩니다.
    이 과정을 소멸이라고 하는데 소멸 직전 deinit이라는 메서드가 호출됩니다. (DeInitialized의 약어다.)

    struct Person{
        var height: Float = 0.0
        var weight : Float = 0.0
    
        deinit{
            print("Person 클래스의 인스턴스가 소멸됩니다.")
        }
    }
    
    var godol: Person = Person()
    godol = nil // "Person 클래스의 인스턴스가 소멸됩니다."

    구조체와 클래스의 차이

    같은점

    • 값을 저장하기 위해 프로퍼티를 정의할 수 있습니다.
    • 기능 실행을 위해 메서드를 정의할 수 있습니다.
    • 서브스크립트 문법을 통해 구조체 또는 클래스가 갖는 값(프로퍼티)에 접근하도록 서브스크립트를 정의할 수 있습니다.
    • 초기화 상태를 지정하기 위해 생성자(Initializer)를 정의 할 수 있습니다.
    • 초기구현과 더불어 새로운 기능 추가를 위해 Extension을 통해 확장할 수 있습니다.
    • 특정 기능을 실행하기 위해 특정 프로토콜을 준수할 수 있습니다.다른점
    • 구조체는 상속할 수 없습니다.
    • 타입캐스팅은 클래스의 인스턴스에만 허용됩니다.
    • 디이니셜라이저(DeInitializer)는 클래스의 인스턴스에만 활용 할 수 있습니다.
    • 참조 횟수 계산 (Reference Counting)은 클래스의 인스턴스에만 적용 됩니다.

    값 타입? 참조 타입?

    구조체는 값 타입이고 클래스는 참조 타입입니다. 값 타입과 참조 타입의 가장 큰 차이는 '무엇이 전달되는가'입니다.
    ex) 어떤 함수의 전달인자로 값 타입의 값을 넘긴다면 전달될 값이 복사 되어 전달 하지만 참조 타입이 전달인자로 전달될 때는 값을 복사하지 않고 참조(포인터 주소)가 전달 됩니다.

    // 값 타입의 예: 구조체
    struct ValueTypeExample {
        var value: Int
    }
    
    func modifyValueType(valueType: ValueTypeExample) {
        var modifiedValueType = valueType
        modifiedValueType.value = 20
        print("Inside modifyValueType: \(modifiedValueType.value)") // 20
    }
    
    var valueTypeInstance = ValueTypeExample(value: 10)
    print("Before modifyValueType: \(valueTypeInstance.value)") // 10
    modifyValueType(valueType: valueTypeInstance)
    print("After modifyValueType: \(valueTypeInstance.value)") // 10
    
    // 참조 타입의 예: 클래스
    class ReferenceTypeExample {
        var value: Int
    
        init(value: Int) {
            self.value = value
        }
    }
    
    func modifyReferenceType(referenceType: ReferenceTypeExample) {
        referenceType.value = 20
        print("Inside modifyReferenceType: \(referenceType.value)") // 20
    }
    
    var referenceTypeInstance = ReferenceTypeExample(value: 10)
    print("Before modifyReferenceType: \(referenceTypeInstance.value)") // 10
    modifyReferenceType(referenceType: referenceTypeInstance)
    print("After modifyReferenceType: \(referenceTypeInstance.value)") // 20

    설명:

    • 값 타입의 예: ValueTypeExample이라는 구조체를 정의했습니다. 구조체는 값 타입이므로 함수에 전달될 때 복사됩니다.
    • 함수 modifyValueType에서 구조체의 값을 변경해도 원본 인스턴스는 변경되지 않습니다.
    • valueTypeInstance는 원래 값이 10이고, 함수 호출 후에도 값이 그대로 10입니다.
    • 참조 타입의 예: ReferenceTypeExample이라는 클래스를 정의했습니다. 클래스는 참조 타입이므로 함수에 전달될 때 참조(포인터 주소)가 전달됩니다. - 함수 modifyReferenceType에서 클래스의 값을 변경하면 원본 인스턴스의 값도 변경됩니다.
    • referenceTypeInstance는 원래 값이 10이고, 함수 호출 후에 값이 20으로 변경됩니다.

    식별 연산자

    클래스의 인스턴스끼리 참조가 같은지 확인할 때는 식별 연산자(Identity Operator)를 사용합니다.

    // 클래스 정의
    class ExampleClass {
        var value: Int
    
        init(value: Int) {
            self.value = value
        }
    }
    
    // 두 개의 클래스 인스턴스 생성
    let instanceA = ExampleClass(value: 10)
    let instanceB = ExampleClass(value: 10)
    
    // instanceA와 instanceB는 동일한 인스턴스가 아닙니다.
    if instanceA === instanceB {
        print("instanceA and instanceB refer to the same instance.")
    } else {
        print("instanceA and instanceB do not refer to the same instance.")
    }
    
    // instanceC는 instanceA를 참조합니다.
    let instanceC = instanceA
    
    // instanceA와 instanceC는 동일한 인스턴스입니다.
    if instanceA === instanceC {
        print("instanceA and instanceC refer to the same instance.")
    } else {
        print("instanceA and instanceC do not refer to the same instance.")
    }
    
    // instanceA와 instanceB는 다른 인스턴스를 참조하므로 식별 연산자는 false를 반환합니다.
    // instanceA와 instanceC는 동일한 인스턴스를 참조하므로 식별 연산자는 true를 반환합니다.

    결론

    Struct(구조체)와 Class(클래스)는 Swift에서 프로그래머가 데이터를 효과적으로 관리하고 기능을 구현하는 데 매우 유용한 도구입니다. 이 두 가지는 유사한 기능을 제공하지만, 중요한 차이점들이 있습니다.

    • 구조체는 값 타입으로, 주로 간단한 데이터 구조를 표현하는 데 사용됩니다. 함수에 전달될 때 복사되어 전달되므로 안전한 데이터 관리가 가능합니다. 상수로 선언된 구조체 인스턴스는 내부 프로퍼티 값을 변경할 수 없습니다.
    • 클래스는 참조 타입으로, 복잡한 데이터 구조와 상속 관계를 표현하는 데 사용됩니다. 함수에 전달될 때 참조(포인터 주소)가 전달되므로 동일한 인스턴스를 여러 곳에서 공유할 수 있습니다. 상수로 선언된 클래스 인스턴스도 내부 프로퍼티 값을 변경할 수 있습니다.

    또한, 클래스는 상속, 타입캐스팅, 디이니셜라이저, 참조 횟수 계산 등 고급 기능을 지원합니다. 이러한 차이점들을 이해하고 상황에 맞게 적절히 활용하는 것이 중요합니다.

    요약

    • 같은 점: 프로퍼티 정의, 메서드 정의, 서브스크립트 문법, 생성자 정의, 확장(Extension), 프로토콜 준수 가능.
    • 다른 점: 구조체는 상속 불가, 타입캐스팅 불가, 디이니셜라이저 사용 불가, 참조 횟수 계산 불가.
    • 값 타입과 참조 타입: 구조체는 값 타입으로 복사되어 전달, 클래스는 참조 타입으로 주소가 전달.
    • 식별 연산자: 클래스 인스턴스끼리 참조가 같은지 확인.

    이러한 이해를 바탕으로 Struct와 Class를 적절히 활용하면 Swift 프로그래밍에서 더 효율적이고 안전한 코드를 작성할 수 있습니다.


    출처: 야곰, ⌜스위프트 프로그래밍 3판⌟, 한빛미디어

    반응형