현재 Swift를 사용하며 iOS를 개발하다가 Kotlin으로 Android 개발을 하게 된 상태이다. Kotlin과 Android를 개발하며 공부할 때 Swift와 어쩔 수 없이 비교하게 되는 부분들이 있다. 그러한 부분들을 이 카테고리에 정리해보려 한다.
Kotlin과 Swift는 서로 유사한 점이 아주 많다. 많이 비슷하지만 두 언어가 완전히 같다고 할 수는 없다. 유사한 점들은 두 언어를 봐보면 알 수 있고, 다른 문서들을 찾아봐도 많이 나온다. 이번 글에서는 유사해보이지만 차이가 있는 부분들에 대해서 다뤄보겠다.
struct (Swift)와 data class (Kotlin)
Swift/Kotlin의 struct (data class)는 class의 간소화된 버전이다. 다음과 같이 만들어서 사용할 수 있다.
[Swift]
[Kotlin]
생성이나 사용에 있어서는 큰 차이가 없을 수도 있지만, 이름을 보면 생각해볼 수 있는 차이점이 하나 있다. Kotlin의 data class는 이름에서 알 수 있듯이 여전히 class 타입이다. Swift의 struct는 class가 아닌 value 타입이다. 이로 인해 어떤 차이가 발생할 수 있는지는 다음 코드를 보며 생각해볼 수 있다.
[Swift]
[Kotlin]
Swift와 Kotlin 모두 동일한 코드를 수행한 것처럼 보인다. 위의 상태에서 foo2에는 무엇이 들어있는지 확인해보면 다른 것을 알 수 있다. 다음은 실행 결과이다.
[Swift]
[Kotlin]
Swift의 foo2에는 1이, Kotlin의 foo2에는 10이 들어있다. Swift의 struct는 foo2 = foo1 과정에서 새로운 struct가 생성되고 내부 값들에 대한 복사가 일어난 것이고, Kotlin의 data class는 class이기 때문에 foo2에 reference만 전달된 것이다.
Swift는 위와 같은 값을 전달할 때 복사가 일어나지만, Kotlin의 경우는 레퍼런스가 전달되어 다른 곳에서 값을 변경했을 때 원본 값도 수정이 되어버려서 문제가 발생할 수 있다. 이를 방지하기 위해서 "Defensive Copy"를 해주는 것이 좋다.
[Kotlin]
[결과]
위와 같이 Dictionary class로부터 객체를 생성해서 words를 dictionaryWords에 받아 수정하면 객체의 값도 같이 수정된다. 하지만 이런 동작을 의도한 경우라면 괜찮지만 그렇지 않은 경우가 더 많을 것이다. 이럴 때 "defensive copy"를 해주어야 하는데 Kotlin에서는 Java보다 편하게 "defensive copy"를 할 수 있다. ".toMutableList()"를 뒤에 붙여서 사용하기만 하면 된다. 참고로 Swift에서는 위의 경우처럼 사용하여도 copy되어 할당되기 때문에 "defensive copy"를 하지 않아도 된다. 다음은 toMutableList()를 사용하여 "defensive copy"를 했을 때이다.
[Kotlin]
[결과]
기존 객체의 값은 변경되지 않고, 의도한 대로 잘 동작하는 것을 확인할 수 있다.
Protocol (Swift), Interface (Kotlin), Extension
Swift의 Protocol과 Kotlin의 Interface는 거의 동일하다. 거의 동일하다는 말은 조금은 다른 부분도 있는 것인데 먼저 동일한 부분만 살펴보면 다음과 같다.
1. 특정 함수가 실제 class나 struct에서 implement되도록 명시할 수 있다.
2. 프로퍼티를 설정하고, get/set 여부를 설정해줄 수 있다.
3. 구현된 함수를 넣어줄 수 있다.
차이점이 한 가지 있는데 이는 다음과 같다.
-> Swift의 Protocol은 특정한 initializer도 설정해줄 수 있다.
코드를 통해서 하나씩 살펴보도록 하자.
Protocol & Interface
[Swift]
[Kotlin]
앞서 설명한 protocol과 interface의 기본적인 모습은 위와 같다.
Swift Extension
[Swift]
[결과]
swift의 일반적인 extension은 위와 같다. protocol을 받는 경우는 `extension class이름 : protocol이름` 형태로 받아서 구현하면 된다.
Kotlin Extension
[Kotlin]
[결과]
위와 같은 방법으로 변수를 바로 extension 할 수 있다.
변수와 비슷한 방식으로 함수도 바로 extension해서 사용할 수 있다.
Swift Extension 추가
`Extension`에 대한 기본적인 개념과 동작은 Swift와 Kotlin 모두 비슷하다. 변수나 함수 하나만 extension할 필요가 있을 때는 Kotlin이 더 간결해 보인다. 하지만 개인적으로는 `extension`을 `protocol`과 함께 사용하는 경우가 많은데 이러한 부분에 대해서는 Swift가 더 잘 되어 있다.
[Swift]
iOS 앱을 만드는데 제목과 내용만 다른 팝업 메시지를 자주 띄워야 하는 경우가 있다고 치자. 한 두 군데의 뷰에서만 그렇다면 그쪽에 구현해두고 사용을 하면 되지만, 큰 앱 내에서 여러 곳에서 이러한 팝업들이 사용되고 있다면 매번 구현하기는 번거로울 것이다. 그럴 때 팝업을 보여주기 위한 protocol을 위와 같이 선언하였다.
[Swift]
extension을 통해 미리 동작 부분을 구현해둔다. 여기서 특이한 점이 있는데 `where Self: UIViewController` 부분이다. UIViewController만이 위의 implemented된 protocol을 받을 수 있게 만든 것이다. 팝업을 보여주기 위해 `present()`를 사용하려면 view controller reference가 필요하기 때문이다. 이를 직접 받아서 사용하거나 로직을 만들면 복잡해지고 오류를 만들 확률이 높아진다. 하지만 위와 같은 방법을 통하면 간단하게 `present()`도 사용하며, protocol을 UIViewController만 받도록 할 수 있다. 팝업이 필요한 UIViewController에서 `extension`만 해주면 위의 함수를 이용하여 편하게 팝업을 보여줄 수 있는 것이다. 여기서 더 나아가 UIViewController 자체를 확장할 수도 있다. `extension UIViewController: popupPresentable {}` 과 같이 확장하면 어떠한 UIViewController에서도 팝업을 띄울 수 있다.
'Swift vs Kotlin' 카테고리의 다른 글
Swift / Kotlin - 유사 문법 비교 2 (764) | 2020.05.23 |
---|---|
Swift / Kotlin - 유사 문법 비교 1 (626) | 2020.05.19 |
댓글