제목 : Swift4 Release Process

이 포스팅은 Swift4의 목표, 배포과정, 산정된 스케줄에대해 이야기한다.

Swift4는 2017년 가을에 메이저 배포를 완료할 것으로 보인다. 이 언어에서 바이너리 안정성을 필요로하는 필수의 기능 작업들을 구현하면서, Swift3 코드에대한 소스 안정성을 제공하는 것을 중심으로 돌아가고있다. 이것은 핵심 언어와 표준 라이브러리를 증진시키는 중요한 것을 포함할 것이다. 특히 제네릭 체계와 String 타입의 큰 변화에 대해 말이다. 더 자세한 내용은 Swift Evolution 페이지에서 확인할 수 있다.

소스 호환성
Swift4 컴파일러는 -swift-version 3 모드와 -swift-version 4 모드 두가지를 제공한다.

Swift Version 3 모드
-swift-version 3 모드는 현재 코드의 디폴트이다. 이 모드로 할때 강력한 목표는 다음과 같다. Swift3.1로 만들어진 막대한 소스들을 계속해서 Swift4로 만들게 하는 것이다. 한편, 예외가 있는데, 한번에 받아드리지 못한 코드를 거절하기위해 발생한 버그를 고치는 경우이다. 실제로는 이런 경우가 상대적으로 드물 것으로 보인다.

여러분의 코드가 Swift3.1 컴파일러로는 컴파일 되었는데 Swift4 컴파일러로는 의도치않은 거절을 당한다면 버그리포트를 보자.

Swift Version 4 모드
-swift-version 4 모드는 이 배포에서 새로운 것들을 가능하게 해주고 파괴적인 변화를 가능하게하는 모드이다. 주목할만한 중요한점은 String API의 철저한 정비이다. 핵심은 API의 인간공학의 증진과 그 퍼포먼스 증진에 있다.

이 변화들은 기존의 소스를 바꾸게 만들고 새 API를 사용하기위해 현재 코드를 마이그레이션 해야할 것이다.

코드 마이그레이션 관점에서 보면 그 부담의 크기가 2.3에서 3.0으로 넘길때보다 3.0에서 4로 갈때가 훨씬 작을 것이다.

다른 언어로 코드 합치기 모드
의도했던 설계는, 다중 Swift 타겟으로 한 Xcode 프로젝트처럼, 다중 Swift 모듈을 담은 프로젝트가 모듈의 (타겟) 레벨마다 특정 Swift 언어 모드로 적용할 수 있게 하고, 컴파일된 같은 바이너리 안에서 자유롭게 상호 소통할 수 있게 하는 것이다. 타겟이 같은 컴파일러로 컴파일 되었을 때만 바이너리 레벨에서 이런 상호 소통이 가능하다는 점을 잊지말자.

상호소통이 가능해지면 어떤것이 가능한지 예시들을 보자.
  • Xcode에서 앱 타겟은 Swfit4로 작성하는데(-swift-version 4) 여러 프레임워크는 개별의 Swift3으로 작성된 것을 사용할 수 있다(-swift-version 3).
  • Swift4로 작성된 Swift 패키지(-swift-version 4)는 현재 페키지 소스를 Swift4로 업데이트하지 않고서도 Swift3으로 작성된 패키지인채로 사용할 수 있다.

전체적으로는 이런 규약이 점차 Swift3코드를 Swift4로 마이그레이션 시키도록 해줄 것이다(한번에 한 타겟이나 한 패키지씩).

Swift 배포에서 소스 호환성의 더 자세한 계획을 보고싶다면 Swift-evolution 메일링 리스트의 이 스레드에서 확인할 수 있다.

Swift4의 스넵샷
Swift3.1의 경우처럼, Swift4도 매일 다운받을 수 있는 배포 브랜치의 스넵샷이 있을 것이다. 스넵샷은 연속적인 통합 테스트의 부분으로서 만들어지 질 것이다. 다운로드가능한 스넵샷의 주기는 더 빈번해질 것이다. 테스트가 통과되었다면 스넵샷은 매일 찍힐 것이다.

