[Swift]구조체와 클래스 알맞게 쓰기

권승용·2022년 7월 28일
0

Swift 프로그래밍

목록 보기
6/7

이 글은 애플 공식 문서에 있는 Choosing Between Structures and Classes의 내용을 요약한 것입니다.

구조체? 클래스?

구조체와 클래스는 그 유사성 때문에 언제 무엇을 사용해야 하는지 선택하기 어렵다.

그럴 땐 아래 조건들을 먼저 생각해 보자.

  • 기본적으로 구조체를 사용하라.
  • Objective-C와의 상호 운용성(interoperability)이 필요하다면 클래스를 사용하라.
  • 모델링 중인 데이터의 identity를 제어해야 한다면 클래스를 사용하라.
  • 상속 구조를 모델링하고 싶다면 구조체와 프로토콜을 사용하라.

상속이 없다면 구조체가 더 빠르고 메모리 면에서 효율적이다!

기본적으로 구조체 사용하기!

Swift에서의 구조체는 다른 언어에서는 클래스에서만 사용 가능한 다양한 기능들을 제공한다.

더해서, Swift의 구조체는 프로토콜의 채택을 통해 상속 기능도 구현 가능하다.

Swift 표준 라이브러리와 Foundation은 우리가 자주 사용하는 타입들(Int, String, 배열과 딕셔너리 등)의 구현에 구조체를 사용하고 있다.

구조체를 사용하면 전체적인 앱의 상태를 고려할 필요가 적어진다.

왜냐하면 구조체는 클래스와 달리 값 타입이기 때문에 구조체에 대한 변경사항이 앱의 다른 부분들에게 영향을 미칠 가능성이 적기 떄문이다.

Objective-C 와의 상호 운용성이 필요하다면 클래스 사용하기!

데이터를 프로세스하는 데 Objective-C API를 사용하거나, Objective-C 프레임워크에 정의된 클래스 계층 안에 데이터를 맞춰 넣어야 한다면 데이터의 모델링을 위해 클래스와 클래스 상속을 사용해야 한다.

Identity를 제어해야 한다면 클래스 사용하기!

Swift에서의 클래스들은 참조 타입이기 때문에 identity 개념이 내장되어있다.

이는 두 개의 다른 클래스 인스턴스들이 그들의 저장 속성에 같은 값을 갖고 있어도 identity 연산자(===)를 사용해 보면 둘이 서로 다르게 인식됨을 의미한다.

이는 또한 앱 전반적으로 공유되는 클래스 인스턴스가 있다면 해당 인스턴스에 가하는 변경점들이 그 인스턴스를 참조하는 코드들에 영향을 미친다는 것도 의미한다.

이러한 종류의 identity 제어가 인스턴스에서 필요하다면 클래스를 사용해야 한다.

대중적인 사용 예로는 파일 관리, 네트워크 연결, 공유 하드웨어 중개(ex: CBCentralManager) 등이 있다.

예를 들어, 만약 로컬 데이터베이스 연결을 나타내는 타입이 있다면 해당 데이터베이스에 대한 접근을 관리하는 코드는 데이터베이스 상태에 대한 모든 제어권이 필요하다.

이러한 경우에는 클래스를 사용하는 것이 적절하지만, 공유되는 데이터베이스 객체에 접근 가능한 객체들에 대한 적절한 제한이 필수적이다.

⭐️ 앱 전체에서 공유되는 클래스 인스턴스들이 만연해 있다면 논리 에러가 일어날 가능성을 증가시킨다.
많은 부분에서 사용되고 있는 클래스 인스턴스에 변경을 가했을 때 어떤 결과가 있을 지 예상하기가 어렵기 때문이다.

Identity를 제어할 필요가 없다면 구조체 사용하기!

만약 앱에서 원격 데이터베이스를 참조한다면, 인스턴스의 identity는 외부 엔티티가 모두 소유하고 있고 식별자(identifier)를 통해 전달될 것이다.

아래 코드를 살펴보자.

struct PenPalRecord {
	let myID: Int
    var myNickname: String
    var recommendedPenPalID: Int
}

var myRecord = try JSONDecoder().decode(PenPalRecord.self, from: jsonResponse)

위 코드를 살펴보면 서버로부터 인코딩된 PenPalRecord 인스턴스를 jsonResponse가 저장하고 있다.

이 때 PenPalRecord 구조체는 데이터베이스 레코드들의 identity를 제어하지 않기 때문에, 각 PenPalRecord 인스턴스에 변경이 가해져도 실제 데이터베이스에 있는 값들이 변경될 위험이 없다.

상속을 모델링하고 싶다면 구조체와 프로토콜 사용하기!

구조체와 클래스는 둘 모두 상속 기능을 지원한다. 다만 구조체와 프로토콜은 프로토콜을 채택 가능할 뿐, 클래스로부터 상속받기는 불가능하다.

그러나 클래스의 상속으로 구현 가능한 계층적 상속 구조 또한 프로토콜 상속과 구조체를 사용해 구현 가능하다.

만약 상속 관계를 처음부터 구현하려고 한다면 프로토콜 상속으로 시작하는 것을 추천한다.

프로토콜은 클래스, 구조체 및 열거형에도 상속 기능 구현이 가능하지만 클래스는 다른 클래스만 상속이 가능하다.

만약 데이터를 모델링 방법을 고민 중이라면, 데이터 타입 계층을 프로토콜 상속을 통해 먼저 구현해 보고, 이 프로토콜들을 구조체에 채택해 보는 것을 추천한다.

profile
ios 개발자 지망생 입니다!

0개의 댓글