Programming/Mac & iOS

[iOS] iOS 멀티태스킹 (Background Service 이용하는 법 : iOS7 이상)

MB Brad KWON 2014. 11. 24. 16:44


    iOS7부터 '멀티 태스킹'에 대해 강력한 지원을 해준다. Background의 세계가 열렸다. 사용자들이 Foreground에서 기다리던 시대는 지났다. 개발자들은 Background를 지원하며 사용자들이 지루하게 기다린 시간을 줄일 의무가 '자의 반, 타의 반'으로 부여됬다. 그럼, 멀티태스킹을 지원하기 위한 Background Service에 대해 알아보자.


** 아래의 기능들을 통해 완전히 종료된 앱을 실행상태로 만드는 것은 불가능하며, 메모리에 로드된 상태의 background에서만 실행을 보장한다.



    새로운 멀티 태스킹 API로는 3가지가 추가되었다. 3가지는 아래와 같다.


1. Background Fetch                                                주기적인 업데이트 사용할 때 사용

2. Remote Notification (Silent Push Notification)    때때로 업데이트를 하지만 자주 제공하진 않을 때 사용

3. Background Transfer Service (NSURLSession)    Background에서 30초 이상의 장시간 업데이트를 할 때 사용


    1, 2번은 일반적으로 OS에서 약 30초의 시간이 주어진다. 30초 안에 데이터를 업데이트 가능할 경우, 앞의 2가지만 사용하면 된다. 하지만 업데이트할 데이터의 양이나 파일의 크기가 커서 30초 이상의 작업시간이 소요될 경우, OS에서 Background Task를 죽이지 않게 하기 위해서 Background Transfer Service(이하 'BTS')를 사용한다.




1. Background Fetch


    iOS7 이전에는 앱이 실행될 때마다, 업데이트를 확인하고 다운로드 받는 과정을 거쳐야만 했다. 하지만 오랜 시간 앱을 실행하지 않은 상태에서 잦은 업데이트로 많은 업데이트들이 밀리고, 사용자가 앱을 실행할 때 네트워크 상태가 안 좋다면 사용자는 Foreground에서 앱을 끄지 못한 채, 기다리는 상황이 발생하게 된다. 이와 같이 잦은 업데이트가 발생하는 앱의 경우, Background Fetch를 사용하면 사용자에게 아~~~~주 쾌적한 환경을 제공해 줄 수 있다.


    기본적인 Fetch Interval은 'UIApplicationBackgroundFertchIntervalNever'로 설정되어 있어 Background Fetch를 실행하지 않는다. 일반적으로 Background Fetch Interval을 설정할 때는 'application:didFinishLaunchingWithOptions:'라는 AppDelegate method를 안에서 'setMinimumBackgroundFetchInterval:'이라는 method를 통하여 설정하게 된다. Fetch Interval은 OS에게 일임하는게 가장 좋은 방법이며 OS에게 일임하기 위해선 Fetch Interval을 'UIApplicationBackgroundFetchIntervalMinimum'으로 설정한다. 이렇게 설정할 경우, iOS에서 리소스의 사용 현황에 따라 임의로 Fetch하기 때문에 개발자가 원하는 간격으로 호출할 수는 없다. 만약에 개발자가 원하는 Fetch Imterval이 있다면 'NSTimeInterval' 타입의 값으로 정할 수 있다. 구체적인 사용법은 아래의 참고 링크를 확인하도록 한다.




