본문 바로가기
개발/Android

[Android] Service – 3. Intent Service

by Dev Aaron 2020. 11. 8.
반응형

Service는 Activity와 같은 다른 컴포넌트에서 시작시킬 때 어떤 함수를 사용하여 시작했는지에 따라 두 가지 유형으로 나눌 수 있습니다.

  • Started Service: startService() 함수
  • Bound Service: bindService() 함수

본 포스팅에서는 이 중 Started Service, 그 중에서 Intent Service에 대해 알아보려 합니다. 이전 포스팅들과 마찬가지로 공식 문서를 참고하여 개인 학습용으로 정리하는 포스팅입니다.


Started Service를 구현하는 데에는 두 가지 방법이 있습니다.

  • Intent Service 상속받기
  • Service 상속받기

간단히 어떤 클래스를 상속받느냐에 따라 달라집니다.

IntentService

아마도 가장 일반적이고 간단하게 사용할 수 있는 Service의 구현 방법일 것 같습니다. (그리고 오해의 여지를 만들 수도 있고요.) 다음 코드는 간단한 Intent Service를 구현한 코드입니다.

class MyIntentService : IntentService("MyIntentService") {

    private val TAG = MyIntentService::class.java.simpleName

    override fun onCreate() {
        super.onCreate()
        Log.d(TAG, "[My] onCreate")
    }

    override fun onHandleIntent(intent: Intent?) {
        Log.d(TAG, "[My] onHandleIntent")

        for (i in 1..10) {
            Log.d(TAG, "[My] onHandleIntent - $i")
            Thread.sleep(1000)
        }
    }

}

먼저 간단히 설명부터 하면, startService를 통해 위 서비스를 시작시키면 기본적인 라이프사이클 콜백 함수가 불립니다. 그리고 핵심 부분인 onHandleIntent() 함수가 호출됩니다. 이 함수에서는 for문을 10번 돌면서 1초 간격으로 로그를 찍습니다.

IntentService 의 실행 로그

로그를 보면 다음과 같습니다.

2019-11-19 21:31:39.436 13309-13309/com. D/MyIntentService: [My] onCreate
2019-11-19 21:31:39.438 13309-13417/com. D/MyIntentService: [My] onHandleIntent
2019-11-19 21:31:39.438 13309-13417/com. D/MyIntentService: [My] onHandleIntent - 1
2019-11-19 21:31:40.439 13309-13417/com. D/MyIntentService: [My] onHandleIntent - 2
...
2019-11-19 21:31:47.447 13309-13417/com. D/MyIntentService: [My] onHandleIntent - 9
2019-11-19 21:31:48.447 13309-13417/com. D/MyIntentService: [My] onHandleIntent - 10

위 로그에서 한가지 특이점을 찾으셨나요?
onHandleIntent() 함수에서는 process id와 thread id가 다릅니다! 바로 onHandleIntent() 함수가 Main 스레드가 아닌 별도 스레드에서 동작한다는 것이죠. 다시 코드를 봐도 아시겠지만 별도로 Thread를 생성하지 않았습니다.

이전 포스팅에서도 언급했듯이 Service는 만들고 시작시켰다고 해서 별도 스레드에서 돌지 않습니다. 똑같이 Main 스레드에서 돌죠. 만약 별도 스레드에서 따로 돌리고 싶다면 Thread를 생성해주는 작업 등이 필요합니다. 하지만 Intent Service의 경우는 이러한 작업을 하지 않고도 알아서 별도 스레드에서 돌려줍니다.

이런 이유로 처음 Service를 배워 써먹어 보게 되면,

"아 서비스는 그냥 백 그라운드 스레드에서 알아서 잘 도는 구나"

라고 착각을 하실 수 있습니다. (제가 그랬거든요… 한참 뒤에 Service가 Main 스레드에서 도는 걸 보고 “서비스는 원래 알아서 백그라운드 스레드에서 도는거 아니었어?” 라며 놀랐었죠…)

정리

IntentService는 Service의 서브 클래스로 내부적으로 Worker Thread를 갖고 이를 통해 작업을 수행합니다. 단 이 Worker Thread는 단 하나로만 돌리기 때문에 Activity와 같은 컴포넌트에서 startService를 여러 번 호출하더라도 각 요청들은 모두 순차적으로 처리됩니다. 그리고 처리가 완료되면 해당 Service는 알아서 종료 라이프사이클을 타기 때문에 stopSelf()나 stopService()를 호출하여 종료시켜줄 필요가 없습니다.

주의 사항

IntentService를 구현하면서 한 가지 주의해야 할 점에 대해 말씀드리고자 합니다. IntentService는 onHandleIntent() 콜백 함수만 구현해주면 간단히 구현이 가능합니다. 하지만 필요에 따라 다른 콜백 함수를 구현하는 것도 당연히 가능하죠. 이때 만약 onStartCommand() 함수를 오버라이딩해야 한다면, return type을 절대 건드려서는 안됩니다.

return super.onStartCommand(intent, flags, startId)

위와 같이 기본 return 반환문을 유지시켜주세요. 그래야만 intent가 onHandleIntent() 함수로 전달된다고 공식 가이드 문서에도 명시되어 있습니다. (실제 위 부분을 임의로 수정해봤더니 onHandleIntent() 함수가 호출되지 않았습니다.)

반응형