원문 : medium.com/@mandrigin/ios-app-performance-instruments-beyond-48fe7b7cdf2?source=userActivityShare-d07a45aa48c6-1455001286
iOS 앱 퍼포먼스: Instrument와 그 이상
유저들은 기다리는걸 굉장히 싫어한다. 그들은 앱이 뭔가 초기화 한다는것을 전혀 모른 상태에서 자신들의 업무 처리를 최대한 빠르게 하고싶어한다. 그러므로 앱이 모두 즉각적으로 시작할 수 있다면 인터페이스가 물 흐르듯 부드럽게 넘어갈 수 있다. 퍼포먼스가 나오는 앱은 소프트웨어 마켓에서 경쟁력있는 특징중 하나이다. 개발자로서 앱이 퍼포먼스있게 잘 동작하게 하는것을 자랑스러워하는 것을 원하는것도 이유이다.
그러나 많은 이들이 겪듯 퍼포먼스 최적화는 꽤 다루기 어려운 문제이다. 대부분 문제를 직관적으로 접근하기 어렵다. 각기 잘 정리된 측정법 없이는 앱이 느려지는 이유를 알아내는건 매우 어렵다.
당신의 앱 퍼포먼스를 최적화하기 위해서는 데이터에 기반한 결론을 내려야한다. 이 장에서는 당신의 앱에 서로 다른 부분에서 퍼포먼스 측정 데이터를 어떻게 얻어낼 수 있는지 보여줄것이다.
이 파트에서는 아래의 것들을 다룰 것이다.
- 앱에서의 CPU, GPU, 메모리&베터리 사용량
- 반응성(리스폰시브니스)
- 앱시작동안의 시간
- 유저로부터 퍼포먼스 데이터를 얻는 법
바로 시작해보자!
CPU, GPU, 메모리&베터리 사용량
첫번째 할일은 CPU, GPU, 메모리를 과하게 사용하는 비효율적인 코드를 찾아내는 일이다. 애플은 이 일을 하기위한 좋은 툴(Instruments)을 제공한다.
우리가 주로 측정해야할 부분은 아래 4개 정도이다.
- CPU ("Time Profiler" 툴 이용)
- GPU (“Core Animation” 툴 이용)
- 메모리 사용량 (“Allocations” 툴 이용)
- 베터리 소모량 (“Energy diagnostics” 툴 이용)
WWDC 비디오는 당신 앱을 분석하기위한 최고의 정보를 제공한다.
아래는 시작하면서 몇 개 골라보았다:
반응성(Responsiveness)
퍼포먼스 측정(이해 "측정"으로 줄여서 말하겠습니다)에 있어서 다음으로 중요한 것은 UI의 반응성이다. 터치 헨들링은 메인 쓰레드에서 발생한다. 메인쓰레드에서 시간이 좀 걸리는 작업을 하면, 앱은 버벅거리게 될것이다.
몇몇 동작은 CPU를 사용하지 않는 주제에 시간을 잡아먹기도 한다. 만약 메인쓰레드에서 동기화 콜을 불렀다면, 이 콜이 얼마나 시간이 걸리는지 알아내는것이 문제를 해결하는 방법일것이다.
시간을 측정하기 위해 로그를 찍어볼 수도 있다.
한가지 더 다른 방법은 Viber의 개발자들이 만든 솔루션으로 나타내는 것이다. 이 솔루션은 메인 쓰레드 하나를 400ms보다 더 많이 멈추지 않게 지켜보고, 체크하는 특별한 스레드를 가지고있다.
Testing Responsiveness (from Viber’s presentation at NSSpain)
Testing Responsiveness (from Viber’s presentation at NSSpain)
더 많은 정보는 이 발표자료(PDF, 7MB)에서 확인할 수 있다.
이 데이터를 이용하여 너무 많은 시간이 걸린 콜(메인싸레드가 멈추는데에는 400ms정도가 적당한 최대치이며, 이 책을 보면 더 많은 정보를 얻을 수 있다.)을 찾아내고, 이것을 최적화 시킬지 메인쓰레드 밖으로 보내던지 해야한다.
시작 시간
다음으로 중요한 측정은 앱의 시작하는데 걸리는 시간이다. 전형적인 유저는 당신의 앱을 오직 몇분만 사용한다. 긴 시작시간은 앱의 이미지에 좋지않은 영향을 준다.
여기 앱 시작의 2가지 경우가 있다.
- Cold 시작 : 당신의 앱 프로세스가 동작하지 않고, OS에 의해 실행된다.
- Warm 시작 : 당신의 앱은 최소화되나 죽지않는다. 이것은 백그라운드로부터 다시 불러온다.
이 색션에서는 리소스를 많이 잡아먹는 Cold 시작에 초점을 맞출것이다.
아래에 iOS 앱의 시작 순서가 나와있다.
The Application Startup Phases (from the documentation)
1. 시작하는데 총 걸리는 시간을 측정한다.
우리는 main()에서부터 applicationDidBecomeActive:까지 시간이 얼마나 걸리는지 측정해야한다.
앱의 새 기능을 보여주면서 시간을 더 잡아먹게 하지 말아야한다. cold 시작 시간을 1초 미만으로 떨어뜨리려고 노력하는 것이 좋다.
2. 시작하는 순서에서 각 부분별로 측정한다.
보통 시작시간의 전체만 아는 것은 충분하지않다. 어떤 부분에서 시작시간을 느리게 만들었는지 아는것 또한 중요하다.
밑에 보이는 것들이 가장 중요한 부분들이다
- -[AppDelegate application:didFinishLaunchingWithOptions:] - 이 콜백은 런칭이미지(혹은 스토리보드)가 보여질때 호출된다. 곧바로 이 메소드로부터 return되면 실제 UI가 로딩을 시작한다.
- -[UIViewController loadView] - 앱에 커스텀 뷰를 불러와야한다면, 여기서 뷰를 초기화하게된다.
- -[UIViewController viewDidLoad] - 뷰가 불러와졌고, 마지막 초기화의 시간이다.
- -[AppDelegate applicationDidBecomeActivate:] - UI는 이미 초기화되어있지만, 이 콜백이 끝날때까지 블럭되있다. 이 메소드는 백그라운드로부터 restore될때 호출된다.
몇몇 매소드가 너무 시간이 많이 걸린다면, 최적화시켜야한다.
3. “under pressure” 시작 시간을 측정한다.
전형적으로 현실과 테스트 환경은 다르다는걸 알아야한다.
당신의 앱은 안타깝게도 "현실세계"에서 작동된다. 유저는 종종 다른 앱에서 당신의 앱을 열기도 한다. “다른 앱”은 굉장히 무거운 앱일 수도 있다. 당신의 앱이 시작될때 그 다른 무거운 앱은 백그라운드로 가면서 데이터를 저장하려고 할 수 있으며, 그런 상황에서의 시간 측정은 굉장히 중요하다.
그런 테스팅(무거운 다른 앱에서 내 앱을 열어보는)을 통해 예측하지 못한 결과를 만들 수도 있기 때문에, 이전에는 코드가 완벽하게 안정적이다가도, 저런 상황에서는 느려질 수도 있다는걸 명심해야한다.
4. 앱이 이미 시작되었지만 여전히 소용없다.(무슨 의미인지 모르겠습니다)
만약 당신 앱이 곧바로 UI를 불러오는것이 무의미한 일이라면, 런칭화면이 끝나지 않을 것이다. 비록 UI가 불러와지고 반응이 왔었어도, 불러오는데 준비를 위한 데이터가 필요하며, 또한 역시 시작 시간을 재어봐라.
당신의 유저로부터 측정값을 수집해야한다.
모든 측정은 테스트 환경에서 가능할 것이다. 그것은 반드시 필요하지만 너무 완벽하게까지 할필욘 없다. 만약 당신 앱이 인기있는 앱이라면, 만약 유저들이 해외시장을 기반으로 한다면, 몇몇 유저들은 당신이 예상하지 못한 아주다른 환경을 사용할 수도 있다.
추측하기에 다를 수 있는 환경들이다.
- 네트워크 상태
- 하드웨어
- 소프트웨어(OS 버전, Jailbreak(탈옥...)
- 기기의 남은 용량
- 기타 등등
분명 당신 개발실에서 측정한 것은 모두 안정적인 상태일지라도, 별점하나로 컴플레인("앱이 너무 느림ㅡㅡ") 리뷰를 받을 수도 있다. 어떻게 대처하면 될까?
퍼포먼스 측정의 집합을 정의하고(혹은 KPI) 실유저로부터 얻어와야한다. 이것은 대부분 통계 패키지와 함께 사용할 수 있다.
아래는 당신의 유저로부터 얻을 수 있는 KPI 예시들이다.
- cold 시작시간
- warm 시작시간
- 마디별 시작시간
- 반드시 서버로부터 다운받아야할 것들의 소요시간
- 메인쓰레드가 400ms보다 더 오래 블럭되는 수
- 메모리 워닝이 일어나는 수
- FOOMS(링크) 수
- UI가 블럭되거나 쓰잘때기없는 동작의 길이
결론
쉽게 설명하자면 퍼포먼스 측정은 Instruments.app 프로그램을 열면서 시작하며, 앞에서 본 것 말고도 다양한게 있다. 몇몇 소개된 방법은 구현하기 쉽지만 또 어떤건 시간과 노력이 필요할 것이다. 어쨋든 저 솔루션들은 당신의 앱 퍼포먼스 이슈를 찾고 해결을 위한 모니터링하는데 도움을 줌과 동시에 더 즐겁게 만들것이다.
별점5점 리뷰를 받기를 바란다!
+) 이해하면서 의역을 한 부분이 많이 있습니다. 잘못 이해한 부분이 있다면 지적해주시면 감사합니다.