슈프림 블로그
[Swift] 구조체와 클래스 어떤 것을 선택해야 할까? (Apple 공식 Article) 본문
tngusmiso.tistory.com/21?category=802241
전에도 구조체와 클래스에 대한 이야기를 썼지만, 이론이 그렇지
실제 데이터 구조를 설계할 때, 도대체 어떤 것을 선택해야 좋을 지 고민한 적이 많다.
찾아보니 Apple Developer 사이트에서 구조체와 클래스 중 어떤 것을 선택할지에 대해 다루는 아티클이 있어서 정리해보려고 한다.
developer.apple.com/documentation/swift/choosing_between_structures_and_classes
<!-- 4줄 요약 -->
Swift는 기본적으로 Struct를 권장하고 있다.
하지만 Objective-C와 상호운용하기 위해서는 Class를 사용하는 것이 바람직하며,
데이터의 ID(식별)를 통제해야 할 경우에도 Class를 사용한다.
Struct에서 동작을 공유하는 형식을 만들고 싶다면 Protocol을 이용한다. (상속을 지원하지 않기 때문)
Swift는 기본적으로 Struct를 권장한다.
Swift에서 구조체의 존재감
Swift의 Struct는 다른 언어의 Class에서 사용될 법한 기능들을 포함하고 있다.
예를들어, 저장프로퍼티(stored properties)와 계산프로퍼티(computed properties)도 Struct에서 사용할 수 있다.
또한, 구조체가 Protocol을 채택하여 기본 기능을 구현하도록 할 수 있다.
Swift 표준 라이브러리와 Foundation에서도 숫자, String, Array, Dictionary 등에 Struct를 사용하고 있다.
구조체를 사용할 때 장점이 뭐길래?
Struct를 사용하면 앱의 전체 상태와 흐름을 고려할 필요가 없다.
Struct는 value-type이기 때문에 값의 복사를 통해 전달되기 때문이다.
로컬에서 Struct를 변경한다고 해도, 의도적으로 흐름을 전달하지 않는 한 앱에 드러나지 않는다.
다시말하자면, Struct는 숨겨진 함수 호출을 통해 보이지 않는 곳에서 변경되지 않는다.
코드 일부만 보더라도 명시적으로 변경되는 코드를 확인할 수 있다.
하지만 Objective-C와 상호운용이 필요할 때는 Class를 사용한다.
Objective-C로 된 많은 API나 프레임워크에는 클래스로 정의된 것이 많다.
이것들을 사용하여 데이터를 처리하기 위해서는 클래스를 직접 사용하거나 상속하여 데이터를 모델링해야 할 수도 있다.
Swift의 Classs는 ID의 개념이 내장되어 있다.
참조 타입이기 때문에!! 두개의 Class 인스턴스는 프로퍼티에 같은 값이 저장되어있다고 하더라도 다른 것으로 간주된다.
Class 인스턴스를 공유하게 되면, 해당 인스턴스가 변경될 때 그것을 참조하고 있는 모든 부분에서 동일하게 변경된 모습을 볼 수 있다.
따라서 내부적으로 인스턴스 ID가 필요한 경우 클래스를 사용하는 것이 효율적이다.
파일 핸들, 네트워크 연결, CBCentralManager 등 참조를 잃지 않아야 하는 곳에 주로 Class가 사용된다.
앱에서 로컬 데이터베이스에 접근해야 할 때 데이터베이스 상태를 완벽하게 제어해야한다.
이럴 때는 Class 사용이 적절하지만, 여기저기서 해당 인스턴스를 참조할 수 있기 때문에 공유 데이터베이스에 액세스 하는 부분을 제한할 필요가 있다.
클래스 인스턴스를 모두가 공유하는 코드는 오류 발생 가능성이 높아진다.
언제 어디서 인스턴스가 좋지 못한 방식으로 변경될 지 모르기 때문에, 코드를 올바르게 작성하는 것이 아주 중요하다.
ID를 제어할 필요가 없을때는 Struct를 사용하면 된다.
로컬 데이터베이스의 경우 앱이 데이터베이스를 통제해야 했으므로 Class 자체에 있는 ID 개념을 이용했다.
하지만, 외부 데이터베이스를 사용한다면 인스턴스의 ID 권한은 전적으로 외부에서 소유하고 있다.
서버에 저장된 레코드의 경우 식별자로 통신하여 접근하고, 앱에서는 struct로 모델링하여, 디코딩할 수 있다.
이렇게 불러온 값을 로컬에서는 자유롭게 변경할 수 있다.
Struct는 원격에 저장되어 있는 데이터베이스 레코드의 ID를 제어하지 않기 때문에 로컬 변경에 의해 원격 데이터가 실수로 변경될 위험이 없다.
Struct도 Protocol을 사용하여 상속 개념을 도입할 수 있다.
Struct는 상속이 불가능하다!라고 했지만, Protocol을 사용하면 어느정도 비슷하게 모델링이 가능하다!
클래스는 상위 클래스를 상속함으로써 동작을 공유할 수 있지만,
구조체와 프로토콜은 프로토콜만 채택할 수 있다.
그렇기 때문에 어떤 것을 모델링 하더라도 상속 개념이 필요하다면 일단 프로토콜 기반으로 작성해 보는 것을 권장한다.
프로토콜은 클래스, 구조체, 열거형 모두 프로토콜은 채택할 수 있기 때문이다.
'iOS_Swift' 카테고리의 다른 글
[iOS/Swift] XCode 프로젝트에 SwiftLint 적용하기 (0) | 2021.02.14 |
---|---|
[iOS] 내 맥에 iPhone 연결하기 (iOS 개발/백업/Wi-Fi로 연결) (0) | 2021.02.12 |
[iOS/Swift] HTTP/HTTPS 통신의 기본, URLSession (0) | 2020.12.29 |
[iOS] 디스패치큐(GCD)의 종류와 특징, 그리고 주의사항 (1) | 2020.12.05 |
[iOS] 동시성 프로그래밍 - 동기/비동기 , 직렬/동시 (0) | 2020.12.05 |