Swift4로 바꾸기
마지막 브랜치 날짜 전까지 현재 메인으로 개발되는 모든 변경사항들(master 브랜치)은 배포 관리자가 발표한다. 아마 2017년 초여름에 될 것으로 보인다. 그 시점 이후, 정해진 사항만 그 기간에 "만들" 것이고, 중요한 수정사항은 swift-4.0-branch로 갈 것이며, master를 개발하여 다음 배포를 준비할 것이다.

브랜치들
  • master : swift-llvm, swift-clang, swift-lldb를 제외하고 Swift4 개발은 master에서 일어난다. master에서 일어나는 모든 변경사항은 마지막 브랜치 날짜까지 마지막 Swift4 배포의 부분으로 들어갈 것이다. 그 시점에서 master는 다음 배포에대한 개발을 따라간다.
  • swift-4.0-branch : Swift4를 위한 배포 관리는 swift-4.0-branch에서 일어난다. 모든 Swift4의 스넵샷은 이 브랜치로부터 만들어지고, 또한 Swift4는 이 브렌치로부터 GM이 된다.
계획상, master는 마지막 브랜치 날짜 전까지 약 2주에 한번꼴로 swift-4.0-branch에 머지(merge)된다. 2주라는 시기에 master 브랜치와 그 보조의 배포 브랜치 개발 사이의 버퍼 역할을 한다. 변경사항들은 (풀 리퀘스트를 통해)신중하게 골라져서 master의 머지들 사이에 swift-4.0-brach로 들어간다.

이 계획의 주목할만한 예외는 swift-package-manager이다. 이것은 매일 master 브랜치에서 swift-4.0-brach로 머지될 것이다.

Swift4로 바꾸는 철학
  • Swift3.1의 소스 호환성은 -swift-version 3모드에서 가장 높은 우선순위이다.
  • Swift4의 보장으로서는 배포의 핵심 목표를 맞추는 변경사항만이 고려될 것이다.
  • 언어와 API에대한 모든 Swift4의 변화는 Swift Evolution 절차에따라 진행될 것이고, 여기에는 배포에대해 어느 범위안에 무엇이 바뀔지 그 기준들을 적어놓았다.
  • 배포 보장처럼 4회로 변경사항을 풀(pull)하는 기준들이 점점더 엄격해질것이다.

영향을 받는 저장소들
아래 저장소들은 Swift4 배포의 일부분으로서 소스를 따라가기위해 swift-4.0-branch 브랜치를 가질 것이다.
swift-llvmswift-clangswift-lldb 저장소는 이미 master에서 swift-4.0-brach로 나왔으며, 다시 브랜치가 나오진 않을 것임을 기억하자.

배포 관리자
배포의 전반적인 관리는 아래 사람들이 개별적으로 감독한다. 배포의 의견으 모아지고, 제한하는 사람(strictoer)이 변경사항을 조정하는게 Swift4 배포에 영향을 줄 때, 이 사람들이 발표할것이다.

배포 관리 과정에 대해 궁금한점이 있다면 마음편하게 swift-dev로 메일을 보내거나 Ted Kremenek로 직접 메일을 보내달라.

릴리즈 브랜치를 위한 풀리퀘스트
릴리즈 브랜치에서 적용시킬 변경사항을 담은 모든 풀리퀘스트는 아래 정보를 담아야한다.
  • 설명(Explanation) : 고쳐진 이슈나 개선된 것에대한 설명. 간단해도 되지만 명확해야한다.
  • 범위(Scope) : 이 변경사항이 주는 영향/중요성의 판단. 예를들어 이 변경사항은 소스를 고쳐야하는 언어 변경사항이다 등..
  • SR 이슈 : SR은 bugs.swift.org에서 이슈/개선점을 고치는/구별하는 변경사항일때이다.
  • 위험성(Risk) : 이 변경사항이 배포에 줄 수 있는 특정 위험성은 무엇인가?
  • 테스트 : 이 변경사항의 영향을 검증하기위해 어떤 특정 테스트를 하였고 나중에 어떤 것이 더 필요한가?
영향을 줄 수 있는 컴포넌트를위해 한명 혹은 그 이상의 코드 소유자들이 이 변경사항을 검토해야한다. 기술적 검토는 코드 소유자로부터 위임받거나, 아니면 적절하거나 유용하다고 간주되게 요청될 수 있다.

