Swifter {Swift Developer}

메뉴

Swift 2.x기반 프로젝트를 Swift 3.0으로 마이그레이션한 경험 정리

Xcode 7기반의 Swift 2.x기반 기존 프로젝트를 Xcode 8기반의 Swift 3.0으로 마이그레이션한 경험을 정리한 것이다.

마이그레이션 순서

어떤 일이라도 처음이 중요하기 때문에 다음과 같은 순서로 진행된다고 보면 될 것 같다.

  1. 팀원 중 누군가가 Swift 3.0으로 진행하자고 이야기한다.
  2. 사용하는 외부 라이브러리들이 업데이트
  3. Xcode에서 “Covert to Current Swift Syntax”에서 [Swift 3]으로 변환하도록 한다.
  4. 변환후 오류를 수정하거나 변환되지 않은 부분 중 외부 라이브러리관련 업데이트를 진행한다
  5. 동작 테스트 및 수정작업을 진행한다.

이런 흐름으로 진행되는데 가장 힘들었던 경우는 4번의 경우로 해당 프로젝트는 Swift 파일이 수백개정도라서 컴파일 오류를 수정하는 것이라서 간단했지만 이래저래 7일정도 소요되었다.

마이그레이션 하기 전에

속담에 “돌다리도 두들겨보고 건너자”라는 말이 있는 것처럼 아래 내용을 필히 확인하자.

라이브러리 호환성을 확인하자

Swift 기반의 외부 오픈소스 라이브러리를 이용한다면, 그것들이 Swift 3.0을 대응하는지 조사하지 않으면 안된다. 지원하지 않는 경우 해당 라이브러리가 지원할 때까지 기다리거나 다른 라이브러리르 찾아서 대응시켜야 한다. 필자는 거의 한달가량을 마이그레이션을 하기 전부터 관련 라이브러리들의 업데이트 상황을 수시로 점검하고 프로젝트에 사용중인 모든 라이브러리가 Swift 3.0을 대응할 때까지 기다렸다가 지원후에 마이그레이션을 진행했다.

또한, 사용하고 있는 라이브러리가 원래 오래된 버전이라면 Swift 2.2에서 실행되는지 동작 확인후 마이그레이션하는 것이 좋다. 크게 바뀌는 경우가 적지만 Swift 3.0을 지원함에 따라 이전과의 인터페이스가 변경될 수 있다.

변경 사항이 많은 경우, 문제가 발생한다면 마이그레이션에 영향을 주는지, 라이브러리 사용이 잘못된 것인지 알기 어렵기 때문에 분리하기 어렵다.

사전 테스트를 자주하자

나중에 이야기하겠지만 Xcode에서 변환한 코드가 완벽하지 않기 때문에 오류가 있을 수 있다. 직접 수정한 내용에 오류가 있는 것도 보통이다. 그럴 때마다 제대로 된 테스트를 하면 기계적인 오류를 발견하는데 수월하다.

사실 실무에서도 테스트를 자주 했기 때문에 로직 수정 실수를 최소로 하고 오류 발견을 바로 할 수 있어 테스트의 중요성을 다시 생각하게 했다.

마이그레이션을 시도하기

“어떤 프로젝트라도 끝은 있다”라는 마음가짐으로 진행하자.

Xcode의 구문 변환기

이전 프로젝트를 Xcode로 열면 새 문법으로 변환해준다.  Swift 3.0은 상당히 많은 변화가 있기 때문에 변환결과가 다양하다.

기본적으로 컴파일 오류가 무수히 계속 나올 수 있기 때문에 이를 모두 해결될 때까지 실행 테스트를 해보기는 어렵다. 오로지 수정을 하면서 테스트해보는 것이 주요 작업이다.

변환 누수로 “enum의 첫글자를 소문자로 변환되었지만 실제 이용부분에서는 변환되지 않는 패턴”을 말할수 있다. 이런 경우가 생각보다 많고 외부 라이브러리의 enum별로는 변환되지 않는 느낌이다.

변환 실수가 많지 않으면 잘못된 변환을 하게 되면 그것은 치명타로 올 수 있다. 귀찮지만 자동 변환된 내용을 여러 사람들과 확인하는 것도 제일 좋다. 아래 예제는 ReactiveCocoa코드로 작성된 부분중 next에 대한 처리가 없어졌다.

컴파일 오류 쉽게 수정하기

