
안드로이드 개발하다 보면 백그라운드에서 뭔가 계속 돌려야 할 일이 있다. 음악 재생이나 파일 다운로드처럼 말이다. 이런 때 사용하는 게 바로 Service다. 오늘은 안드로이드 Service에 대해 정리해봤다.
Service는 사용자 인터페이스 없이 백그라운드에서 장시간 실행되는 작업을 처리하는 안드로이드 컴포넌트다. 쉽게 말해서 "화면에는 안 보이지만 뒤에서 열심히 일하는 친구"라고 생각하면 된다.
대표적인 예가 음악 플레이어다. 음악 앱에서 노래를 틀고 다른 앱으로 이동해도 음악이 계속 재생되지 않나? 그게 바로 Service가 하는 일이다.
안드로이드 Service는 크게 세 가지로 나눌 수 있다.
startService()로 시작하면 독립적으로 실행되는 서비스다. 한 번 시작하면 작업이 끝날 때까지 계속 돌아간다.
언제 사용하나?
// 파일 다운로드 시작
val downloadIntent = Intent(this, DownloadService::class.java)
downloadIntent.putExtra("file_url", "https://example.com/file.zip")
startService(downloadIntent)
bindService()로 클라이언트가 연결해서 직접 통신할 수 있는 서비스다. 클라이언트가 없으면 자동으로 종료된다.
언제 사용하나?
// 음악 서비스와 연결해서 직접 제어
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
val binder = service as MusicPlayerService.MusicBinder
musicService = binder.getService()
musicService?.play() // 직접 메소드 호출 가능!
}
}
사용자에게 알림을 보여주면서 실행되는 서비스다. 시스템이 강제로 종료하기 어려워서 안정적으로 돌아간다.
언제 사용하나?
이 부분이 처음에 좀 헷갈렸다. 간단하게 정리하면
Started Service를 쓸 때
Bound Service를 쓸 때
기억하기 쉽게 "제어가 필요하면 Bound, 독립적인 작업이면 Started"라고 외우면 될 것 같다.
포그라운드 서비스는 좀 특별하다. 반드시 알림을 보여줘야 하고, 5초 이내에 startForeground()를 호출해야 한다.
class MusicPlayerService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// 🔥 핵심: 5초 이내에 이걸 호출해야 함!
startForeground(NOTIFICATION_ID, createNotification())
// 실제 작업 수행
performBackgroundWork()
return START_STICKY
}
private fun createNotification(): Notification {
return NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("음악 재생 중")
.setContentText("현재 재생: 노래 제목")
.setSmallIcon(R.drawable.ic_music_note)
.addAction(R.drawable.ic_pause, "일시정지", pausePendingIntent)
.setOngoing(true) // 사용자가 스와이프로 제거 못하게
.build()
}
}
AndroidManifest.xml에도 권한 추가하는 거 잊지 말자
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<service
android:name=".MusicPlayerService"
android:foregroundServiceType="mediaPlayback"
android:exported="false" />
Service도 Activity처럼 생명주기가 있다. 유형에 따라 조금씩 다르지만 기본적인 흐름은 이렇다

onCreate() → onStartCommand() → [실행 중] → onDestroy()
onCreate() → onBind() → [연결됨] → onUnbind() → onDestroy()
중요한 건 onCreate()는 서비스가 처음 생성될 때 한 번만 호출되고, onStartCommand()는 startService()를 호출할 때마다 실행된다는 거다.
그리고 onDestroy()에서는 반드시 리소스 해제해야 한다! 안 그러면 메모리 누수 생긴다.
override fun onDestroy() {
super.onDestroy()
// 반드시 리소스 해제!
mediaPlayer?.release()
wakeLock?.release()
}
실제로 써보면서 느낀 주의사항들이다
안드로이드 8.0부터 백그라운드 서비스 제한이 심해졌다. 정말 필요한 경우가 아니라면 WorkManager나 JobScheduler 같은 대안을 고려해보자.
// 작업 완료 후 꼭 이거 호출하자
stopSelf()
사용자가 무슨 일이 일어나고 있는지 알 수 있게 명확한 알림을 제공하자. "백그라운드에서 실행 중"이라고만 하지 말고 구체적으로 설명해주자.
무한 루프 돌리지 말고, 적절한 간격으로 작업하자:
// ❌ 이렇게 하지 말자
while(true) {
checkForUpdates()
Thread.sleep(1000)
}
// ✅ 이렇게 하자
handler.postDelayed(periodicTask, 5 * 60 * 1000) // 5분 간격
Service는 백그라운드 작업의 핵심이지만, 최신 안드로이드에서는 제약이 많아졌다. 꼭 필요한 경우에만 사용하고, 사용할 때는
이렇게 구분해서 사용하면 될 것 같다.
Service 잘 활용하면 사용자 경험이 확실히 좋아지는데, 잘못 쓰면 배터리 킬러가 되니까 신중하게 사용하자! 😅