1. 서론
API 버전이 마시멜로우인 23이상부터 Doze모드와 AppStand by의 개념이 도입되었습니다. 안드로이드 앱을 개발하는 개발자라면, Doze모드와 AppStand by를 대처해야한다는 말을 들어봤을 것입니다. 그리고 이를 실제로 대응하면서, 껄끄러웠던 경험이 있었을 것이라고 생각합니다. 필자도 '백그라운드에서 시간을 체크하는 작업', '백그라운드에서 네트워크 통신을 하는 작업'등을 경험을 해봤고, 이번에 'FCM에서 네트워크 통신을 사용'하는 경험을 통해서 Doze모드와 각종 백그라운드 정책에 직면을 했습니다. 그래서 이번 포스팅을 통해서 안드로이드의 백그라운드 제한 작업에 함께 알아보려고 합니다.
2. Doze 모드 (Android 6.0)
Doze 모드는 충전기 연결이 되지 않은 배터리 동작이고 화면이 꺼진 상태로 움직임이 없는 경우가 일정 시간 이상 지속(기준 시간은 제조사마다 다르다고 합니다) 되는 경우 진행됩니다.
즉, Doze 모드는 '기기를 오래동안 사용하지 않은 경우 앱의 백그라운드 CPU 및 네트워크 활동을 지연시켜 배터리를 절약하는 목적을 갖고 있는 기능이 제공됩니다. 그래서 위의 그림과 같이 screen off, stationary on battery가 특정시간 동안 진행되면, Doze 모드로 진입이 되어 네트워크 및 백그라운드 작업에 제한이 생깁니다. 이러한 제한은 maintanance window의 시점에서야 일괄적으로 처리됩니다.
그래서, Doze 모드는 아래와 같은 조건일 때 발생합니다.
- 기기가 움직이지 않고, 스크린이 특정시간 꺼져 있을 때
- 기기에 전원공급이 없을 때
2-1. Doze 모드에서 발생하는 일들
Doze 모드에 진입하게 되면, 아래와 같은 일들이 발생하게 됩니다.
- 네트워크 액세스가 정지됩니다.
- 시스템에서 wake lock을 무시합니다.
- 표준 AlarmManager 경보(setExact() 및 setWindow() 포함)가 다음 maintenance window로 지연됩니다.
- 시스템에서 Wi-Fi 검색을 수행하지 않습니다.
- 시스템에서 동기화 어댑터 실행을 허용하지 않습니다.
- 시스템에서 JobScheduler 실행을 허용하지 않습니다.
3. Doze의 변화 (Android 7.0)
Android 7.0 SDK로 변화하면서, Doze 모드 또한 더 체계적으로 변하게 됩니다. 우선, 이전의 Doze 모드에서는 '디바이스가 움직이지 않는다면'이라는 전제조건이 붙으면서, 사용자가 걷거나 하는 경우에는 Doze모드로 진입하지 못 했습니다. 가장 먼저 변한 것은 사용자가 움직이더라도 사용자가 기기의 플러그를 뽑고, 화면이 꺼져 있는 동안 Doze 모드에 진입할 수 있다는 점입니다.
그리고, 이제 Doze 모드는 2단계에 걸쳐서 실행됩니다. 이것을 Light-Doze 모드, Deep-Doze 모드로 분리해서 부릅니다. Light-Doze 모드는 maintenance window가 잦게 실행되지만, 네트워크의 통신과 싱크, Job 작업들이 지연되게 됩니다.
그리고, Deep-Doze 모드에 진입하게 되면, 이전의 Doze 모드와 같이 알람, 네트워크의 통신, 싱크, Job 작업들이 지연되며, GPS, Wi-fi Scans, 네트워크 통신이 제한됩니다.
(Maintenance window: Doze 모드 중에도 필요한 작업(예: 네트워크 요청, 데이터 동기화, 백그라운드 작업 등)을 할 수 있도록 잠시 기기를 깨어나게 하는 시간 )
3-1. 제한 상황
Setting | Job | Alarm | Network | FCM |
Doze Active | 다음 maintaince window | 일반 알람: 다음 maintaince window 유휴 상태 중 알람: 최대 9분 연기됨 |
다음 maintaince window | High Priority : 제한 없음 Normal Priority : 다음 maintaince window |
4. AppStand by의 목적 (Android 6.0)
AppStand by는 최근 사용자와 상호작용이 없는 앱의 백그라운드 네트워크 활동을 지연시킵니다. 아래의 경우가 모두 포함되지 않는다면, 해당 앱은 AppStand by 상태로 빠지게 됩니다.
- 사용자가 명시적으로 앱을 실행합니다.
- 앱 프로세스가 현재 포그라운드에 있습니다(활동 또는 포그라운드 서비스로 있거나 다른 활동 또는 포그라운드 서비스에 사용되고 있음).
- 사용자가 잠금 화면이나 알림 목록에서 볼 수 있는 알림을 앱에서 생성합니다.
- 앱이 활성 기기 관리 앱(예: 기기 정책 컨트롤러)입니다. 이러한 앱은 일반적으로 백그라운드에서 실행되지만 기기 관리 앱은 언제든 서버에서 정책을 수신할 수 있게 유지되어야 하므로 앱 대기 모드를 시작하지 않습니다.
만약, 디바이스가 오랜 시간동안 AppStand by 상태가 된다면, 앱은 하루에 한 번 maintenance window를 획득하게 됩니다. 그리고, 디바이스가 충전되게 된다면, AppStand by 상태에서 해제되어 미뤄진 작업들을 처리하게 됩니다.
5. Background Limits (Oreo)
Oreo에 진입하면서, 각종 백그라운드 작업들이 제한이 되었습니다. 우리가 흔히 알고 있는 Service, Broadcast, GPS 작업 등을 다루고 있습니다. 백그라운드 작업들은 기기의 제한된 리소스(RAM)을 사용합니다. 이러한 경우에, 사용자의 리소스를 소모하게 되는데, Oreo에서는 이러한 점을 제한하고, 리소스를 관리하기 위한 제한이 추가됩니다.
6. App Standby buckets
pie 버전에서는 App Standby bukets이 추가되었습니다. 앱의 상태를 다섯가지로 구분지어 최근에 얼마나 자주 사용되었는가를 기준으로 실행시키게 됩니다. Active, WorkingSet, Frequent, Rare, Never의 상태로 나누어서 5가지로 구분을 하고, 해당 상태에 따라서, FCM, Network, Alarm, Job등 각자의 기능들을 지연시키거나 제한합니다. 해당 기준은 안드로이드의 알고리즘을 통해서 머신러닝이 구분짓는다고 합니다.
상태 | Job | Alarm | Network | FCM |
Active | 제한 없음 | 제한 없음 | 제한 없음 | 제한 없음 |
Working Set | 2시간 지연 | 6분 지연 | 제한 없음 | 제한 없음 |
Frequent | 8시간 지연 | 20분 지연 | 제한 없음 | 1일 : Priority high 기준으로 10회 |
Rare | 24시간 지연 | 2시간 지연 | 24시간 지연 | 1일 : Priority high 기준으로 5회 |
Never | 제한 | 제한 | 제한 | 제한 |
이와 같이 App Standby Bucket에 의해서 각자 다른 제한사항이 있다는 것을 알 수 있습니다.
7. App Restrictions & Battery Saver
그림5. 배터리 절약 모드
Job | Alarm | Network | FCM | GPS | 비고 | |
App Restrictions | 제한 | 제한 | 제한 | 제한 | 제한 | |
Battery Saver | 제한 | 제한 | 제한 | 가능 | 스크린 off 동안 | Foreground에서는 가능 |
안드로이드에서는 배터리가 없을 때, 배터리를 아끼기 위해서 자동으로 App Restrictions 모드를 활성화 시킵니다. App Restrictions 모드는 우리가 흔히 알고 있는 '절전 모드' 이며 백그라운드일 때, Job, Alarm, Network, FCM, GPS 모두를 제한하게 됩니다.
그리고, Battery Saver는 안드로이드 Pie에서 제공하고 있는 기능으로, Forground의 기능은 모두 가능하지만,
Job, Alarm, FCM, Network가 제한되고, 스크린이 꺼져있는 동안 GPS가 제한되게 됩니다.
8. 각자 다른 제한사항에서 대처 방법
여기까지 글을 읽었다면 도즈모드, 백그라운드 서비스, App Standby Buckets와 같은 다양한 배터리 관리 사항들이 생겼다는 것을 공감할 수 있을 것입니다. 그렇다면, 우리들은 이런 제한을 대응하기 위해서 어떻게 해야할 지, 고민을 해야하겠는데 https://youtu.be/-7eZL3XRqas 해당 영상에서 이에 대한 해답을 명확하게 제시해주고 있습니다. 그래서, 이에 대해서 명확하게 개념을 얻기 위해서는 꼭 2번씩 영상을 보고 이해 하셨으면 좋겠습니다.
8-1. 제한 상황
계속해서, 각종 제한 사항에서는 충전중이지 않은 상태일 때, Network, GPS, FCM, Alarm과 같이 디바이스가 백그라운드에서 작업을 처리하는 행위들을 제한하고 있다는 사실을 이야기하고 있습니다.
-Alarm의 실행 로직
알람의 백그라운드 로직
- FCM의 실행 로직
FCM의 백그라운드 로직
- Job의 실행 로직
Job의 백그라운드 로직
8-2. 백그라운드 작업은 WorkManager와 함께
해당 글에서는 WorkManager까지 다루지는 않을 것이다. 하지만, 각종 백그라운드 제한 사항이 생김에 따라서, 고려해야할 사항이 많은데 그럴 때 손 쉽게 해결할 수 있는 해결책 중 하나는 WorkManager이다. 또한 모든 것의 정답은 WorkManager는 아니다. 아래와 같은 상황 때, WorkManager를 사용하게 되면 손 쉽게 해결 할 수 있다.
9. 배터리 최적화 대응하기
앞서 설명한 도즈와 어플 대기모드가 어플의 기능 수행에 영향을 미칠 때 대응할 수 있는 방법입니다. 크게 4가지 방법이 존재하며 각 방법마다 사용이 가능한 어플의 종류가 달라질 수 있습니다. 각 방법에 대한 내용과 특징에 대해 정리하면 아래의 표와 같습니다.
방법
|
내용
|
특징
|
화이트 리스트 등록
|
도즈와 어플 대기모드의 대상으로부터 제외되는 화이트 리스트에 등록합니다.
|
채팅, 메시지 앱 등 특정 조건의 앱만 등록이 가능합니다. 해당 조건이 아닐 때 화이트 리스트 등록을 요청하는 경우에는 구글 플레이 스토어에 어플 등록이 안되는 경우가 발생합니다.
|
알람 매니저 활용
|
특정 기능을 수행하도록 알람을 설정해 어플 혹은 스마트폰을 깨웁니다.
|
알람 매니저에서 사용하는 API에 따라 해당 어플만 깨울 수도 있으며 기기 자체를 도즈 상태에서 벗어나게 할 수도 있습니다. 도즈를 깨우는 알람은 배터리 효율을 방해하기 때문에 추천하지 않는다고 합니다.
|
FCM 활용
|
Firebase의 푸시 메시지를 활용해 어플에게 메시지를 전송합니다.
|
도즈는 유지되고 해당 어플만 잠깐 도즈에서 벗어나 메시지를 수신합니다. 푸시 메시지의 priority를 high-priority로 설정해야 합니다.
|
Foreground Service 활용
|
Foreground service를 사용해 service가 계속 진행되도록 합니다.
|
구글 개발자 문서에서는 공식적으로 언급하지 않은 방법입니다. Foregound service의 형태를 사용하는 경우 상태 메시지에 나타납니다.
|
1. 화이트 리스트(Whitelist) 등록
구글은 배터리 효율 정책에서 기본적으로 전체 어플을 대상으로 진행하고 이 중 필요한 어플을 제외하는 형태인 화이트 리스트 방식을 사용했습니다. 사용자마다 어플의 수도 다르고 배터리 효율을 최대화하고자 이러한 방식을 사용한 것으로 생각됩니다. 기본 어플 및 몇 가지 어플들을 제외하고는 화이트 리스트에 등록되어 있지 않기 때문에 도즈 및 어플 대기모드로부터 자유롭고자 하는 어플은 화이트 리스트에 등록하는 과정이 필요합니다. 다이얼로그를 통해 화이트 리스트 등록 화면에 접근하도록 하여 사용자에게 직접 등록을 시킬 수도 있으며 Manifest에 등록하여 권한 형태로 획득할 수도 있습니다.
2. 알람 매니저(Alarm Manager) 활용
화이트 리스트 등록 대상이 아니지만 도즈 및 대기모드에서 특정 기능을 수행해야 하는 경우에는 알람 매니저를 활용할 수 있습니다. 알람 매니저를 통해 특정 시간대에 어플을 깨워 기능을 수행하도록 설정합니다. 이때 알람 매니저의 setExact()로는 도즈 및 대기모드에서 깨우는 것이 안 되고 maintenance window로 넘어가게 됩니다. 사용 가능한 알람 매니저의 종류와 특징에 대한 설명을 다음과 같습니다.
API
|
특징
|
setAndAllowWhileIdle()
setExactAndAllowWhileIdle() |
도즈 상태는 유지되고 해당 어플만 도즈에서 잠깐(10초 정도) 깨어납니다. 나머지 어플들은 도즈 상태에 있습니다. 구글 개발자 문서 상에서는 해당 API를 통한 알람은 어플마다 9분에 한 번씩만 사용이 가능하다고 명시되어 있습니다. 갤럭시 S7(SM-G930S)으로 테스트해본 결과 10분에 한 번씩 울리도록 설정해도 가끔 입력한 시간보다 밀려서 알람이 울리는 경우가 발생합니다.
|
setAlarmClock()
|
도즈 상태에서 벗어납니다. 이는 해당 어플뿐만 아니라 나머지 어플들까지 도즈 상태에서 벗어나게 됩니다. 구글 개발자 문서 상에서는 알람이 울리기 바로 전에 도즈에서 벗어나도록 한다고 명시되어 있습니다. 갤럭시 S7(SM-G930S)으로 테스트해본 결과 알람 등록 시 알람 등록 표시가 상태 메시지에 나타나며 알람은 정확하게 설정한 시간이 발생합니다.
|
3 FCM(Firebase Cloud Messaging) 활용
도즈 및 어플 대기모드에서는 네트워크 액세스가 제한되기 때문에 서버로부터 데이터를 받아오는 어플의 경우 문제가 발생할 수 있습니다. 이때 활용 가능한 방법인 FCM(Firebase Cloud Messaging)을 활용한 푸시입니다. FCM을 활용해 high-priority로 푸시를 보내게 되면 해당 어플은 도즈 및 어플 대기모드 상태에서도 푸시를 받을 수 있습니다. 일반적인 푸시는 normal-prioriy이기 때문에 반드시 high-priority로 설정을 해주어야 도즈 및 어플 대기모드에서도 받을 수 있습니다. FCM의 메시지 정보를 설정하는 방법은 아래의 사이트에서 확인할 수 있습니다.
4 Foreground Service 활용
구글 개발자 문서에서는 언급되어 있지 않지만 Foreground Service를 통해서도 도즈 및 어플 대기모드에 대응할 수 있습니다. Foreground Service를 유지하고 있는 동안에는 해당 서비스는 도즈 및 어플 대기모드에 의해 제한받지 않기 때문입니다. "포그라운드 서비스는 사용자가 능동적으로 인식하고 있으므로 메모리 부족 시에도 시스템이 중단할 후보로 고려되지 않는 서비스를 말합니다."라고 구글 개발자 문서에 언급된 것과 같은 방식으로 도즈 및 어플 대기모드 후보에 포함되지 않는 것으로 생각됩니다. Foreground Service의 경우에는 상태 표시줄에 알림이 나타나게 되며 가장 대표적인 Foreground Service는 음악 재생 플레이어입니다.
참고자료
https://gamjatwigim.tistory.com/116
Android 백그라운드 정책 톺아보기
1. 서론 API 버전이 마시멜로우인 23이상부터 Doze모드와 AppStand by의 개념이 도입되었습니다. 안드로이드 앱을 개발하는 개발자라면, Doze모드와 AppStand by를 대처해야한다는 말을 들어봤을 것입니다
gamjatwigim.tistory.com
https://blog.naver.com/nife0719/221029613969
[Android] 배터리 최적화 대응하기: 도즈(Doze)와 어플 대기모드(App Standby)
구글에서 안드로이드 마시멜로(6.0, SDK 23)부터 배터리 최적화와 ...
blog.naver.com
'Android > Background Task' 카테고리의 다른 글
[Android] WorkManager 사용법 (2) - 심화 (1) | 2024.11.16 |
---|---|
[Android] WorkManager 사용법 (1) - 기본 (0) | 2024.11.16 |
[Android] 안드로이드 백그라운드 작업 (2) - Task 종류 (0) | 2024.11.16 |
[Android] 안드로이드 백그라운드 작업 (1) - 개요 (1) | 2024.11.16 |