swift-4.0-brach로 가는 모든 변경사항(master에서 자동으로 머지된 바깥의 변경사항들)은 반드시 해당 배포 관리자가 승인한 풀리퀘스트를 거처야한다.



    WRITTEN BY
    tucan.dev
    개인 iOS 개발, tucan9389

    ,

    기억할것: Swift는 여전히 ABI-안정성이 지원되지 않음!
    이 글을 읽기 전에 모두가 알아야 할 사실은 Swift가 여전히 ABI에 안정적이지 않다는 사실이다. 이 말은 이전 버전의 Swift 컴파일러로 만든 바이너리가 현재 버전과 호환이 되지 않는다는 의미이다. 좀 더 알아듣기 쉽게 설명하자면 여러분의 모든 파일과 의존성들은 같은 버전의 Swift로 컴파일해야한다는 의미이다: 다른 버전의 Swift로 작성된 코드들은 합칠 수 없다.

    애플은 현재 최신버전의 Swift3.0을 깨부수면서 (약속한것은 아니지만) 이것을 해결하려고 노력중에 있으며 Swift4에서 ABI 안정성을 지원할 계획이다.

    2.3으로 가야할까 3.0으로 가야할까?
    만약 여러분이 우리 VTS처럼 중요한 Swift 코드베이스를 가지고 있다면 아래에 해답이 있다.

    그렇다. 두가지 다이다.

    여러분의 Swift 코드베이스가 지저분하지 않다면 2.3을 생략하고 3.0으로 넘어가면 된다.

    아래에 염두할 것들이다.
    1. 의존성은 중요하다. 여러분의 의존성이 Swift2.3이나 Swift3.0을 지원하는지 확인해야한다. 대부분 주요 라이브러리/프레임워크들은 둘 다 지원하고 있다(Alamofire, Charts). 그러나 기억해야할 것은 Swift3.0을 업그레이드 하는 방법은 하나밖에 없다. Swift3.0으로 새 개발을 시작하고 나면 2.3버전의 모든 의존성이 업데이트 없이는 작동하지 않을 것이다.
    2. 8.x 버전의 Xcode는 Swift2.3 지원을 멈출 것이다. Swift2.3은 Swift3.0으로 업그레이드 하기 힘든 프로젝트를 위한 매개 단계의 경향이 있다.
    3. 만약 여러 프로젝트에 걸쳐진 개인의 CocoaPods이 있다면 먼저 이것부터 업그레이드 해야한다.

    2.3으로 업그레이드 할 수 있으나 어느정도 지연이 될지도 모른다. Xcode9가 배포되기 전에 Swift3으로 갈아타야하기 때문이다.

    Swift2.2에서 2.3으로 마이그레이션 이슈
    마이그레이터는 아마 Range<T>를 CountableRange<T>로 변환할 것이다. Swift3에는 오직 CountableRange<T> 밖에 없기 때문이다.

    마이그레이터는 dispatch_queue_set_specific() 사용을 위해 /*Migrator FIXME: Use a variable of type DispatchSpecificKey*/ 주석을 달아 줄 것이다. 이것은 미래의 Swift3으로 마이그레이션 하는 것과 관련이 있다.

    Swift2.x에서 Swift3.0으로의 마이그레이션 이슈
    Swift의 3.0버전은 "모든걸 깨부순(break everything)" 배포이다. Swift3은 모든 것을 깨부수고 언어적 긴 용어가 필요없는 모든 것을 없앨 것이다. 따라서 많은 변화가 생기고, 프로젝트를 안정화시키기위해 그 많은 것들을 고쳐야할 것이다.

    Swift2.3
    Swift2.3은 굉장히 마이너한 업데이트이다. 어떤 식으로 마이너할까? 사실 딱 한가지가 바뀌었다. 컴파일타임 nullability가 바뀐 애플 SDK의 Objective-C 코드를 체크하는 것이다.

    몇몇 마이너한 이름 재정의과 수많은 옵셔널 생성자와 같은 다른 변화들은 이제 옵셔널 대신에 필요한 오브젝트를 반환한다. 이것은 번들로부터 nib을 인스턴스화하는 것과 같은 것들에 적용됐다.

    Swift3.0

    (인지할만한)주요 변화들
    private의 정의는 fileprivate로 바뀌었다.

    공식적으로 private라 불리던 것이 이제 fileprivate로 바뀌었다. fileprivate 변수는 extension으로 접근할 수 있다. private 변수는 클래스에서 extension으로 접근할 수 없다.


    public의 정의는 open으로 바뀌었다.
    현재 클래스나 파라미터 public 정의는 두가지 기능을 제공한다.
    1. 외부모듈이 클래스나 맴버를 사용할 수 있다.
    2. 외부모듈이 클래스나 맴버를 오버라이드 할 수 있다.

    Swift3에서의 public은 외부적으로 사용가능함이지, 오버라이드 가능함은 아니다.
    이전의 이 기능은 open으로 되었다.


    동사와 명사
    함수 이름이 -d(과거형)으로 끝나는 것들은 그 오브젝트의 새 인스턴스를 반환한다.
    이러한 변화는 reverse와 reversed, enumerate와 enumerated 등에 적용한다.

    Objective-C의 불리언은 이제 is라는 단어로 시작되고 Foundation 타입은 더이상 접두에 NS를 사용하지 않는다(NSString처럼 String과 충돌이 일어나는 경우들은 빼고 말이다.).

    Foundation 타입은 Swift의 let과 var 선언에서 아지 잘 동작할 것이다.



    맴버로 불러오기
    설명이 달린 C 함수들을 메소드로 부를 수 있다. 임포터(importer)는 보통 이러한 맵핑을 자동으로 추론할 수 있아며 Swift에 예전의 C-API를 자연스럽고 네이티브하게 사용할 수 있게 해준다. Case and point, CoreGraphics API. 참고로 CoreGraphics는 이번 배포때 공식적으로 업데이트 되지 않았다.


    케멀케이스(CamelCase) 변화들
    열거형이나 프로퍼티에서 머리문자(CG, NS등)로 시작하는 것들이 UpperCamelCase에서 LowerCamelCase로 대체되었다. 
    // Before
    let red = UIColor.redColor().CGColor
    // After
    let red = UIColor.red.cgColor

    (개인적으로 가장 작은 변화라 생각되는)상태절 변화

    이제부터는 guard, if, while절에서 where 키워드를 사용할 수 없다. where 키워드는 for-in-where 형태의 for문에서는 사용할 수있다.
    case 절에서도 마찬가지로 바뀌었다.


    첫번째 인자의 문자 일관성
    이렇게 이해하면 쉽다: 첫번째 파라미터의 이름은 디폴트로 필요하다.


    (내가 좋아하는 변화인)묵시적으로 언랩핑된 옵셔널 다루기
    여러분이 여러 언어(shared-language)로 프로젝트를 할 때 이 점 덕분에 마이그레이션 작업이 의미있어진다고 생각이 든다. 그것이 무엇일까?

    이전에 ImplicitlyUnwrappedType! 프로퍼티를 가진 Objective-C 타입이 이제 WrappedType?로 되었다. 아래의 경우를 제외하고 모두 적용된다.

    더 나은 Objective-C API 변환
    네이밍이 더 명확해졌다.

    최신식 디스패치

    컬랙션 타입이 새로운 모델을 가지게 됨
    이전에 컬랙션 타입에서 한 인덱스에서 시작하여 탐색할 때는 index의 successor 메소드를 사용해야 했다. 이제는 이 책임이 컬랙션으로 넘어가게 되었다. c.index(after:index) 이런식으로 작성한다. 컬랙션은 이제 어떤 comparable 타입의 인덱스를 가진다.
    (아래 부분은 Range 오브젝트를 손수 만들때 적용된다. 보통 이렇게 할 일은 드물거라 생각된다.)

    이런 변화에서 사이드 이팩트로서 Range가 여러 타입으로 쪼개어졌다(Range, ClosedRange, CountableRange, CountableClosedRange) ClosedRanged는 이제 그 타입(0...Int8.max)의 최대값 범위를 포함한다. Range와 ClosedRange는 더이상 반복(iterate)을 할 수 없다. 그 의무로서 오직 Comparable 오브젝트만 필요하다. 따라서 Range<String>을 만들 수 있다.

    Objective-C의 id는 Swift의 Any 타입으로 불러와진다.
    애플의 말을 인용하자면
    이제부터 id는 'AnyObject'가 아닌 'Any'로 불러오기 때문에, 이전에 여러분이 'AnyObject'로 동적인 검색을 수행하는 곳에서 애러가 뜰 수도 있다.

    (인식하지 못할지도 모르는)작은 변화들
    옵셔널 비교연산자가 제거됨
    현재 nil 타입은 비교가능하다.

    이 점은 아래와같이 버그를 만들기 쉽다.

    이제는 이것들을 비교하기 전에 반드시 언랩핑을 해주어야한다.
    이것이 굉장히 좋은 점 중 하나이기도 하지만 유닛테스트를 망가뜨릴지도 모른다.

    클러저 파라미터 이름과 레이블
    수많은 클로저 파라미터 이름이 재정의되고 선택적으로 바뀌었다.

    flatten이 join으로 명칭이 바뀌었다.

    UnsafePointer<T> 다루기
    오브젝트가 아닌 것들의 포인터 타입의 nullability는 옵셔널을 사용해 표현할 수 있다.

    부동 소숫점 값을 반올림하는 기능은 이제 그 값이 가지고 있다.
    이전에는 부동 소숫점을 반올림하기 위해 전역의 C함수(float나 ceil)을 사용할 수 있었다. 아직 이 함수들도 사용가능하나 디프리케이트 될지 고려되고 있다.

    대신 아래와 같이 사용할 수 있다.
    추가적인 반올림 기준이다.
    1. toNearestOrAwayFromZero
    2. toNearestOrEven
    3. towardZero
    4. awayFromZero

    제네릭 타입 에일리어스

    연산자 정의 문법의 변화

    Objective-C의 상수는 이제 Swift 타입이다.
    이제 Objective-C inter-op 식의 문자열을 사용할 수 없다.

    굳이 걱정하지 않을 정도로 작은 것
    NSError의 Bridging이 강화되었다.

    nulTerminatedUTF8CString이 utf8CString으로 이름이 바뀜

    문자열의 UnicodeScalar 생성자 중복을 제거

    실패할 수 있는 UnicodeScalar 생성자는 이제 옵셔널을 반환한다.

    더이상 튜플 splatting이 안된다.

    더이상 curry한 func 선언 문법이 안된다.

    이 모든 변화가 Swift3에서 일나날까?
    아니다.

    아직 이번 배포를 위해 검토하는 계획 안이다.(옮긴이: Swift3은 16.9.13에 정식 배포가 되었는데, 이 글은 16.8.31에 쓰여졌다)  몇 계획은 Swift3.x에서 달라질 것이고, 우리가 일반적으로 사용하지 않는 API 호출의 제거/병합과 같은 아주 마이너한 변화들은 포함시키지 않았다. 

    추가로 나는 이 개별적인 변화를 깊게 볼 필요가 없었으며, 대신 각 변화에대한 높은 수준에서 개괄적인 설명을 하였다. 몇 변화는 그 영역에서 파급표과를 가지고 있으며, 여러분이 이러한 변화에 관심이 있으면 Swift EVO project를 한번 방문해 보아라.

    이번 배포에서 검토 진행/대기중인 변화들
    1. Sequence-기반 생성자를 추가하고 Dictionary에 메소드를 합친다.
    2. 약 참조(weak reference)에서 강 참조(strong reference)로 self를 업그레이드하여 옵셔널 바인딩을 사용할 수 있게 해준다.
    3. 표준 라이브러리에 AnyHashable을 추가한다.

    3.x 배포에서 바뀐것들
    1. 순환 알고리즘
    2. .self 제거
    3. 커스텀 Objective-C 표현을 제공하는 것을 Swift 타입에서 허용
    4. 동적 케스터로부터 연결 변환 동작을 제거
    5. Sequence end-operation 이름을 합리화

    보너스
    제거되어서 우리 모두가 기쁜 것들

    1. Swift 언어에서 where문 제거
    2. 인스턴스 맴버를 접근하기 위해 self가 필요함
    3. extension에서 접근 변경자 제거



    WRITTEN BY
    tucan.dev
    개인 iOS 개발, tucan9389

    ,