상세 컨텐츠

본문 제목

Swift의 값 타입과 참조 타입

iOS

by Arlo 2019. 4. 27. 16:13

본문

Swift의 배열이 얕은 복사인지, 깊은 복사인지 공부하다가 궁금한 내용이 생겨 Apple 개발자 문서의 일부를 번역해봤습니다.

( 원본 글 링크 : https://developer.apple.com/swift/blog/?id=10 )

 

안전한 변경을 위한 조건

Immutability is a guarantee that an object won’t unexpectedly change in value while you’re using it

참조 타입보다 값 타입을 사용하는 가장 큰 이유는 코드를 쉽게 이해할 수 있기 때문이다. 모든 인스턴스가 공유되지 않고 유니크하다면 (즉, 복사된다면), 앱의 다른 부분에서 원본 데이터를 변경할 일은 없을 것이다.

이러한 방식은 멀티 쓰레드 환경에서 아주 유용하다. 다른 쓰레드에서 내가 모르는 사이에 데이터를 수정할 수도 있기 때문이다. 만약 그런 일이 일어난다면 디버그하기도 힘든 지독한 버그가 발생할 수도 있다.

두 가지 타입의 차이점은 데이터를 변경할 때 무슨일이 일어나는지에 있다. 때문에 데이터의 변경이 없다면 혹은 변경가능한 데이터가 없다면, 값 타입과 참조 타입은 정확히 똑같이 동작한다. ( Copy On Write )

그렇다면 클래스를 완전히 immutable하게 만드는 방법이 있으면 좋지 않을까라는 의문이 들것이다. 그렇다면 NSObject 오브젝트를 사용할 때 값 타입의 장점을 가져갈 수 있으니 유용할테니 말이다.

하지만 지금 immutable한 클래스를 작성하는 것은 상태를 바꿀 수 있는 API를 숨기거나, immutable한 저장 프로퍼티를 사용하는 것으로만 가능하다. 사실, NSURL같은 Cocoa 클래스들이 immutable한 클래스로 설계되었는데, Swift는 언어 단에서 class를 immutable하도록 강제하는 기능을 제공하지 않는다. immutability를 강제하는 방법은 struct나 enum을 사용하는 것이다.

 

어떻게 선택할까?

만약 새로운 타입을 설계해야 한다면, 값 타입와 참조 타입 중 어느것을 선택해야 할까? 만약 NSObject의 자식 클래스로 예상되는 많은 Cocoa API와 통신하는 작업을 해야한다면 class를 사용해야 한다. 다른 경우에 대해서는 아래 가이드라인을 보자.

값 타입은 이럴 때 사용한다.

  • 인스턴스끼리 == 로 비교하는 것이 마땅할 때

  • 독립적인 상태를 가지는 개체들이 필요할 때

  • 여러 쓰레드에서 사용되는 코드에 해당 데이터가 사용될 때

참조 타입은 이럴 때 사용한다.

  • 인스턴스끼리 ===로 비교하는 것이 마땅할 때

  • 공유되며, 상태가 변경가능한 개체가 필요할 때

Swift에서, Array, String, Dictionary는 모두 값 타입이다. 마치 C언어의 int 처럼 그 데이터의 유일한 개체처럼 동작한다. 다른 코드에 의해 나도 모르게 데이터가 변경되는 것을 방지하기 위해 명시적으로 copy를 만든다거나 하는 특별한 작업을 할 필요가 없다.

중요한 것은, 동기화 할 필요 없이 여러 쓰레드 사이에서 데이터를 안전하게 넘길 수 있다는 것이다. 안전성을 높이는 측면에서, 이러한 모델은 Swift에서 예상가능한 코드를 작성하는 데에 도움이 될 것이다.


 

결론은 Array 타입이 Reference 타입을 요소로 가지고 있다 하더하도, Array가 Value 타입이므로 깊은 복사(배열 내부의 클래스 인스턴스 역시 복사됨)가 일어납니다.