컴파일 오류 정말 다양하게 나온다. 단, 아래와 같은 빨간 컴파일 오류의 경우 클릭하면 바로 수정할 내용이 나와 편리 해준다.

xcode-error

이런 마크가 보이면 그냥 직접 수정하는 것을 추천하고 Xcode의 Editor메뉴에서 [Fix All in Scope]항목을 선택하면 빨간 아이콘 오류 표시 부분을 한번에 고쳐준다. 이게 상당히 편리하기 때문에 꼭  활용하자.

팀개발인 경우

혼자 개발하는 앱이라면 크게 신경쓸 일없이 진행하면서 오류를 수정해 갈 수 있지만, 팀단위로 여러명이 공동 작업을 한다면 다른 사람의 작업에 영향을 최소로 하지 않으면 안된다.

그래서 나름대로 정리한 방법은 아래와 같다.

  1. 주요 지점에서 직접 병합한다
  2. Xcode에서 변환한다.
  3. 변환 누수속에서 간단한 문자열 바꾸기로 변환해야 할 것들은 sed명령어로 대체규칙을 만들어 두자.
  4. 로직 수정이 필요한 것은 수정 및 자주 커밋한다
  5. 수정은 모두 정리된 후 동작 테스트 및 수정을 한다.

실무에서 필자는 5번째 단계까지 8일정도 소요되었다. 물론 그 진행하는 기간동안 팀원들끼리 병합하면 충돌이 나기 시작한다. 그래서 마이그레이션을 환료한 후 병합하는 방법은 정말로 끔찍하다.

그래서 주요 포인트에서 진행시 어느정도 정리된 곳은 반영하지 않으면 안된다.

  • 새로 브렌치를 기반으로 새 브렌치를 만든다.
  • Xcode에서 변환을 한다
  • 3번째에서 만든 sed치환을 적용한다.
  • 4번쨰에서 수정커밋 git cherry-pick을 반영한다

이런 형태로 작업을 진행했고 3번째를 만들거나 귀찮지만 주요 포인트에서 작업을 다시하는 경우 충돌이 발생하면 이를 최소화하기 위해 반복적으로 일을 진행했다.

sed 예제

swiftgen은 완벽하지 않다

swiftgen을 사용하고 있는데 이것은 이미지 파일명이나 스토리보드의 identifier 및 문자열로 취급하는 인수를 코드로 처리해준다. 보통 실무 프로젝트에서 스토리보드 기능에 사용하고 있다. swiftgen이 Swift 3.0을 지원한다고 하지만 swiftgen storyboards -t swift3 ~ 형태로 선언하면 Swift 3.0기반 소스코드를 생성해준다. 그렇지만 performSegue코드가 오버로드로 제대로 인식되지 않아 실행되지 않기 때문에 아래와 같은 익스텐션으로 확인해서 해결하기도 한다.

그외 이슈로는 Xcode 변환기 String형의 enum 문자열들은 소문자로 변환해주지 않는다는 것이다. 하지만 swiftgen으로 만드는 enum은 Swift 3.0스펙에 따라 소문자로 시작한다. 즉, Xcode는 swiftgen용 소스코드 performSegue(StoryboardSegue.PremiumService.WebView)형태의 WebView부분을 webView로 다시 만들어주지 않으면 안되지만 swiftgen은 바로 webView형태로 소스코드를 만들어주기 때문에 컴파일 오류가 많아지게 된다.

이런 불일치한 오류를 해결하기 위해 필자는 보통 컴파일 오류 수정이 될 때까지 extension을 추가해서 최대한 적게 나오도록 하고 swiftgen 사용을 잠시 접었다. 수정이 완료된 후 swiftgen -t swift3으로 처리해서 직접 enum수정을 했다. 다른 분의 경우 스크립트를 만들어 수정하는 경우도 있다.

Xcode8은?

이제 시작이다.

디버깅을 하면 로그가 너무 많았다.

Xcode8은 약간의 버그가 있어 로그가 상당량이 나온다. 이를 제한하는 방법은 이미 필자 블로그에도 소개했다.

Xcode8에서 시뮬레이터keychain을 사용할 수 없다

이것도 버그인데 Capabilities의 Keychain Sharing을 선택하면 해결된다.

 

Facebook Comments

카테고리:   Swift 3.0

댓글

죄송하지만 댓글은 닫혀 있습니다.