백그라운드 실행 제한

앱은 백그라운드에서 실행될 때마다 기기의 제한된 리소스(예: RAM)를 사용합니다. 이러한 경우 사용자 환경이 손상될 수 있으며, 사용자가 게임 재생이나 동영상 시청 등 리소스를 많이 사용하는 앱을 사용하는 경우 특히 그렇습니다. 사용자 환경을 개선하기 위해 Android 8.0(API 수준 26)에서는 앱이 백그라운드에서 실행되는 동안 할 수 있는 작업을 제한합니다. 이 문서에서는 운영체제의 변경사항과 새로운 제한사항에 따라 앱이 잘 작동하도록 업데이트하는 방법을 설명합니다.

개요

많은 수의 Android 앱과 서비스를 동시에 실행할 수 있습니다. 예를 들어 사용자가 한 창에서 게임을 하면서 다른 창에서 웹을 탐색하고 제3의 앱을 사용하여 음악을 재생할 수 있습니다. 동시에 실행되는 앱이 많을수록 시스템에 더 많은 부하가 발생합니다. 추가 앱 또는 서비스가 백그라운드에서 실행 중이면 시스템에 추가 부하가 발생하여 사용자 환경이 저하될 수 있습니다. 예를 들어 음악 앱이 갑자기 종료될 수 있습니다.

이러한 문제가 발생할 가능성을 줄이기 위해 Android 8.0은 사용자가 앱과 직접 상호작용하지 않을 때 앱에서 할 수 있는 작업을 제한합니다. 앱은 두 가지 방식으로 제한됩니다.

  • 백그라운드 서비스 제한: 앱이 유휴 상태인 경우 백그라운드 서비스 사용이 제한됩니다. 이는 사용자가 더 잘 알 수 있는 포그라운드 서비스에는 적용되지 않습니다.

  • 브로드캐스트 제한: 제한적인 예외를 제외하고 앱은 매니페스트를 사용하여 암시적 브로드캐스트에 등록할 수 없습니다. 계속해서 런타임에 이러한 브로드캐스트를 등록할 수 있으며 매니페스트를 사용하여 앱을 구체적으로 타겟팅하는 명시적 브로드캐스트와 브로드캐스트에 등록할 수 있습니다.

대부분의 경우 앱은 JobScheduler 작업을 사용하여 이러한 제한사항을 해결할 수 있습니다. 이 접근 방식을 사용하면 앱이 활발히 실행되지 않을 때 작업을 실행할 수 있지만, 여전히 사용자 환경에 영향을 미치지 않는 방식으로 이러한 작업을 예약할 수 있는 여지를 시스템이 확보할 수 있습니다. Android 8.0은 서비스 및 broadcast receiver를 예약된 작업으로 더 쉽게 바꿀 수 있도록 JobScheduler에 관한 여러 개선사항을 제공합니다. 자세한 내용은 JobScheduler 개선사항을 참고하세요.

백그라운드 서비스 제한사항

백그라운드에서 실행되는 서비스가 기기 리소스를 사용할 수 있으므로 사용자 환경이 저하될 수 있습니다. 이 문제를 완화하기 위해 시스템은 서비스에 여러 제한을 적용합니다.

시스템은 포그라운드 앱과 백그라운드 앱을 구분합니다. (서비스 제한 목적의 백그라운드 정의는 메모리 관리에서 사용하는 정의와는 다릅니다. 메모리 관리와 관련하여 앱은 백그라운드에 있을 수 있지만 서비스를 실행하는 기능은 포그라운드에 있을 수 있습니다.) 다음 조건 중 하나라도 참일 경우 앱이 포그라운드에 있는 것으로 간주합니다.

  • 액티비티가 시작되든 일시 중지되든 상관없이, 보이는 액티비티가 있는 경우
  • 포그라운드 서비스가 있는 경우
  • 앱의 서비스 중 하나에 바인딩하거나 앱의 콘텐츠 제공자 중 하나를 사용하여 앱에 또 다른 포그라운드 앱이 연결된 경우 예를 들어 다른 앱이 다음 항목에 바인딩되면 앱이 포그라운드에 있는 것입니다.
    • IME
    • 배경화면 서비스
    • 알림 리스너
    • 음성 또는 텍스트 서비스

위 조건에 모두 해당하지 않으면 앱이 백그라운드에 있는 것으로 간주됩니다.

앱이 포그라운드에 있는 동안에는 포그라운드와 백그라운드 서비스를 모두 자유롭게 만들고 실행할 수 있습니다. 앱이 백그라운드로 전환되면 몇 분 동안은 서비스를 만들고 사용할 수 있습니다. 이 기간이 끝나면 앱은 유휴 상태로 간주됩니다. 이때 시스템은 마치 앱이 서비스의 Service.stopSelf() 메서드를 호출한 것처럼 앱의 백그라운드 서비스를 중지합니다.

특정 상황에서는 백그라운드 앱이 몇 분 동안 임시 허용 목록에 배치됩니다. 앱이 허용 목록에 있는 동안 서비스를 제한 없이 실행할 수 있으며 백그라운드 서비스 실행이 허용됩니다. 앱은 사용자에게 표시되는 다음과 같은 작업을 처리할 때 허용 목록에 배치됩니다.

대부분의 경우 앱은 백그라운드 서비스를 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로 선언합니다.

브로드캐스트 제한사항

앱이 브로드캐스트를 수신하도록 등록한 경우 앱의 broadcast receiver는 브로드캐스트가 전송될 때마다 리소스를 사용합니다. 이로 인해 너무 많은 앱이 시스템 이벤트에 기반한 브로드캐스트를 수신하도록 등록하면 문제가 발생할 수 있습니다. 브로드캐스트를 트리거하는 시스템 이벤트로 인해 이러한 모든 앱이 빠르게 연속적으로 리소스를 소비하여 사용자 환경이 저하될 수 있습니다. 이 문제를 완화하기 위해 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()를 호출하여 런타임에 수신기를 만듭니다.
  • 예약된 작업을 사용하여 암시적 브로드캐스트를 트리거한 조건을 확인합니다.