소피it블로그

[UIKit] 앱 백그라운드 실행 준비하기 - 공식 문서 번역 본문

개발_iOS/UIKit

[UIKit] 앱 백그라운드 실행 준비하기 - 공식 문서 번역

sophie_l 2022. 8. 12. 12:36

https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background

 

Apple Developer Documentation

 

developer.apple.com

1. 개요

 

앱은 다양한 이유로 백그라운드 상태로 전환된다. 유저가 포그라운드 앱에서 나가면 앱은 UIKit가 앱을 중지하기 전에 빠르게 백그라운드 상태로 옮겨진다. 시스템은 앱을 직접 백그라운드 상태로 론치할 수도 있고, 중지된 앱을 백그라운드로 옮긴 후 중요한 업무를 수행할 시간을 주기도 한다.

앱이 백그라운드에 있을 때에는 일을 최소한으로 해야 하며, 최선은 아무 것도 안 하는 것이다. 앱이 기존에 포그라운드에 있었다면 태스크를 중지하고 공유 자원을 반환시키기 위해 백그라운드 전환을 사용하라. 앱이 백그라운드에 진입해서 중요한 일을 처리하려고 한다면 해당 업무를 최대한 신속하게 끝내라.

모든 상태 전환의 결과로 UIKit는 적절한 delegate 객체에 알림을 보낸다.

 

  • iOS 13 및 그 이후: UISceneDelegate 객체
  • iOS 12 및 그 이전: UIApplicationDelegate 객체

delegate 객체의 두 가지 타입 전부 지원할 수 있지만 UIKit는 가능한 상황에선 항상 scene delegate 객체를 사용할 것이다. UIKit는 백그라운드에 진입하는 특정 씬에 관련된 scene delegate만을 부른다.

 

2. 비활성화에 맞춰 앱을 잠잠히 만들기

 

시스템은 앱을 다양한 이유로 비활성화한다. 유저가 포그라운드 앱을 벗어나면 시스템은 해당 앱을 백그라운드로 옮기기 직전에 비활성화한다. 또한 시스템은 일시적으로 앱을 중단시켜야 할 상황에 앱을 비활성화한다. 예를 들면 시스템 경고를 띄워야 할 경우가 그렇다. 시스템 패널의 경우 시스템은 유저가 패널을 해제할 때 앱을 재활성화한다.

비활성화 중에 UIKit는 다음과 같은 메서드를 호출한다:

 

  • scene을 지원하는 앱의 경우: 적절한 scene delegate 객체의 sceneWillResignActive(_:) 메서드
  • 그 외의 경우: app delegate 객체의
  • applicationWillResignActive(_:) 메서드

비활성화를 통해 유저의 데이터를 보존하고 주된 작업등을 중지함으로써 앱이 잠잠해지도록 하라. 구체적으로 말하면 다음과 같다:

 

  • 디스크에 유저 데이터를 저장하고 열려있는 파일을 닫는다.
  • dispatch와 operation queue들을 중지한다.
  • 새로운 작업을 실행하지 않는다.
  • 활성화되어있는 타이머의 효력을 중지한다.
  • 게임플레이를 자동으로 중지한다.
  • 새로운 Metal 작업이 처리되도록 커밋하지 않는다.
  • 새로운 OpenGL 커맨드를 커밋하지 않는다.

3. 백그라운드에 진입함에 따라 자원을 해제하기

 

앱이 백그라운드로 전환될 때 앱에 할당된 메모리를 해제하고 공유 자원을 비워라. 포그라운드에서 백그라운드로 전환하는 앱의 경우 메모리를 비우는 것이 특히 중요하다. 포그라운드는 메모리와 시스템 자원에 대한 우선권을 가지며, 시스템은 해당 자원들을 사용할 수 있게 하기 위해 필요한 경우 백그라운드 앱을 종료시킨다. 앱이 포그라운드에 있지 않았다고 해도 최소한의 자원만을 사용하는 게 맞는지 확인하라.

