2016년 7월 20일 수요일

Xcode 8 Beta 로 겪어보는 Swift 3 의 변화들

지금까지는 Xcode 의 각 베타가 나올 때 마다 변화점들을 기록하곤 했는데, Swift 가 오픈소스화 된 지금은 이런 변화를 매번 캐치할 필요는 없을 것 같다. 무엇보다, Swift 문법(Syntax) 자체의 변화를 정리할 필요도 없이 아래 사이트를 보면 Swift 3 의 변화점을 알 수 있다.

https://swift.org/blog/swift-3-0-preview-1-released/

3.0 의 변경점은 더 이상 일어나지 않고 이제 4.0 을 개발한다고 선언까지 된 상태이니 이제 기정사실이 된 변화점들이다.

이렇게 정리가 잘 된(?) 글들이 있으니 이제 내가 할 일은 그냥 체감하는 것 뿐인것 같다. 그래서 실제로 체감(?)해 보고 느낀 것들을 정리해 본다. 물론 이번 글이 전부는 아니겠지만...

이 글을 쓰는 시점에서 Xcode 8 은 Beta 3 까지 나온 상황이다. 따라서 이 글의 내용은 글을 읽는 시점에 따라 틀린 내용이 있을 수 있다.

프레임워크 변화들

문법적인 면을 제외하면 역시나 주로 쓰게될 라이브러리의 변화를 가장 크게 느낄 것이다. 실제로 Swift 3 에 맞춰서 애플에서는 각종 파운데이션 등의 프레임워크를 뜯어고치고 있다.

NS Prefix 의 실종

주로 볼 수 있는 변화는 바로 NS 라는 머릿글자(Prefix)가 보이질 않는다는 점이다. 실제로 이 NS 로 시작되는 이름의 클래스들을 가져다 쓰면 오류가 나면서 NS가 떨어져 있는 녀석으로 바꾸라는 친절한(?) 오류팝업을 볼 수 있다.
NS 는 NextStep 의 머릿글자로 구성된 약자다. 스티브 잡스가 깊게 관여한 'macOS 의 전신인 OS X의 전신인 MacOS의 전신인 ... 전설적인(?) OS' 의 이름이다.
바뀐 예로 기존 NSURL 의 도움말 팝업을 한번 보자.


Xcode 8 에서 NSURL 은 URL 로 바꾸라고 오류가 나고, 그래서 URL 로 바꿔서 보면 -_-;; 아래와 같이 표시된다.


큰 변화는 이름이 URL로 바뀌었다는 점, 그리고 타입이 struct 로 변경되었다는 점이다. 덕분에 사용법도 약간 바뀌게 되었다. (생성자가 다른데, URL 타입은 기본 생성자가 없어서 저렇게 썼으니 오해하지 말자)

이제 부터라도 데이터 타입을 모조리 struct 로 바꾸려는 애플의 의지가 잘 보이는데 사실 이게 맞는 것이다. 점점 Swift 친화적으로 프레임워크들이 바뀌고 있다는 말이다.

개인적으론 완전히 재구현한 것은 아닐거라 생각된다. 아마도 URL 구조체는 내부에 NSURL 타입의 멤버를 가지고 있지 않을까 생각된다. 즉 감싸기(Wrapper) 구조체인 것으로 보인다.

싱글톤의 변화

과거에 쓴 Swift 의 싱글톤 예제의 내용은 정적 메소드 형식이 아니라 정적 프로퍼티 형식이다. 그런데 애플이 이 방식으로 싱글톤 팩토리를 바꾸기 시작했다.

예를 들어 NSFileManager 를 보자. 이 녀석은 역시 이름이 FileManager로 바뀌었는데 또 다른 점이 있다면 싱글톤 팩토리가 이름이 축약되고 프로퍼티 형식이 되었다. 기존에 사용하던 방식은 NSFileManager.defaultManager() 였는데 이게 Xcode 8 에서는 FileManager.default 이렇게 바뀌었다.

물론 이런 변화는 싱글톤을 제공하는 거의 모든 클래스에서 발견된다. 예를 들어 NSBundle.mainBundle()Bundle.main 으로 바뀌었다.

enum의 이름들의 변화

지금(2016년 7월)까지도 enum 으로 선언된 각 case 이름들은 전부 대문자로 시작한다. 그런데 Xcode 8 부터는 이 케이스 이름들이 전부 소문자로 시작하도록 바뀌었다. 예를 들어 NSSearchPathDirectory.DocumentDirectoryFileManager.searchPathDirectory.documentDirectory 로 바뀌었다.

심지어 위의 예제에서 바뀐걸 눈치챘다면 큰 변화가 생긴 것을 알 수 있다. 기존의 전역 enum 이던 녀석들이 특정 클래스 아래로 모였다는 점이다. 이 외에도 많은 enum 값들이 어딘가로 소속(?)되어 버렸다. 예를 들자면 NSSearchPathDirectoryFileManager.SearchPathDirectory 로 바뀌었다.

과연 얼마나 많은 것들이 바뀌었을지 좀 걱정된다. 다행인건 Xcode 가 알아서 마이그레이션을 지원해 준다는 점이다. 안해줬으면 욕할뻔했다.

