Structures VS Classes for Swift

Hoontopia
hoontopia
Published in
5 min readJun 18, 2019

Swift 로 iOS 를 개발을 할 때 자주 하는 고민 중 하나는 구조체를 사용 할 것인지 클래스를 사용 할 것인지이다. (1위는 역시 네이밍;;)

Apple 은 Swift 로 코드를 작성하는 경우 “Default Structure!” 를 권장하여서 따르고 있기는 했었는데, 좀 더 명확한 기준을 정리하기 위하여 폭풍 검색, 귀중한 문서를 찾게 되었다.

그렇다. 이 글은 이 문서를 정리한 것이다.

Overview

구조 및 클래스는 데이터와 모델링 동작을 앱에 저장하는 데 적합하지만, 비슷하므로 선택이 어려울 수 있다. (인정)

따라서 새로운 데이터 타입을 앱에 추가 할 때, 아래 권장 사항을 고려해라.

  • Use structures by default. (구조체를 디폴트로)
  • Use classes when you need Objective-C interoperability. (Objective-C 와 호환이 필요한 경우 클래스로)
  • Use classes when you need to control the identity of the data you’re modeling. (모델링 중인 데이터의 identity 를 제어해야 할 때 클래스로)
  • Use structures along with protocols to adopt behavior by sharing implementations. (구현을 공유하여 동작을 맞추기 위해 구조체와 프로토콜을 같이 써라)

Choose Structures by Default

구조체를 사용하여 일반적인 종류의 데이터를 표현해라. Swift 의 구조체에는 다른 언어의 클래스로 제한되는 많은 기능이 포함된다. (저장 프로퍼티, 연산 프로퍼티 및 메소드를 포함) 또한, Swift 구조체는 기본 구현(Default implementations)을 통해서 동작을 얻기 위해, 프로토콜을 채택 할 수 있다.

구조체를 사용하면 앱의 전체 상태를 고려하지 않고도, 코드의 일부를 쉽게 추론 할 수 있다. 구조체는 클래스와 달리 값 유형이므로, 구조체의 로컬 변경 사항은 의도적으로 변경 사항을 전달하지 않는 한, 앱의 다른 부분에 영향을 끼치지 않는다. 결과적으로 해당 섹션의 인스턴스에 대한 변경 사항을 해당 코드 섹션만 보고, 명시적으로 변경된다는 것을 확신 할 수 있다. (클래스는 참조를 공유하므로 다른 코드 섹션을 의심해야..)

Use Classes When You Need Objective-C Interoperability

데이터를 처리하기 위해 Objective-C API를 사용하거나 Objective-C 프레임 워크에 정의 된 기존 클래스 계층에 데이터 모델을 맞추어야하는 경우, 클래스 및 클래스 상속을 사용하여 데이터를 모델링해야 할 수도 있다.

Use Classes When You Need to Control Identity

Swift의 클래스는 참조 유형이기 때문에 identity 가 내장되어 제공된다. 즉, 두 개의 다른 클래스 인스턴스가 각각의 저장된 속성에 대해 동일한 값을 가질 때 여전히 identity 연산자 (===)에 의해 다른 것으로 간주된다. 인스턴스가 이러한 종류의 identity 를 필요로 할 때 클래스를 사용해라. (예를 들면, 파일 핸들, 네트워크 연결 및 CBCentralManager 와 같은 공유 하드웨어 중개자)
예를 들어 로컬 데이터베이스 연결을 나타내는 타입이있는 경우, 해당 데이터베이스에 대한 액세스를 관리하는 코드는, 데이터베이스의 상태를 완전히 제어해야한다. 이 경우 클래스를 사용하는 것이 적절하지만 앱의 어떤 부분에서 공유 데이터베이스 객체에 액세스 할지는 제한해야한다. (State 관리가 필요한 경우인듯)

Use Structures When You Don’t Control Identity

제어하지 않는 identity 로 엔티티에 대한 정보가 들어있는 데이터를 모델링 할 때는 구조체를 사용해라. 예를 들어 원격 데이터베이스를 참조하는 응용 프로그램에서 인스턴스의 identity 는 외부 엔티티가 완전히 소유하고 이를 식별자로 전달할 수 있다. 앱 모델의 일관성이 서버에 저장되어있는 경우 레코드를 식별자가 있는 구조체로 모델링 할 수 있다. 아래 예제의 jsonResponse 는 서버에서 인코딩 된 PenPalRecord 의 인스턴스를 포함한다.

PenPalRecord 와 같은 모델 타입에 대한 로컬 변경에 유용하다. 예를 들어, 앱은 사용자의 피드백에 따라 여러 다른 펜팔을 추천 할 수 있다. PenPalRecord 구조체는 원본 데이터베이스 레코드의 identity 를 제어하지 않기 때문에, 로컬 PenPalRecord 인스턴스의 변경 실수로 인해 데이터베이스의 값이 변경 될 위험이 없다. myID 속성은 상수로 선언되므로 로컬에서 변경할 수 없다. (잘못된 레코드를 데이터베이스에 요청 하는 일이 생기지 않음.)

Use Structures and Protocols to Model Inheritance and Share Behavior

구조와 클래스 모두 상속 형식을 지원한다. 하지만, 구조체와 프로토콜은 클래스를 상속받을 수 없고, 프로토콜만 채택 할 수 있다. 그러나 클래스의 상속으로 만들 수 있는 상속 계층 구조는 프로토콜 상속 및 구조체를 사용하여 모델링 할 수도 있다. 상속 관계를 처음부터 구축하려는 경우 프로토콜 상속을 선호해라. 프로토콜은 클래스, 구조체 및 열거형 을 상속 허용하지만, 클래스의 상속은 다른 클래스와만 호환된다. 데이터 모델링 방법을 선택할 때는, 먼저 프로토콜 상속을 사용하여 데이터 유형 계층 구조를 작성한 다음 구조체에서 해당 프로토콜을 채택해라!

https://developer.apple.com/documentation/swift/choosing_between_structures_and_classes

--

--