2. Remote Notification (Silent Push Notification)


    앞에 설명했던 Background Fetch는 iOS에서 주기적으로 Fetch를 실행하는 방법으로 업데이트가 자주 일어나는 상황에서 유리하다. 하지만 업데이트가 자주 일어나지 않지만 계속해서 주기적으로 Fetch를 실행하게 된다면 엄청난 리소스의 손실을 초래하게되어 전반적인 사용자 경험을 해칠 수 있다. (물론, iOS가 30초 이상의 실행을 규제하기 때문에 엄청난 손실이 아닐 수도 있다. 하지만 1ms를 줄이고자 알고리즘을 계속해서 수정하는 진정한 개발자라면 30초라면 겁나게 큰 시간일거다.)


    작동 방식은 APNS와 비슷하다. 단지, 기존 APNS는 Push Notification을 수신함과 동시에 사용자에게 메시지를 표시하지만 Silent Push Notification은 수신하면 사용자에게 알리지 않고 앱을 조용히 Background에서 실행하게 된다. 앱은 개발자가 AppDelegate상에서 'application:didReceoveRemoteNotification:fetchCompeletionHandler:'에 정의된 로직을 수행하게 된다. 로직 수행이 완료되면 그 때, 사용자에게 업데이트가 완료됨 알리게 된다.


    그럼 iOS는 어떻게 일반 Push Notification과 Silent Push Notification을 구분할까? 간단하다. Notification Payload에 content-available의 값을 넣고 alert과 sound의 값을 넣어주지 않으면 된다. iOS는 이를 확인하고 개발자가 정의한 Background Task를 수행하게 될 것이다. 여기서 우리가 또 하나 명심해야할 것은 Background Fetch와 마찬가지로 Silent Push Notification도 최대 실행시간이 30초까지 밖에 보장이 안된다. 그 이상의 task를 수행하고 싶을 경우에는 BTS를 사용한다. Silent Push Notification의 자세한 사용법 역시 아래의 참고 링크에서 확인하면 된다.




3. Background Transfer Service (NSURLSession)


    Background Fetch와 Silent Push Notification은 앞서 말한바와 같이 30초의 제한을 두고 동작하기 때문에 커다란 컨텐츠 파일의 업로드/다운로드나 오랜 응답시간을 요하는 작업에는 적당하디 않다. 이를 위해 제공하는 아름다운 API가 있다. 아른바 BTS이다. BTS는 NSURLSession이라는 클래스를 사용하여 구현한다. NSURLSession은 업로드는 'NSURLSessionUploadTask'를 사용하고 다운로드는 'NSURLSessionDownloadTask'를 사용한다. 구체적인 사용법은 Apple API Document을 참고하면 된다. 하지만 다운로드 같은 경우에는 MBURLSessionDownload라는 아름다운 Open Source를 사용하면 된다. 사용법 또한 너무 직관적인 나머지 프로그래밍에서 'printf' 좀 찍어봤다는 디버깅도 할 줄 모르는 무능력 개발자들도 사용이 가능하다. MBURLSessionDownload에 관한 내용은 다음 글에서 확인이 가능하다.


    BTS를 사용함에 있어 Background Fetch와 Silent Push Notification을 사용하여 업데이트를 확인하는 과정을 거친다음에 BTS로 컨텐츠 업데이트 로직을 구현한다면 훨~~~~씬 더 아름다운 앱을 만들 수 있을 것이다.




Conclusion


    우리는 iOS7부터 제공되는 Background Service에 대해 알아봤다. 이를 활용하면 사용자의 대기시간을 줄이고 보다 편리한 앱의 업데이트를 구현할 수 있을 것이다. 물론, 아이폰의 배터리 라이프를 위해 Background Refresh를 꺼 놓은 경우도 있다. 하지만 최선의 앱 구현을 원하는 자아성취형 프로그래밍 전문가라면 이를 꼭 활용할 것임이 확실하다. 추가적으로 덧붙이자면 Background Service가 완료된후, Completion Handler를 꼭 호출하도록 하자. iOS는 Completion Handler의 호출을 기준으로 Background 앱이 다시 Sleep을 취할 수 있도록하기 때문이다. 앞의 1, 2번 방법에 경우 애초에 작동시간이 최대 30초로 제한이 되어는 있지만, 뒤에 설명드린 BTS는 무제한적으로 앱이 잠에 들지 못해 iOS를 피곤하게 만드는 상황을 만들 수 있기 때문이다. Completion Handler를 호출할 때, 사용하는 Parameter의 종류를 끝으로 이 글을 마무리한다.


1. UIBackgroundFetchResultNewData        새로 갱신할 데이터가 존재할 경우

2. UIBackgroundFetchResultNoData          새로 갱신할 데이터가 존재하지 않을 경우

3. UIBackgroundFetchResultFailed            갱신할 데이터의 확인이 실패했을 경우



참고 : http://code.tutsplus.com/tutorials/ios-7-sdk-multitasking-enhancements--mobile-20295