[Swift] struct, class, enum 비교

김창규·2023년 3월 22일
0

Swift

목록 보기
3/3

* 해당 글은 개인 공부자료이므로 오류가 있을 수 있습니다.

[개요]

Swift에서는 struct, class, enum 세 가지 타입을 제공합니다.
이 타입들의 공통점차이점을 알아보고 언제 사용해야하는지 알아보겠습니다.

[struct, class, enum의 공통점]

  • 프로퍼티메서드 정의 가능
    • 저장 프로퍼티(Stored Property)는 ClassStruct만 가질 수 있음
    • 연산 프로퍼티(Computed Property)는 Class,Struct,Enum 모두 가질 수 있음
  • 서브스크립트 정의 가능
  • 이니셜라이저 정의 가능
  • 익스텐션 가능
  • dot(.)을 사용하여 하위 프로퍼티 접근 가능
  • 프로토콜 준수 가능

[struct, class, enum의 차이점]

클래스(class)

  • 참조 타입 (Reference Type)
  • 힙(Heap) 메모리에 생성
  • 단일 상속
  • 객체를 전달
  • deinit으로 인스턴스 메모리 할당 해제
  • ARC(Automatic Reference Counting)로 메모리 관리

구조체(struct)

  • 값 타입 (Value Type)
  • 스택(Stack) 메모리에 생성
  • 상속 불가
  • 값을 전달
  • 프로퍼티 값 변경 불가능

열거형(enum)

  • 값 타입 (Value Type)
  • 스택(Stack) 메모리에 생성
  • 상속 불가
  • 공통된 타입의 그룹화

[값 타입과 참조 타입]

값 타입

struct PersonStruct {
	var name: String
    var age: Int
    
    // init() 생략 가능
    
    // 프로퍼티 값 변경 불가능하지만 mutating 사용하여 변경 가능
    mutating func increaseAge() {
    	age += 1
    }
}

PersonStruct이름의 구조체를 선언하였습니다.
메모리에는 어떻게 할당되는지 알아보겠습니다.

선언되는 PersonStruct는 위와 같이 데이터 영역에 저장되게 됩니다. 아직 선언만 된 상태 이기 때문에 스택영역에 할당되지 않았습니다. 이제 저장된 데이터를 인스턴스화 시켜 스택영역 메모리에 할당해보겠습니다.

var personStruct1 = PersonStruct(name:"henry", age: 20)

var personStruct2 = personStruct1

personStruct1 이름의 변수에 PersonStruct를 생성해 주고 personStruct1personStruct2에 복사를 했습니다. 메모리에서는 아래와 같이 할당되게 됩니다.

personStruct1personStruct2는 각각 별개로 스택영역에 인스턴스가 생성됩니다. 값참조 이기 때문에 복사를 하게되면 서로 영향을 주지 않는 별개의 값이 스택영역에 저장되게 됩니다.

personStruct1.increaseAge() // age 1증가
8
print(PersonStruct1.age) // 21
print(PersonStruct2.age) // 20

personStruct1age를 증가시키면 스택영역의 personStruct1age가 증가되고, personStruct2age는 변화가 없습니다.

다음은 참조타입에 대해 알아보겠습니다.


참조타입

class PersonClass {
    var name: String
    var age: Int
    
    // init()직접 구현해야됨
    init(name:String, age: Int) {
        self.name = name
        self.age = age
    }
    
    // 프로퍼티 값 변경 가능
    func increaseAge() {
        age += 1
    }
}

위 코드와 같이 PersonClass이름을 가진 클래스를 선언했습니다. nameage의 프로퍼티를 가지고 increateAge()라는 age를 1씩 증가시키는 함수를 가지고 있습니다.
이렇게 선언을 하게 되면 메모리에는 무슨일이 일어날까요?

앞서 값 타입은 스택영역에, 참조타입은 힙영역에 저장된다고했습니다. 하지만 현재는 선언만 한 상태라 클래스는 힙과 스택영역에 존재하지 않고 데이터영역에 PersonClass라는 클래스 데이터가 저장되어있습니다. 이제 이 클래스를 생성해보면 다음과 같습니다.

var personClass1 = PersonClass(name: "henry", age: 20)
var personClass2 = personClass1

personClass1.increaseAge() // age 1 증가

print(personClass1.age) //21
print(personClass2.age) //21

먼저 personClass1이름의 변수에 PersonClass를 생성하고, personClass2personClass1복사를 했습니다. personClass1age를 1 증가 시켰는데 personClass2age 도 1이 증가된 것을 볼 수있습니다. 그 이유는 클래스가 참조타입이기 때문입니다. 이게 어떻게 된건지 메모리 구조를 통해 알아보겠습니다.

PersonClass는 참조타입 클래스이기 때문에 생성을하면, 힙영역에 실제 인스턴스 데이터를 저장하게되고, 스택영역의 personClass1은 힙영역의 데이터를 가르키는 주소값을 갖게됩니다. 따라서 personClass2도 같은 메모리 주소를 가르키는 값을 할당받게 된거죠.
포인트는 "참조타입은 실제 값이 아닌 값을 가르키는 주소값" 입니다.

[사용 용도]

  • 구조체(struct)

    • 간단한 값 타입을 다루거나 데이터를 복사해서 사용할 때
  • 클래스(class)

    • 복잡한 객체를 다루거나 공유할 때
    • 상속이 필요할 때
    • objective-C 와 상호 운용성 필요할 때
profile
iOS 공부

0개의 댓글