본문 바로가기

Swift

[Swift] Struct 와 Class 뭘 써야할까?

구조체와 클래스는 데이터를 용도에 맞게 묶어 표현하고자 할 때 유용하다. 프로퍼티와 메서드를 사용하여 구조화된 데이터와 기능을 가질 수 있다. 

 

 

 

Struct 의 특징을 알아보자.

 

  • 값 타입이다. 값의 타입을 정의하기 위해 사용된다.
  • 대입 명령 시 내용이 복사된다. 
  • 참조 카운트가 없어서 메모리 관리에 안전하다.
  • 레퍼런스 형태가 아니기 때문에 공유가 불가능하다.
  • 불변성(Immutable) 구현에 유리하다.
  • 멀티스레딩에 안전하다.
  • 상속이 불가능하다.
  • 프로토콜은 사용이 가능하다.
  • Object가 아니기 때문에 AnyObject로 캐스팅이 안된다. -> 기존의 id 로 쓰던 타입들을 모두 AnyObject 로 받는 경우가 많은데 이 경우 struct 로 만들어진 값을 넘기는게 불가능하다는 의미가 된다. 대신 Any 의 경우는 struct 로 만들어진 값도 캐스팅이 가능하다.

 

Struct와 Class를 비교할 때 첫 번째 항목인 값과 참조 라는 차이점에 대해 가장 많이 언급한다. 

 

 

 

참조 타입 (Reference Type)

class Animal {
    var weight = 0
    
    init(weight: Int) {
        self.weight = weight
    }
}

var cat = Animal(weight: 10)
var dog = Animal(weight: 20)

cat.weight          // 10
dog.weight          // 20

cat = dog
cat.weight          // 20
dog.weight          // 20

dog.weight = 100
cat.weight          // 100
dog.weight          // 100


cat = dog
코드가 실행이 된 이후로 둘은 하나의 오브젝트처럼 보인다. 이것은 cat = dog 코드가 '레퍼런스 복사'로 동작한다는 것을 의미한다.(둘 다 동일한 메모리 레퍼런스를 가지고 있다는 말.) 이후 cat 이나 dog 의 값을 바꾸게 되면 동일하게 다른 쪽의 값도 바뀌게 된다. 어차피 동일한 메모리의 내용이 바뀌는 것이니까.

 

 

 

 

 값 타입 (Value Type) 

struct Animal {
    var weight = 0
    
    init(weight: Int) {
        self.weight = weight
    }
}

var cat = Animal(weight: 10)
var dog = Animal(weight: 20)

cat.weight           // 10
dog.weight           // 20

cat = dog
cat.weight           // 20
dog.weight           // 20

dog.weight = 999
cat.weight           // 20
dog.weight           // 999

 

구조체에게 있어서 '=' 연산자의 동작은 값(value)의 복사로 동작하게끔 정의되어 있다.

 

 

 

 

 생성 속도

 

메모리에 인스턴스가 생성될 때의 시간을 계산해 봤다.

컴퓨터와 시스템 상태에 따라 값은 다르게 나오지만, 무조건 Struct 가 Class 보다 빠른 걸 확인할 수 있다.

 

 

 

 

Struct 와 Class 의 공통점

  • 값을 저장하기 위해 프로퍼티를 정의할 수 있다.
  • 기능 실행을 위해 메서드를 정의할 수 있다.
  • 서브스크립트 문법을 통해 구조체 또는 클래스가 갖는 값(프로퍼티)에 접근하도록 서브스크립트를 정의할 수 있다.
  • 초기화 될 때의 상태를 지정하기 위해 이니셜라이저를 정의할 수 있다.
  • 초기구현과 더불어 새로운 기능 추가를 위해 익스텐션을 통해 확장할 수 있다.
  • 특정 기능을 실행하기 위해 특정 프로토콜을 준수할 수 있다.

 

 

 

 Struct 와 Class 의 차이점

  • 구조체는 상속할 수 없다.
  • 타입 캐스팅은 클래스의 인스턴스에만 허용된다.
  • 디이니셜라이저는 클래스의 인스턴스에만 활용할 수 있다.
  • 참조 횟수 계산은 클래스의 인스턴스에만 적용한다.

 

 

 

 

애플은 다음 조건 중 하나 이상에 해당한다면 구조체를 사용하는 걸 권장한다.

  • 연관된 간단한 값의 집합을 캡슐화하는 것만이 목적
  • 캡슐화 한 값을 참조하는 것 보다 복사하는 것이 합당할 때
  • 구조체에 저장된 프로퍼티가 값 타입이며 참조하는 것 보다 복사하는 것이 합당할 때
  • 다른 타입으로부터 상속받거나 자신을 상속할 필요가 없을 때

 

 

✅ 정리:

1. 상속, 초기화 해제객체, 레퍼런스 카운팅 등 다양한 기능을 제공하는 클래스에 비해 훨씬 제약된 수의 기능을 제공하는 스위프트가 표준 라이브러리의 구성 요소로서 적합하기 때문이다.
2. 구조체는 밸류 타입으로서, 단 하나의 소유 객체만을 지니며, 새로운 변수에 할당하거나 함수에 전달할 때는 항상 복사해서 사용한다는 점도 이유 중 하나다.

 

구조체의 이런 단순성은 우리가 작성한 코드를 체계적으로 안정화시키며, 특정 구조체를 변경해도 앱의 다른 부분은 영향을 받지 않을 수 있다.

 

 

 

 

 


출처: https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html

출처: iOS 프로그래밍을 위한 스위프트 기초(야곰)

출처: http://seorenn.blogspot.com/2016/04/swift-class-struct.html

 

Structures and Classes — The Swift Programming Language (Swift 5.7)

Structures and Classes Structures and classes are general-purpose, flexible constructs that become the building blocks of your program’s code. You define properties and methods to add functionality to your structures and classes using the same syntax you

docs.swift.org