안드로이드 시스템·Compose 용어 사전
컴포넌트포그라운드 서비스 · Foreground Service · startForegroundService

Service

화면 없는 백그라운드 실행 컴포넌트. 최신 안드로이드에서는 강하게 제한된다.

화면 없이 도는 컴포넌트. 최신 안드로이드에서는 강하게 제한된다.

왜 제한되나

앱들이 백그라운드에서 마음대로 돌면 배터리가 녹고, 메모리가 부족해지고, 사용자는 이유를 모른다

Android 8.0(O) 부터

  • 앱이 백그라운드에 있을 때 일반 Service 를 시작할 수 없다
  • IllegalStateException

포그라운드 서비스 — 알림이 대가다

class PlayerService : Service() {
    override fun onStartCommand(i: Intent?, f: Int, id: Int): Int {
        startForeground(NOTIF_ID, buildNotification())   // ★ 5초 안에 불러야 한다
        return START_STICKY
    }
    override fun onBind(i: Intent?): IBinder? = null
}

startForeground 를 5초 안에 안 부르면 ANR 로 죽는다

사용자에게 지속 알림을 보여 주는 것이 '계속 돌아도 되는' 대가다

  • 음악 재생 · 내비게이션 · 운동 기록처럼 사용자가 인지하는 작업만 정당하다

Android 14부터 타입 선언이 강제된다

<service
    android:name=".PlayerService"
    android:foregroundServiceType="mediaPlayback" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

타입(mediaPlayback · location · dataSync · camera …) 을 선언하고 그에 맞는 권한도 받아야 한다 안 맞으면 실행 시점에 예외로 죽는다

대부분의 경우 Service가 정답이 아니다

지연돼도 되는 작업 (동기화 · 업로드 · 정리)

  • WorkManager. 재부팅을 넘고, 제약을 걸고, 재시도한다

화면이 살아 있는 동안만 필요한 작업

  • 코루틴 + lifecycleScope

정확한 시각에 해야 하는 일

  • AlarmManager

사용자가 인지하는 지속 작업

  • 포그라운드 서비스

"백그라운드 작업 = Service" 는 낡은 반사다

바인드 서비스

// 다른 컴포넌트가 붙어 메서드를 직접 부르는 형태
override fun onBind(intent: Intent): IBinder = LocalBinder()
inner class LocalBinder : Binder() { fun getService() = this@PlayerService }
  • 마지막 클라이언트가 unbind 하면 서비스가 종료된다
  • 수명이 클라이언트에 묶인다

면접 함정

  • "Service는 별도 스레드에서 돈다" → 기본은 메인 스레드다. 무거운 일을 하면 ANR이다.
  • "START_STICKY면 죽어도 되살아난다" → 되살아나지만 Intent는 null이다. 그리고 최근 버전에서는 보장이 약하다.

시작형과 바인드형의 수명

시작형 (startService / startForegroundService) onCreate → onStartCommand → (실행) → stopSelf()/stopService() → onDestroy 스스로 멈춰야 한다

바인드형 (bindService) onCreate → onBind → (클라이언트 사용) → onUnbind → onDestroy 마지막 클라이언트가 떠나면 자동 종료된다

둘을 섞으면 (음악 앱이 대표적)

  • 시작형으로 계속 돌리고, 화면이 붙었을 때만 바인드해 제어한다
  • stopSelf 와 unbind 가 모두 끝나야 종료된다

onStartCommand 반환값

  • START_STICKY — 죽으면 재시작한다. Intent 는 null 로 온다 (음악 재생)
  • START_NOT_STICKY — 재시작하지 않는다 (일회성 작업)
  • START_REDELIVER_INTENT 마지막 Intent 와 함께 재시작한다 (다운로드)

백그라운드 실행 제한 요약

  • Android 8 — 백그라운드에서 일반 Service 시작 금지

  • Android 9 — 유휴 앱의 센서·네트워크 접근 제한 (App Standby Buckets)

  • Android 10 — 백그라운드에서 Activity 실행 금지

  • Android 12 — 정확한 알람 권한 · 포그라운드 서비스 시작 제한 강화

  • Android 13 — 알림 권한 · 포그라운드 서비스 관리 대화상자

  • Android 14 — 포그라운드 서비스 타입 선언 강제

  • Android 15 — 포그라운드 서비스 시간 제한 (dataSync 6시간)

  • 방향은 일관된다 — "사용자가 모르는 백그라운드 실행을 계속 줄인다"

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 4대 컴포넌트 — Intent·Service·Receiver·Provider