상세 컨텐츠

본문 제목

[iOS][Swift] 구조체와 클래스 : Difference between Struct and Class

iOS

by caution.dev 2018. 11. 21. 11:26

본문

안녕하세요! caution입니다.

iOS 카테고리의 첫 번째 글이네요! 이 카테고리에는 주로 iOS나, Swift 관련한 개념정리용으로 포스팅 할 예정이에요.

첫 번째는 Swfit 의 Struct와 Class 에 대한 이야기입니다.

Struct와 Class는 모두 어떤 데이터를 담을 수 있는 구조를 만들 때 사용됩니다. 우리가 사용하는 Int, String 들도 Swift의 미리 정의되어 있는 struct입니다. 자주 사용하시는 타입이 struct인지 class인지 궁금하시다면 xcode상에서 option + click 으로 정의를 엿볼 수 있어요! 실제 정의부로 들어가고 싶으시다면 command + click 으로 jump to Definition으로 들어가보셔도 좋아요.

option + click 


command + click


struct 와 class의 공통점과 차이점은 다음과 같습니다. 

(공통점)

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

(차이점)
  • 구조체는 상속할 수 없음
  • 타입캐스팅은 클래스의 인스턴스에만 허용 -> 구조체는 Any만
  • 디이니셜라이저는 클래스의 인스턴스에만 활용
  • 참조 횟수 계산은 클래스의 인스턴스에만 활용
  • 구조체는 let으로 선언하면 내부 프로퍼티 값을 변경할 수 없지만, 클래스는 let으로 선언해도 내부 프로퍼티 값을 변경할 수 있음
  • 구조체는 값 타입, 클래스는 참조타입

차이점의 마지막에, 값 타입과 참조타입에 대한 이야기가 나왔습니다. 값 타입과 참조타입은 뭘까요?
이는 이미 정의된 특정 변수를 다른 변수에 복사하거나 초기화하는데 사용하는 등 대입 명령을 사용할 때 값을 복사해서 새로운 인스턴스를 만들어내는지, 아니면 이미 정의된 변수에 대한 메모리 주소를 참조하는 방식으로 복사되는지의 차이에 따라 값 타입과 참조 타입으로 나뉩니다.
 구조체는 값 타입이라고 했으니 Int도 값 타입이겠죠! 다음 예시 코드를 보겠습니다 :)

let firstInt : Int = 100

var secondInt : Int = firstInt

secondInt += 200


print("firstInt : \(firstInt) , secondInt : \(secondInt)")

이 경우 firstInt와 secondInt의 값은 같을까요? 다를까요? 앞선 설명에 따르면 secondInt를 초기화할 때 firstInt의 값을 단순 복사했기 때문에 secondInt를 변경했다고 해서 firstInt에 영향을 주지 않습니다.
그렇다면 클래스로 정의된 인스턴스를 복사할 때는 어떨까요?

class Person {

    let name: String

    var age: Int

    

    init(name: String, age: Int) {

        self.name = name

        self.age = age

    }

}


let caution = Person(name: "caution", age: 0)

let oldCaution = caution

oldCaution.age = 100


print("caution.age : \(caution.age), oldCaution.age : \(oldCaution.age)")

 oldCaution 의 age 값을 변경했는데 caution의 나이마저 변경되어 버렸습니다!(안됑) 참조타입은 값을 복사하여 새로운 인스턴스를 만들어 내는 것이 아니라, oldCaution은 기존 caution 인스턴스의 메모리 주소값을 복사하여 가지고 있기 때문에 oldCaution의 값을 변경하든, caution의 값을 변경하든 결국은 하나의 인스턴스를 변경하게 됩니다.

그렇다면 언제 클래스와 구조체를 사용해야 할까요? 간단히 정리해보았습니다 :)

struct의 특징

  • 참조 타입이 아니기 때문에 공유가 불가능하다.
  • 참조 카운트를 확보하지 않기 때문에 메모리 관리에 안전하다.
  • let 변수에 선언해서 불변성 구현에 유리하다.
  • 멀티쓰레딩에 안전하다.
  • 상속은 부족하지만 프로토콜은 사용할 수 있다 > AnyObject로의 캐스팅이 불가능하다.
  • 클래스 보다 인스턴스 생성이 빠르다. 하지만 데이터의 용량이 커지면 커질수록 복사속도는 클래스가 더 빠를 수 있다.
구조체를 사용해야 할 때
  • 적은 데이터, 즉 멤버 프로퍼티의 갯수나 차지하는 메모리 용량이 적은 타입
  • 연관된 간단한 값의 집합을 캡슐화 하는 것만이 목적일 때
  • 구조체에 저장된 프로퍼티가 값 타입이며, 참조되는 것보다 복사되는 것이 합당할 때
  • 다른 타입으로부터 상속받거나, 자신이 상속될 필요가 없을 때
  • 불변성을 확보하고 싶을 때

구조체를 사용해서는 안될 때 = 클래스를 사용해야 할 때

  • 싱글톤(Singletone Pattern)과 같이 값이 공유되어야 할 때
  • 저장 프로퍼티에 참조 객체가 들어갈 때 
  • View나 ViewController의 경우도 공유 형태이니 레퍼런스 접근이 되어야만 한다.
struct의 특징
참조 카운트가 없어서 메모리 관리에 안전하다. 래퍼런스 형태가 아니라서 공유가 안된다. let 변수에 선언해서 불변성 구현에 유리하다. 멀티쓰레딩에 안전하다. 상속이 불가능하다. 하지만 프로토콜은 사용할 수 있다. AnyObject로의 캐스팅이 되지 않는다.


오늘의 포스팅은 여기까지입니다!

감사합니다 :)

'iOS' 카테고리의 다른 글

[iOS] ViewController Life Cycle  (0) 2018.12.14
[iOS][Swift] escaping vs non-escaping 차이  (1) 2018.11.21

관련글 더보기