심지어 C 함수들도 좀 바뀐 듯

예를 들어 GCD Dispatch의 경우
dispatch_async(dispatch_get_main_queue()) { ... }
이런 식으로 메인 큐에다 실행시킬 내용을 코딩하고 했는데 이 문법은 이제
DispatchQueue.main.async { ... }
이런 식으로 써야한다.

즉, 일부 C API 들은 Swift 용으로 새로 클래스 혹은 구조체 형태로 구현되면서 기존과는 다른 형태로 제공될 것으로 보인다.

함수/메소드 라벨링

이것도 프레임워크 변화로 넣어야 하나 좀 고민했는데 Swift 3 문법 자체의 변화이기도 하기에 별도로 분리했다.

이게 뭐냐면, 이제 메소드나 함수의 첫 인자도 무조건 라벨을 붙여서 호출하도록 바뀌었다는 이야기다. 아래 코드의 경우
func test(a: Int, b: Int) { }
위 함수를 호출 할 때 Swift 3 에서는
test(a: 0, b: 1)
이런 식으로 첫 인자의 라벨(a)도 반드시 명기해야 한다.

이런 변화가 있었기에 프레임워크들도 이를 따라서 전반적으로 메소드 이름과 첫 인자 이름이 싸악 바뀌었다. 예를 들어
NSFileManager.defaultManager().directoryContentsAtPath(somePath)
위 코드가 아래와 같은 식으로 라벨링이 바뀌었다.
FileManager.default.directoryContents(atPath: somePath)
메소드 이름이 줄어든 대신, 줄어든 분 만큼이 첫 라벨로 옮겨갔다고 생각하면 고치기는 편할 것이다. 물론 Xcode 가 알아서 가이드 해주니 걱정할 건 하나도 없다.

반대로 생략하고 싶다면 기존과 동일하게 밑줄(underscope)를 붙여주자.
func test(_ a: Int, b: Int) { }
...
test(0, b:1)
이건 이젠 상식적인 이야기다.

String.CharacterView.Index 의 변화

이걸 어떻게 정리해야 하나 고민했다. 왜냐하면 String 하나의 변화라서 별로 큰 건 아닌데 개인적으로 고치는데 고생했기 때문이다.

Index 자체가 싹 바꼈는데 아예 문서에다 대놓고 'The Collection indexing model has changed dramatically in Swift 3' 라고 써 놨다. 극적인(Dramatically) 변화라고...

기존의 successor나 predecessor 가 사라지고 대신 이제는 index 자체의 after 혹은 before 라벨이 붙은 메소드를 활용해야 한다. 예를 들어 특정 문자열의 마지막 캐릭터만 골라내고 싶다면
let str = “abcde”
str[str.index(before: str.endIndex)]
이런 식으로 쓸 수 있다. 위의 경우 마지막 코드에는 “e”가 반환된다.

만약 이런 문자열 인덱스와 관련된 작업을 해 놨다면 Swift 3 에서는 각오하자 -_-;

기타

Beta 3 부터 이제 릴리즈의 기본 최적화는 'Whole Module Optimization' 이다. Xcode 7 때 까지만 해도 빌드 타임이 비정상적으로 오래 걸리는 등의 문제로 회피하는 경향의 옵션이었다.


이게 뭐냐면, C++ 의 inline 스타일 코딩, 혹은 C의 매크로 코드 기능을 컴파일러가 알아서 자동으로 해 주는 방식의 최적화를 추가하는 기능이다. 즉 알아서 자동으로 많이 쓰는 코드를 호출(call)이 아닌 쳐박아버리기(inline)로 넣어서 컴파일해 버린다는 의미다.

따라서 특정 상황에서 극적으로 퍼포먼스가 향상된다는 마법의 옵션인데 이제는 큰 문제는 사라졌나 보다. 물론 아직까지 릴리즈(Archive)를 해본 적이 없어서 판단은 못 하겠지만... -_-;;;

마무리

일부분만 정리했는데도 이 정도의 분량이 나온다. 파운데이션이나 기타 프레임워크의 변화가 너무 커서 정신이 없다.

그나마 다행인건 Python 2 에서 Python 3 로 넘어가는데 곤욕(?)을 느끼는 유저가 많은 것과는 다르게 Swift 의 경우 Xcode 7 이 알아서 3.0 문법으로 마이그레이션을 권장하는 듯 넘어가기 순탄한 정책을 취하고 있다는 점이다. 덕분에 Swift 3 가 정식으로 릴리즈 되어도 문법과 관련된 고생은 별로 하지 않아도 된다고 생각된다.

어쨌거나 미래를 대비하자. 난 Swift 3 가 마음에 들고 이번에 바뀐 프레임워크들도 마음에 든다. 그냥 고치는게 귀찮을 뿐이지... :-)

[다음글] Xcode 8 GM 으로 겪어보는 Swift 3 의 변화들 #2
[관련글] 스위프트(Swift) 가이드​

댓글 1개 :

jusung :

ㅎㅎㅎ 잘 보았습니다. 공유해주셔서 감사합니다. :)