Swift) Class와 Struct의 차이점에 대해 설명하시오.

Class와 Struct 차이점

Class

  • 참조 타입(Reference Type)
  • 상속 가능
  • heap memory 영역에 할당 (속도가 느림)
  • 런타임에 직접 alloc하며 reference counting을 통해 dealloc이 필요
  • memory fragmentation 등의 overhead가 존재
  • NSData serialize 가능
  • Codable 사용 불가능
  • 런타임에 타입 캐스팅을 통해서 클래스 인스턴스에 따라 여러 동작이 가능
  • deinitializer 존재

Struct / Enum

  • 값 타입(Value Type)
  • 상속 불가능 (protocol은 사용 가능)
  • stack memory 영역에 할당 (속도가 빠름)
  • scope based lifetime: 컴파일타임에 compiler가 언제 메모리를 할당/해제할지 정확히 알고있음
  • data locality: CPU 캐시 히트율이 높음
  • NSData로 serialize 불가능
  • Codable 프로토콜을 이용하여 손쉬운 JSON <-> struct 변환 가능 (Swift 4 이상)
  • 항상 새로운 변수로 copy가 일어나기 때문에 multi-thread 환경에서 공유변수로 인해 문제를 일으킬 확률이 적음

참조 타입과 값 타입 비교

참조 타입(Reference Type)

  • 데이터를 전달할 때 값의 메모리 위치를 전달한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 클래스 생성
class ReferenceType {
var property = 1
}

// 클래스 인스턴스 생성
// 첫 번째 참조 생성
// 두 개 다 같은 것이니까 아무거나 사용하삼 ~
let firstClassReference : ReferenceType = ReferenceType()
// let firstClassReference = ReferenceType()

// 두 번째 참조 변수에 첫 번째 참조 할당
let secondClassReference = firstClassReference

print("first class reference property : \(firstClassReference.property)")
// ----- 출력값
// 1
print("second class reference property : \(secondClassReference.property)")
// ----- 출력값
// 1

// 두 번째 참조를 통해 인스턴스의 프로퍼티 값 변경
secondClassReference.property = 2

// 두 번째 클래스 참조는 첫 번째 클래스 인스턴스를 참조하기 때문에
// 두 번째 참조를 통해 인스턴스의 프로퍼티 값을 변경하면
// 첫 번째 클래스 인스턴스의 프로퍼티 값도 변경 됨

print("first class reference property : \(firstClassReference.property)")
// ----- 출력값
// 2
print("second class reference property : \(secondClassReference.property)")
// ----- 출력값
// 2

// 상수로 선언했어도 값이 바뀌는 이유는
// secondClassReference 자체를 변경한 것이 아닌
// secondClassReference가 바라보는 값을 변경하는 것이기 때문에 가능하다.

값 타입(Value Type)

  • 데이터를 전달할 때 값을 복사하여 전달한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 구조체 생성
struct ValueType {
var property = 1
}

// 첫 번째 구조체 인스턴스
let firstStructInstance = ValueType()

// 두 번재 구조체 인스턴스에 첫 번째 인스턴스 값 복사
let secondStructInstance = firstStructInstance

// 두번째 구조체 인스턴스 프로퍼티 값 수정
secondStructInstance.property = 2

// 두 번째 구조체 인스턴스는 첫 번째 구조체를 똑같이 복사한
// 별도의 인스턴스이기 때문에
// 두 번째 구조체 인스턴스의 프로퍼티 값을 변경해도
// 첫 번째 구조체 인스턴스의 프로퍼티 값에는 영향이 없음

print("first struct instance property : \(firstStructInstance.property)")
// ----- 출력값
// 1
print("second struct instance property : \(secondStructInstance.property)")
// ----- 출력값
// 2

값 타입(Value Type)을 사용하는 경우

  • 연관된 몇몇의 값들을 모아서 하나의 데이터 타입으로 표현하고 싶은 경우
  • 다른 객체 또는 함수 등으로 전달될 때 참조가 아니라 복사(값 복사) 할 경우
  • 자신을 상속할 필요가 없거나, 다른 타입을 상속 받을 필요가 없는 경우

스위프트에서의 사용

  • 스위프트의 기본 데이터 타입은 모두 구조체로 구현되어있다.
  • 스위스트는 구조체열거형 사용을 선호한다.
  • Apple 프레임워크는 대부분 클래스를 사용한다.
  • 구조체/클래스 선택과 사용은 개발자의 몫이다.

정리

  • 클래스는 참조 타입이고, 데이터를 전달할 때 값의 메모리 위치를 전달한다.
  • 두 번째 클래스가 첫 번째 클래스 인스턴스를 참조하기 할 때, 두 번째 클래스의 인스턴스 프로퍼티 값을 변경하면 첫 번째 클래스 인스턴스의 프로퍼티 값도 변경된다.
  • 구조체는 값 타입입고, 데이터를 전달할 때 값을 복사하여 전달한다.
  • 두 번째 구조체 인스턴스가 첫 번째 구조체를 복사하면 그것은 똑같이 복사된 별도의 인스턴스이기 때문에 두 번째 구조체 인스턴스의 프로퍼티 값을 변경해도 첫 번째 구조체 인스턴스의 프로퍼티 값에는 영향이 없다.
  • class안에 struct 변수를 property로 정의하는것 가능하며, 반대로 struct의 property중 하나로 class 인스턴스 변수를 갖고있는 것도 가능하다.
  • 이 경우 해당 struct 변수의 copy가 일어날때 class 인스턴스의 주소값만 복사된다.
  • 우리가 사용하는 배열, 딕셔너리, 셋과 같은 컬렉션 타입은 구조체로서 구현되어 있다.

참고

Swift) Class와 Struct의 차이점에 대해 설명하시오.

https://suzumsz.github.io/2021/09/27/Swift/Class vs Struct/

Author

Sujeong Kim

Posted on

2021-09-27

Updated on

2021-10-05

Licensed under

댓글