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