코루틴이란?


간단하게 설명하자면 쓰레드에 의존하지 않고 비동기 작업을 용이하게 해주는 라이브러리입니다.

코루틴의 장점


기존 비동기 작업, 멀티테스킹을 위해서는 Thread를 기반으로 하는 안드로이드 라이브러리 AsyncTask를 사용했습니다.

하지만 시스템 프로그래밍 관점에서 보았을 때 쓰레드를 생성하는 비용과 멀티 스레딩의 메모리 관리, Context Switching의 비용 등 부담이 많이 발생하는데 코루틴을 사용하면 멀티스레딩 없이 비동기 작업을 진행할 수 있고 비용이 적게 듭니다.

코루틴의 경우 이름 그대로 협업 루틴이기 때문에 하나의 쓰레드 안에서 여러 코루틴을 생성해 비동기 작업을 할 수 있습니다.

단순이 어떤 종류의 작업을 진행할지 Dispatcher를 통해 지정해주면 간단하게 비동기 작업을 수행할 수 있습니다.

작업 종류


작업 종류를 크게 3가지로 나누어 지정할 수 있습니다.


Main : 메인 스레드(UI 스레드)에서 작업을 합니다, UI를 참조하거나 변경 할 때 쓰입니다.

IO : 네트워크 관련된 작업을 합니다.

Default : CPU 연산이 필요한 작업에서 쓰입니다.


메모리 누수


Thread를 사용하는 AsyncTask 보다는 훨씬 안전하지만 코루틴이라고 해서 메모리 누수의 문제점을 완전히 피해갈 순 없습니다.

예를 들어 lifecycleScope를 인지하지 않고 코루틴을 사용하면 모든 엑티비티가 onDestory() 되더라고 주어진 task를 이어가며 메모리 누수가 발생합니다.

이를 방지하기 위해 lifecycleScope 를 제공합니다.

아래 의존성 프로젝트를 추가하면 lifecycleScope 코루틴을 쉽게 생성 할 수 있습니다.


    //코루틴
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'

    // 생명주기 aware 코루틴
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'


//MainActivity.kt
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding= ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        lifecycleScope.launch {
            for(i in 1..100){
                delay(1000)
                Log.d("life cycle aware",i.toString())
            }
        }
        CoroutineScope(Dispatchers.IO).launch {
            for(i in 1..100){
                delay(1000)
                Log.d("life cycle not aware",i.toString())
            }
        }
    }

onDestroy가 호출된 이후 일반 코루틴과 달리 lifecycleScope 코루틴은 바로 작업을 종료합니다.


하지만 이렇게 lifecycleScope 코루틴을 사용하더라도 완전히 문제점이 사라지지 않습니다.

lifecycleScope의 경우 컴포넌트의 onDestroy와 함께 스코프 안의 job들이 취소되는데 만약 onDestroy가 아니라 홈버튼에 의한 onStop()만 호출된 경우 의도치 않는 메모리 누수가 계속 발생하고 앱이 죽을 수 있습니다.

이를 막기 위해서는 onStop()에서 코루틴을 멈추고 onStart()에서 시작시키는 코드를 작성해야 하는데 이런 보일러 플레이트 코드가 가독성을 떨어트리고 프로그래머에게 직접 메모리 누수에 대한 부담을 주게됩니다.


따라서 이런 보일러 플레이트 코드를 없에기 위해 repeatOnLifecycle API를 제공 (엑티비티가 포그라운드에 있을 때 만 동작)

느낀점

우리 프로그래머들은 계속해서 좋은 라이브러리들을 제공받고 쉬운 사용방식으로 인해 간결해진 코드와 시간적 이득을 볼 수 있습니다.

우리는 새로운 최신 라이브러리들을 의심하지 않고 제공받은 API를 남발하는 경우가 있는데 좋은 라이브러리일수록 그리고 더욱 간결해질수록 더욱이 그 안을 유심히 들어다봐야하고 의도치 않은 실수나 메모리 누수가 발생할 수 있는지 점검해야합니다.