-
#1. Why CoroutineAndroid/Coroutine 2021. 10. 5. 17:20
서론
안드로이드에서 비동기 백그라운드 작업을 하는 AsyncTask가 @Deprecated가 붙고 이 커밋에서 다음과 같은 코멘트가 남겨졌다.
AsyncTask was intended to enable proper and easy use of the UI thread. However, the most common use case was for integrating into UI, and that would cause Context leaks, missed callbacks, or crashes on configuration changes. It also has inconsistent behavior on different versions of the platform, swallows exceptions from doInBackground, and does not provide much utility over using Executors directly.
요약하자면, AsyncTask는 UiThread를 사용하기 위해 만들어 졌지만, Context누수 잘못 된 Callback 등 여러가지 문제가 있고, 플랫폼의 각 버전마다 일관성있는 행동을 하지 못했고, 여러 Exception들로 인해 많은 효용을 제공하지 못했다고 한다.
AsyncTast가 Deprecated가 되면서 대체재가 필요한데 대표적으로 두 가지가 있다.
- RxJava/ RxKotiln
- Coroutine
여기서는 Coroutine에 대해 알아볼 것이다.
Android Studio 공식 홈페이지에서는 아래와 같이 Coroutine을 소개한다.
A coroutine is a concurrency design pattern that you can use on Android to simplify code that executes asynchronously. Coroutines were added to Kotlin in version 1.3 and are based on established concepts from other languages.
On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive. Over 50% of professional developers who use coroutines have reported seeing increased productivity.
코루틴은 동시 실행 디자인 패턴이고, 비동기적 코드를 실행하는 것을 쉽게 만들어준다. Coroutine은 Kotlin 1.3버전에 추가됐고, 다른 언어에서 정착한 개념을 기반으로 한다.
안드로이드에서는 앱이 작동하지 않게하거나 메인스레드를 block하는 오래 걸리는 작업을 관리할 수 있도록 도와준다. 50%가 넘는 프로 개발자들은 Coroutine을 사용하고 업무 생산성이 증가했다고 보고됐다.
정리해보면...
기존 Android Studio에서 비동기 실행으로 많이 사용하던 AsyncTask 가 Deprecated가 되면서 비동기 실행을 위한 솔루션이 필요했는데 대표적인 두 가지가 Rx, Coroutine이다.
Coroutine은 비동기 동시 실행을 위한 디자인 패턴이고 Kotlin에만 있는 개념이 아닌 파이썬, C#, Go, Javascript 등 여러 언어에서 지원하고 있는 개념이다.
Coroutine을 이용하여 비동기적 코드를 쉽게 실행할 수 있다.
코루틴이 뭐길래 많은 개발자들의 생산성이 증가했다고 하고, 비동기 동시 실행을 쉽게 만들어 준다고 자신있게 언급하는가? 이제 어떻게 비동기 실행을 쉽게 만들어주는지 알아보자.
1. Coroutine 작동 방식
fun DoSomething{ StartCoroutine{ Do1() Do2() Do3() } } suspend fun Do1(){ delay(2000) } suspend fun Do2(){ delay(5000) } suspend fun Do3(){ delay(3000) }
위 코드에서 DoSomething()으로 코루틴을 실행하는 함수가 있다.
실제 Coroutine은 StartCoroutine으로 실행하지 않지만, 이해를 돕기 위해 StartCoroutine으로 나타냈다.
suspend 키워드는 간단하게 말하자면 시작하고, 멈추고, 다시 시작할 수 있는 함수다.
위 코드에서 MainThread가 DoSomething()함수를 실행한다면 Do1()함수를 먼저 실행하게 된다. Do1은 2초가 소요되는데, MainThread는 2초를 마냥 대기하는 것 대신 Do1이 완료되기 까지 잠시 Coroutine을 빠져나와 다른 일을 진행한다.
2초가 지나 Do1이 완료된다면 다시 Coroutine으로 진입하여 Do2()함수를 실행한다.
이런 진행이 가능한 이유가 바로 suspend 키워드다. suspend에 대한 자세한 설명은 뒤에서 살펴보도록 하겠다.
이제 위 코드에 흐름을 따라가보자.
1. MainThread가 DoSomething를 호출하여 StartCoroutine으로 Coroutine이 된다.
2. suspend 키워드가 명시된 Do1을 만나 MainThread는 잠시 Coroutine을 빠져나와 다른 일을 진행하고, 2초가 지나 Do1이 완료되어 다시 Coroutine에 진입하여 다음 차레인 Do2를 실행한다.
3. 마찬가지로 Do2의 suspend 키워드로 인해 MainThread는 잠시 Coroutine을 빠져나와 다른 일을 진행하고 ,5초 후 다시 Coroutine으로 다시 진입한다.
5. Do3도 같은 방식으로 진행한다.
기본적인 Coroutine은 위와 같이 진행한다. 실제 StartCoroutine함수로 Coroutine을 시작하지는 않지만, 위 코드만 보면 기존에 AsyncTask에 비해서는 굉장히 코드가 간소화 된 것을 볼 수 있다. 이전 AsyncTask를 사용하기 위해서는 클래스 하나를 만들고 AsyncTask를 상속받아 필요 함수(doInBackground, onProgressUpdate..)들을 Override하여 각 작업을 처리해주어야 했지만 Coroutine은 굉장히 간단하게 진행 할 수 있다.
2. Coroutine으로 비동기 Callback 처리하기
Coroutine을 사용하면 비동기 처리가 굉장히 쉬워진다. 심지어는 이게 비동기 처리인가? 싶을 정도로 읽기 쉽고 짜기도 쉬운 코드를 볼 수 있다.
Do함수들이 순서대로 실행되어야 하는 Callback 함수를 구현해보자
Callback
fun DoSomething(p: Parameter){ val parameter = p Do1(parameter){ result1 -> Do2(result1){result2 -> Do3(result2){ result3 -> Do4(result3) -> {result4 val result5 = finish(result4) result5.Do() } } } } }
콜백으로 비동기 처리를 구현했을 때 흔히 겪을 수 있는 콜백 헬이다. 심지어 에러 처리도 하지 않는 코드인데 벌써 보기가 어렵다. 비동기 처리를 위한 다양한 방법론이 나오기 전에는 대부분 이런방식으로 처리했다.
Kotlin Coroutine
suspend fun DoSomething(p: Parameter){ val parameter = p try{ val result1 = Do1(parameter) val result2 = Do2(result1) val result3 = Do3(result2) val result4 = Do4(result3) val result5 = finish(result4) result5.Do() }catch(e: Exception){ ... }
안에서 호출되는 각 함수들은 오래걸리는 작업이고, 언제 끝날지 모르는 비동기 작업들이지만 각자 함수들의 순서는 정확히 지켜진다. Do2함수는 Do1함수가 끝나야만 실행되고, Do3함수는 Do2함수가 끝나야만 실행된다.
이게 가능한 이유는, DoSomething라는 함수가 Coroutine이기에 Do1을 만나면 Do1함수를 실행함과 동시에(여기서는 백그라운드 스레드에서 동시에 실행될 것이다.) 잠시 DoSomething를 빠져나간다. 그러다가 Do1이 자신의 일을 끝마치면 다시 DoSomething로 돌아올 수 있기 때문이다. 이게 코루틴으로 비동기 처리를 할 때 생기는 장점이다.
여기까지 Coroutine이 무엇인지 알아봤다. 다음은 Coroutine을 사용하는 방법에대해 알아보겠다.
Ref:
https://developer.android.com/kotlin/coroutines
https://calvinjmkim.tistory.com/35
'Android > Coroutine' 카테고리의 다른 글
#3 Coroutine 형식 (0) 2021.10.10 #2 Coroutine 구성요소 (0) 2021.10.06