Android Background Task Specialist
Android 백그라운드 실행 전문가: WorkManager, Foreground Service, Doze 모드 처리, 배터리 효율적인 프로세싱에 대한 전문 지식을 제공합니다.
활성화 트리거
다음에서 활성화: "WorkManager", "background task Android", "Foreground Service", "Doze mode", "battery optimization", "periodic work", "background sync", "JobScheduler", "background processing Android"
다음에서는 사용하지 마세요: iOS 백그라운드 태스크 → swiftui-data-flow-expert | React Native 백그라운드 → mobile-offline-sync-architect | UI 아키텍처 → jetpack-compose-navigation-expert
빠른 시작
- 올바른 API 선택 — 지연 가능한 작업에는 WorkManager, 사용자에게 보이는 지속적 작업에는 Foreground Service, 짧은 비동기 작업에는 코루틴 사용
- 워커 정의 —
CoroutineWorker를 확장하고suspend함수를 사용하여 깔끔한 비동기 코드 작성 - 제약 조건 구성 — 네트워크 유형, 배터리 수준, 저장 공간 요구사항 설정
- Doze 및 App Standby 처리 — Doze 호환 스케줄링을 위해 AlarmManager 대신 WorkManager 사용
- adb로 테스트 — Doze 모드를 강제하고 제약 조건 충족 시 작업이 실행되는지 확인
핵심 기능
| 도메인 | 기술 |
|---|---|
| 지연 가능한 작업 | WorkManager 2.10, OneTimeWorkRequest, PeriodicWorkRequest |
| 포그라운드 | Foreground Service 유형 (dataSync, location, mediaPlayback, shortService) |
| 제약 조건 | NetworkType, BatteryNotLow, StorageNotLow, DeviceIdle |
| 체이닝 | WorkContinuation, 병렬 체인, 고유 작업 정책 |
| 테스팅 | TestWorkerBuilder, TestListenableWorkerBuilder, WorkManagerTestInitHelper |
아키텍처 패턴
WorkManager 결정 트리
작업이 사용자에 의해 시작되었고 완료되어야 하는가?
├─ 예 → 10분 미만인가?
│ ├─ 예 → Foreground Service (shortService 유형)
│ └─ 아니오 → Foreground Service (dataSync, location 등)
│
└─ 아니오 → 지연 가능한가?
├─ 예 → WorkManager
│ ├─ 일회성? → OneTimeWorkRequest
│ └─ 주기적? → PeriodicWorkRequest (최소 15분 간격)
│
└─ 아니오 → 앱이 화면에 보이는 동안인가?
├─ 예 → CoroutineScope (viewModelScope 또는 lifecycleScope)
└─ 아니오 → 아마도 WorkManager를 사용해야 함
재시도 및 진행률을 포함한 CoroutineWorker
@HiltWorker
class SyncWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted params: WorkerParameters,
private val syncRepository: SyncRepository,
private val notificationHelper: NotificationHelper,
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
// UI 관찰을 위한 진행률 보고
setProgress(workDataOf("progress" to 0))
return try {
val pendingItems = syncRepository.getPendingChanges()
pendingItems.forEachIndexed { index, item ->
syncRepository.syncItem(item)
setProgress(workDataOf(
"progress" to ((index + 1) * 100 / pendingItems.size)
))
}
Result.success(workDataOf("synced" to pendingItems.size))
} catch (e: IOException) {
if (runAttemptCount < 3) {
Result.retry() // 기본적으로 지수 백오프 적용
} else {
Result.failure(workDataOf("error" to e.message))
}
}
}
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(
NOTIFICATION_ID,
notificationHelper.createSyncNotification()
)
}
}
제약 조건 및 체이닝을 포함한 스케줄링
// 1시간마다 주기적 동기화 스케줄링 (최소 15분)
val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(1, TimeUnit.HOURS)
.setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
)
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL,
WorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS
)
.addTag("sync")
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"periodic-sync",
ExistingPeriodicWorkPolicy.KEEP, // 이미 스케줄링되어 있으면 다시 시작하지 않음
syncRequest
)
// 체인: 다운로드 → 처리 → 업로드 (순차적)
WorkManager.getInstance(context)
.beginWith(downloadWork)
.then(processWork)
.then(uploadWork)
.enqueue()
안티 패턴
- 지연 가능한 작업에 AlarmManager 사용 — AlarmManager 알람은 Doze 호환되지 않으며 배터리를 소모합니다. Doze, App Standby, 배터리 세이버를 존중하는 WorkManager를 사용하세요.
- 포그라운드 알림 없이 백그라운드 서비스 실행 — Android 12+는 백그라운드 서비스를 종료합니다. 적절한 유형 선언과 함께 Foreground Service를 사용하거나 WorkManager를 사용하세요.
- 15분 미만의 PeriodicWork — WorkManager는 최소 15분 간격을 강제합니다. 더 자주 실행해야 하는 작업은 Foreground Service 또는 생명주기를 인식하는 코루틴을 사용하세요.
- Foreground Service 유형 선언 누락 — Android 14+는 manifest에
foregroundServiceType을 명시적으로 선언해야 합니다. 생략하면SecurityException이 발생합니다. - 작업 관찰 무시 — 작업을 시작만 하고 사용자에게 진행률을 보여주지 않는 경우.
getWorkInfoByIdLiveData()또는getWorkInfoByIdFlow()를 통해WorkInfo를 관찰하여 UI를 업데이트하세요.
품질 체크리스트
[ ] 지연 가능한 백그라운드 작업에 WorkManager 사용 (AlarmManager 아님)
[ ] Foreground Service가 AndroidManifest에 올바른 유형으로 선언됨
[ ] 제약 조건 구성 (네트워크, 배터리, 저장소)
[ ] 일시적 실패에 대한 백오프 재시도 정책 설정
[ ] 주기적/일회성 작업에 대한 고유 작업 정책 설정
[ ] 작업 진행률이 UI에서 관찰 가능함
[ ] Doze 모드 adb 테스트: `adb shell dumpsys deviceidle force-idle`
[ ] 배터리 최적화 테스트: `adb shell am set-inactive <package> true`
[ ] TestWorkerBuilder로 워커 테스트 완료
[ ] Foreground Service 알림용 알림 채널 생성됨
[ ] 작업 체인이 부분적 실패를 우아하게 처리함
[ ] 백그라운드 작업이 사용자의 배터리 세이버 선호도를 존중함