앱이 백그라운드에서 실행될 때마다 RAM과 같은 기기의 제한된 리소스를 사용합니다. 이로 인해 사용자 환경이 저하될 수 있으며, 특히 사용자가 게임 재생이나 동영상 시청과 같이 리소스를 많이 사용하는 앱을 사용하는 경우 더욱 그러할 수 있습니다. 사용자 환경을 개선하기 위해 Android 8.0(API 수준 26)은 앱이 백그라운드에서 실행되는 동안 할 수 있는 작업을 제한합니다. 이 문서에서는 운영체제의 변경사항과 새로운 제한사항에 따라 앱이 잘 작동하도록 업데이트하는 방법을 설명합니다.
개요
많은 수의 Android 앱과 서비스를 동시에 실행할 수 있습니다. 예를 들어 사용자가 한 창에서 게임을 플레이하면서 다른 창에서 웹을 탐색하고 세 번째 앱을 사용하여 음악을 재생할 수 있습니다. 한 번에 실행되는 앱이 많을수록 시스템에 더 많은 부하가 가해집니다. 추가 앱이나 서비스가 백그라운드에서 실행 중이면 시스템에 추가 부하가 발생하여 사용자 환경이 저하될 수 있습니다. 예를 들어 음악 앱이 갑자기 종료될 수 있습니다.
이러한 문제가 발생할 가능성을 줄이기 위해 Android 8.0에서는 사용자가 앱과 직접 상호작용하지 않을 때 앱에서 할 수 있는 작업을 제한합니다. 앱은 두 가지 방식으로 제한됩니다.
백그라운드 서비스 제한사항: 앱이 유휴 상태인 경우 백그라운드 서비스 사용이 제한됩니다. 이는 사용자에게 잘 보이는 포그라운드 서비스에는 적용되지 않습니다.
브로드캐스트 제한: 제한적인 경우를 제외하고 앱은 매니페스트를 사용하여 암시적 브로드캐스트에 등록할 수 없습니다. 개발자는 여전히 런타임에 이러한 브로드캐스트에 등록할 수 있으며 매니페스트를 사용하여 특정 앱을 대상으로 하는 명시적 브로드캐스트와 브로드캐스트에 등록할 수 있습니다.
대부분의 경우 앱은 JobScheduler
작업을 사용하여 이러한 제한사항을 해결할 수 있습니다. 이 접근 방식을 사용하면 앱이 활발하게 실행되지 않을 때 작업을 실행할 수 있지만 시스템은 사용자 환경에 영향을 미치지 않는 방식으로 이러한 작업을 예약할 수 있는 여지를 있습니다. Android 8.0은 서비스와 broadcast receiver를 예약된 작업으로 더 쉽게 바꿀 수 있도록 JobScheduler
에 관한 여러 개선사항을 제공합니다. 자세한 내용은 JobScheduler 개선사항을 참고하세요.
백그라운드 서비스 제한사항
백그라운드에서 실행되는 서비스는 기기 리소스를 사용할 수 있으므로 잠재적으로 사용자 환경이 악화될 수 있습니다. 이 문제를 완화하기 위해 시스템은 여러 가지 제한사항을 서비스에 적용합니다.
시스템은 포그라운드 앱과 백그라운드 앱을 구분합니다. (서비스 제한을 위한 백그라운드 정의는 메모리 관리에서 사용하는 정의와 다릅니다. 앱은 메모리 관리와 관련하여 백그라운드에 있지만 서비스를 실행하는 기능과 관련된 포그라운드에 있을 수 있습니다.) 다음 조건 중 하나라도 참일 경우 앱이 포그라운드에 있는 것으로 간주합니다.
- 액티비티가 시작되든 일시 중지되든 상관없이, 보이는 액티비티가 있는 경우
- 포그라운드 서비스가 있는 경우
- 앱의 서비스 중 하나에 바인딩하거나 앱의 콘텐츠 제공자 중 하나를 사용하여 앱에 또 다른 포그라운드 앱이 연결된 경우 예를 들어 다른 앱이 다음에 결합되면 앱이 포그라운드에 있는 것입니다.
- IME
- 배경화면 서비스
- 알림 리스너
- 음성 또는 텍스트 서비스
이러한 조건에 모두 해당하지 않으면 앱이 백그라운드에 있는 것으로 간주됩니다.
앱이 포그라운드에 있는 동안에는 포그라운드 및 백그라운드 서비스를 모두 자유롭게 만들고 실행할 수 있습니다. 앱이 백그라운드로 전환되면 몇 분 동안 계속 서비스를 만들고 사용할 수 있습니다. 이 기간이 끝나면 앱이 유휴 상태로 간주됩니다. 이때 시스템은 마치 앱이 서비스의 Service.stopSelf()
메서드를 호출한 것처럼 앱의 백그라운드 서비스를 중지합니다.
특정 상황에서는 백그라운드 앱이 몇 분 동안 임시 허용 목록에 배치됩니다. 앱이 허용 목록에 있는 동안 제한 없이 서비스를 실행할 수 있으며 백그라운드 서비스 실행이 허용됩니다. 앱은 사용자에게 표시되는 다음과 같은 작업을 처리할 때 허용 목록에 배치됩니다.
- 우선순위가 높은 Firebase 클라우드 메시징 (FCM) 메시지 처리
- SMS/MMS 메시지와 같은 브로드캐스트 수신
- 알림에서
PendingIntent
실행 - VPN 앱이 포그라운드로 승격되기 전에
VpnService
를 시작합니다.
대부분의 경우 앱은 백그라운드 서비스를 JobScheduler
작업으로 대체할 수 있습니다.
예를 들어 CoolPhotoApp은 포그라운드에서 실행되고 있지 않더라도 사용자가 친구로부터 공유 사진을 받았는지 확인해야 합니다. 이전에는 앱의 클라우드 스토리지를 통해 확인된 백그라운드 서비스를 앱에서 사용했습니다. Android 8.0 (API 수준 26)으로 이전하기 위해 개발자는 백그라운드 서비스를 예약된 작업으로 대체합니다. 이 작업은 주기적으로 실행되고 서버를 쿼리한 다음 종료됩니다.
Android 8.0 이전에는 포그라운드 서비스를 만드는 일반적인 방법은 백그라운드 서비스를 만든 다음 이 서비스를 포그라운드로 승급하는 것이었습니다.
Android 8.0에서는 좀 복잡하며, 시스템은 백그라운드 앱이 백그라운드 서비스를 생성하는 것을 허용하지 않습니다. 이러한 이유로 Android 8.0에는 포그라운드에서 새 서비스를 시작하는 새로운 startForegroundService()
메서드가 도입되었습니다. 시스템에서 서비스를 만든 후 5초 이내에 앱은 서비스의 [startForeground()
](/reference/android/app/Service#startForeground(int, android.app.Notification) 메서드를 호출하여 사용자에게 표시되는 새 서비스의 알림을 표시해야 합니다. 앱이 제한 시간 내에 startForeground()
를 호출하지 않으면 시스템이 서비스를 중지하고 앱을 ANR로 선언합니다.
브로드캐스트 제한사항
앱이 브로드캐스트를 수신하도록 등록하면 앱의 수신기는 브로드캐스트가 전송될 때마다 리소스를 사용합니다. 이는 너무 많은 앱이 시스템 이벤트에 기반한 브로드캐스트를 수신하도록 등록하면 문제를 일으킬 수 있습니다. 브로드캐스트를 트리거하는 시스템 이벤트로 인해 이러한 모든 앱이 빠르게 연속해서 리소스를 소비하여 사용자 환경이 저하될 수 있습니다. 이 문제를 완화하기 위해 Android 7.0 (API 수준 24)에서는 백그라운드 최적화에 설명된 대로 브로드캐스트를 제한했습니다. Android 8.0(API 레벨 26)은 이러한 제한을 더욱 강화했습니다.
- Android 8.0 이상을 타겟팅하는 앱은 브로드캐스트가 특별히 해당 앱으로 제한되지 않는 한 매니페스트에 암시적 브로드캐스트의 broadcast receiver를 더 이상 등록할 수 없습니다. 암시적 브로드캐스트는 앱 내의 특정 구성요소를 타겟팅하지 않는 브로드캐스트입니다. 예를 들어
ACTION_PACKAGE_REPLACED
는 모든 앱에서 등록된 모든 리스너로 전송되어 기기의 일부 패키지가 교체되었음을 알립니다. 브로드캐스트는 암시적이므로 Android 8.0 이상을 타겟팅하는 앱의 매니페스트에 등록된 수신기에는 전달되지 않습니다.ACTION_MY_PACKAGE_REPLACED
도 암시적 브로드캐스트이지만 패키지가 교체된 앱으로만 전송되므로 매니페스트에 등록된 수신기에 전달됩니다. - 앱은 자체 매니페스트에 있는 명시적 브로드캐스트에 계속해서 등록할 수 있습니다.
- 앱은 런타임에
Context.registerReceiver()
를 사용하여 암시적이든 명시적이든 모든 브로드캐스트의 수신기를 등록할 수 있습니다. - 서명 권한이 필요한 브로드캐스트는 이 제한에서 제외됩니다. 이러한 브로드캐스트는 기기의 모든 앱이 아닌 동일한 인증서로 서명된 앱으로 전송되기 때문입니다.
많은 경우 이전에 암시적 브로드캐스트에 등록된 앱은 JobScheduler
작업을 사용하여 유사한 기능을 가져올 수 있습니다.
예를 들어 소셜 사진 앱은 수시로 데이터를 정리해야 할 수 있으며 기기가 충전기에 연결되어 있을 때 이 작업을 실행하는 것이 좋습니다.
이전에는 앱이 매니페스트에 ACTION_POWER_CONNECTED
수신기를 등록했습니다. 앱이 이 브로드캐스트를 수신할 때 정리가 필요한지 확인했습니다. Android 8.0 이상으로 이전하기 위해 앱은 매니페스트에서 이 수신기를 삭제합니다. 대신 앱은 기기가 유휴 상태이고 충전 중일 때 실행되는 정리 작업을 예약합니다.
이전 가이드
기본적으로 이러한 변경사항은 Android 8.0 (API 수준 26) 이상을 타겟팅하는 앱에만 영향을 미칩니다. 그러나 앱이 API 수준 26 미만을 타겟팅하더라도 사용자는 설정 화면에서 모든 앱에 이러한 제한을 사용 설정할 수 있습니다. 새로운 제한사항을 준수하도록 앱을 업데이트해야 할 수도 있습니다.
앱에서 서비스가 어떻게 사용되는지 확인하세요. 앱이 유휴 상태일 때 백그라운드에서 실행되는 서비스를 사용하는 경우 서비스를 교체해야 합니다. 가능한 해결책은 다음과 같습니다.
- 앱이 백그라운드에 있는 동안 포그라운드 서비스를 만들어야 한다면
startService()
대신startForegroundService()
메서드를 사용하세요. - 서비스가 사용자에게 보이는 경우, 이 서비스를 포그라운드 서비스로 만듭니다. 예를 들어 오디오를 재생하는 서비스는 항상 포그라운드 서비스여야 합니다.
startService()
대신startForegroundService()
메서드를 사용하여 서비스를 만듭니다. - 서비스의 기능을 예약된 작업과 복제하는 방법을 찾습니다. 서비스가 사용자가 즉시 알아차릴 수 있는 작업을 하고 있지 않다면 일반적으로 예약된 작업을 대신 사용할 수 있어야 합니다.
- 네트워크 이벤트 발생 시 백그라운드에서 폴링하는 대신 FCM을 사용하여 선택적으로 애플리케이션의 절전 모드를 해제합니다.
- 애플리케이션이 자연스럽게 포그라운드가 될 때까지 백그라운드 작업을 연기합니다.
앱 매니페스트에 정의된 broadcast receiver를 검토합니다. 매니페스트에서 영향을 받는 암시적 브로드캐스트의 수신자를 선언하는 경우 이를 교체해야 합니다. 가능한 해결책은 다음과 같습니다.
- 매니페스트에 수신기를 선언하는 대신
Context.registerReceiver()
를 호출하여 런타임에 수신기를 만듭니다. - 예약된 작업을 사용하여 암시적 브로드캐스트를 트리거한 조건을 확인합니다.