Swift 컴파일 속도를 향상시키자

marojun
marojun's iOS
Published in
7 min readSep 21, 2017
이미지 출처 : https://developer.apple.com/xcode/

Nothing is perfect

스위프트는 멋진 모던 프로그래밍 언어중 하나이지만 사실 이런저런 문제를 가지고 있다. 특히 큰 프로젝트 운영 시 스위프트로 구성되어 있는 프로젝트를 컴파일해보면 시간이 굉장히 오래걸리는 것을 알 수 있다.

실제로 5~6 분정도 빌드를 기다리곤했는데 뭐 긍정적으로 생각해 보면 이건 개선할 여지를 가지고 있다는거다. 예전 안드로이드 스튜디오처럼..

사실 스위프트라는 좋은 언어를 가지고 컴파일하는데 하루 이틀 버리는건 굉장히 비생산적인 일이다. 부디 이번 글을 통해 극복(with Xcode 환경설정, 코딩 스타일) 해보도록 하자.

It’s optimization time!

도움이 되는 툴을 사용해보자

Build Time Analyzer for Xcode 라는 멋진 오픈소스 툴을 설치해보자. 프로젝트의 데이터를 분석해서 컴파일하는데 어떤 부분에서 얼마나 시간이 걸리는지 알려준다. 이를 통해 문제가 있는 부분을 손쉽게 발견하고 최적화 할 수 있으니 꼭 적용해 보도록 하자.

개인적으로 위 방법이 제대로 동작하지 않아 (로그를 찾을수 없다고 메시지가 계속 노출됨) http://irace.me/swift-profiling 해당 링크의 방법으로 진행했다.

Xcode improvements

코드를 보기전에 개발툴에서의 최적화 팁을 살펴보자.

a. 최적화 레벨을 조절하자.

Target — Build Setting 에서 Optimization Level의 디버그 항목을 None 으로 설정한다.

b. 빌드세팅의 User-Defined 항목으로 SWIFT_WHOLE_MODULE_OPTIMIZATION = YES 을 추가하도록한다.

중간에 보이는 “+” 버튼을 눌러서 항목을 추가하도록 한다.
추가완료!

경험상 이 플래그들이 컴파일시 큰 부분을 차지하는것을 알 수 있었으니 적용해보도록 하자.

해당 기능을 WMO라고 줄여서 부르기도 하는데 빌드시 모든 파일을 한번에 분석해 최적화 하는 방법을 말한다.

c. Remove dSYM file from Debug

dSYM (디버그 기호 파일)은 디버깅 정보를 가져 와서 dSYM 번들에 저장하는 파일이다. 이것은 프로젝트를 컴파일할때마다 생성되는데 디버깅시에는 DWARF 값이 변경되기때문에 사실상 필요가 없어 릴리즈 모드시에만 적용하도록한다.

d. Check your Build Active Architecture Only values

해당 메뉴는 말 그대로 빌드시 특정 아키텍처에 대해서만 빌드로 할지에 대한 여부를 결정하는 값이다. 릴리즈시에는 다양한 아키텍쳐를 지원해야 하므로 NO로 나머지 경우에 대해 전부 YES로 설정하자.

e. Empty your Derived Data

프로젝트를 만들때 문제가 발생한다면 이 부분부터 시작해야한다.

해당 폴더에 프로젝트 빌드의 결과 등이 저장되어 있다. 가끔 빌드가 꼬이면 해당폴더를 삭제시 잘 수행되는 경우가 있기에 첫 머리말을 이렇게 시작한것 같다. 참고로 첫번째로 소개했던 방법을 수행해 보신분들은 빌드시 생성되는 Derived Data 를 통해 컴파일 속도분석이 이루어 진다는 것을 알 것이다.

File -> Project Settings 에서 DerivedData 를 선택하면 해당 폴더에 접근이 가능한다. 이것을 삭제하도록 한다. 지워도 되나 싶을수 있지만 염려할 필요는 없다. 프로젝를 실행하면 다시 생성되기 때문이다. 잊지 말아야할 것은 데이터를 지우고 프로젝트를 클린해야한다는 것이다. (CMD+Shift+K)

여기까지는 엑스코드를 통해 컴파일하는데 시간을 절약하는 방법들에 대해 알아보았다. 이제부터는 코딩을 통해 컴파일 시간을 최적화 하는 방법을 알아보도록 한다.

이에앞서 http://theappspace.com/software-development-success-philosophy/ 는 읽어보기를 권장한다.

이제부터 소개하는 내용은 단순히 컴파일을 빨리하기 위해 코드의 간결성이나 가독성을 무시하는 방법을 보여주기도 한다. 이는 개발자 본인의 선택이니 필요에 따라 적용해보는것이 좋을듯 하다.

Swift improvements

Add type annotations

항상 변수에 타입을 지정하도록 한다. 이 방식을 통해 컴파일러는 어떠한 타입인지를 미리 알 수 있기때문에 읽는 속도를 절약할 수 있게된다. 예를 들어 다음과 같이 사용한다.

좋은예 : let array: [String] = [“a”, “b”, “c”, “d”, “e”, “f”, “g”]나쁜예 : let array = [“a”, “b”, “c”, “d”, “e”, “f”, “g”]

Avoid Nil-Coalescing operator

다른 큰 향상방법은 Nil-Coalescing operator 를 사용하지 않는것이다.

(한국에서는 Nil 병합 연산자로 불리우는 것 같다. 옵셔널 변수에 대해 Nil 인 상황에 대한 기본값을 ?? 과 함께 지정하는 방식 으로 보면된다. — https://outofbedlam.github.io/swift/2016/04/14/NilCoalescingOperator/ )

좋은예 : 
if let name = string{
/* string has value */
}else{
/* string is nil*/
}
나쁜예 : let name = string ?? “”

Avoid Ternary Conditional Operators

삼항연산자를 사용하지 말자.

좋은예 : 
var letter = “”
if isFirst{
letter = “a”
}else{
letter = “b”
}
나쁜예 : let letter = isFirst ? “a” : “b”

Don’t use + to concatenate a string

문자열을 합칠때 + 를 사용하는 것을 지양한다. 즉, 아래와 같이 사용하도록 한다.

좋은예 : let url = “https://google.com/\("path")/\("anotherpath")"나쁜예 : let url = “https://google.com/” + “path/” + “anotherpath”

Pre-Compute

조건문의 비교값에 연산을 넣지 않는다.

좋은예 : if number == 3600{}나쁜예 : if number == 60 * 60 {}

Conclusion

이번에 소개된 컴파일 속도 향상법이 생각보단 별로고 어떤 부분에서는 확신을 줄 수 없을수도 있지만

본인 프로젝트에 정의하지 않은 타입의 변수와 번잡하게 사용된 Nil 병합연산자의 갯수를 살펴보면 측정된 컴파일 지연 시간의 상관관계를 어렴풋이라도 느낄것이라 생각된다. 실제로 이를 수정해보면 많은 시간을 절약함을 깨닫게 될 것이다. 부디 이글을 통해 많은 분들이 컴파일 시간을 절약하고 그만큼 더 생산적인 일을 할 수 있기를 바란다.

이 글은 https://medium.com/theappspace/speed-up-swift-compile-time-6f62d86f85e6 을 인용하여 작성함을 밝힙니다.

--

--

marojun
marojun's iOS

전슬마로. KTH, SK Planet, NCSOFT 에서 iOS와 Android를 개발하고 있다. — 안드로이드 개발 그룹 https://www.facebook.com/groups/junsle/