백그라운드에 진입함에 따라 UIKit는 다음과 같은 메서드를 호출한다.

 

  • 씬을 지원하는 앱들의 경우: 적절한 scene delegate 객체의 sceneDidEnterBackground(_:) 메서드
  • 이외의 경우: app delegate 객체의 applicationDidEnterBackground(_:) 메서드

백그라운드 전환 도중에는 다음의 태스크 중 앱에 필요한 항목들을 최대한 수행하라.

 

  • 파일에서 직접적으로 읽어들이는 이미지나 미디어를 버려라.
  • 생성하거나 디스크에서 다시 로드해올 수 있는 용량이 큰 in-memory 객체들을 버려라.
  • 카메라와 다른 공유 하드웨어 자원에 대한 접근을 해제하라.
  • 앱의 유저 인터페이스에서 패스워드와 같은 민감한 정보를 숨겨라.
  • 알러트와 다른 일시적인 인터페이스를 해제하라.
  • 공유된 시스템 데이터베이스와의 연결을 닫아라.
  • Bonjour 서비스에서 등록을 해제하고 이와 연관된 listening socket을 전부 닫아라.
  • Metal 커맨드 버퍼들이 스케쥴되어있다는 것을 확실히 하라.
  • 기존에 제출했던 OpenGL 커맨드들이 종료되었음을 확실히 하라.

앱의 asset catalog에서 가져온, 이름 있는 이미지들을 버릴 필요는 없다. 또한 NSDiscardableContent 프로토콜 수용하거나 NSCache 객체를 사용하여 관리하는 객체들을 해제할 필요도 없다. 이에 대한 처리는 시스템이 자동적으로 할 것이다.

앱이 백그라운드로 전환될 때 공유 시스템 자원을 차지하지 않는지를 확인하라. 앱이 백그라운드로 전환된 후에도 카메라나 공유 시스템 데이터베이스와 같은 자원에 접근하고 있다면 시스템이 해당 자원을 반환받기 위해 앱을 종료할 것이다. 자원에 접근하기 위해 시스템 프레임워크를 사용한다면 해당 프레임워크의 문서를 참조하라.

 

4. App Snapshot에 대해 UI 준비하기

 

앱이 백그라운드에 진입하고 delegate 메서드가 리턴하고 나면, UIKit는 앱의 현재 유저 인터페이스에 대한 스냅샷을 찍으며, 시스템은 해당 이미지를 앱 스위쳐에 띄운다. 또한 앱을 포그라운드로 가져올 때 임시로 그 이미지를 띄운다.

이때 앱의 UI는 패스워드나 신용카드 번호와 같은 민감한 유저 정보를 포함하면 안 된다. 인터페이스가 해당 정보들을 포함하고 있으면 백그라운드에 진입할 때 뷰에서 그 정보들을 제거하라. 또한 alert나 일시적인 인터페이스, 시스템 뷰 컨트롤러 등 앱의 내용을 흐리는 것들이 있으면 전부 해제하라. 스냅샷은 앱의 인터페이스를 나타내기 때문에 유저가 알아보기 쉬워야 한다. 앱이 포그라운드로 돌아올 때 다시 데이터를 복구하면 된다.

 

5. 백그라운드의 중요한 이벤트에 응답하기

 

앱은 보통 백그라운드에 진입한 후에는 추가적인 실행 시간을 부여받지 않는다. 그러나 UIKit는 다음과 같은 time-sensitive 기능들을 제공하는 앱에 대해서는 추가 실행 시간을 부여한다.

 

  • AirPlay를 통한 오디오 소통이나 Picture video에서의 Picture
  • 위치 민감 정보
  • Voice over IP
  • 외부 액세서리를 통한 소통
  • 블루투스 LE 액세서리를 통한 소통이나 디바이스를 블루투스 LE 액세서리로 변환하기
  • 서버로부터의 정기적인 업데이트
  • Apple Push Notification service(APNs)

앱이 백그라운드 기능을 지원한다면 Xcode에서 Background Modes 기능을 활성화하라. 각 백그라운드 태스크는 서로 다른 요구조건을 갖는다. 필요한 기능을 어떻게 구현하는지와 관련하여 적절한 프레임워크 디테일을 확인하라.