기존의 RxJava와 같은 코드 스타일은 콜백을 사용하여 백그라운드 스레드의 작업을 처리하였다. 작업 완료 여부를 메인 스레드가 busy-waiting하고 있지 않고, 완료 되었을 때 콜백 코드가 호출되어 Main-Safe하게 작업을 처리할 수 있다.
// RxJava Callback 방식
fun createUser(id: String, password: String){
repository.checkUser(id, password)
.observeOn(scheduler)
.toObservable
.subscribe{ user ->
repository.signIn(user)
.doOnSuccess{
// 로그인 성공
Timber.d("login success")
}
}.let(compositeDisposable::add)
}
하지만 콜백 요청이 많아지고 중첩으로 하게된다면 코드의 가독성을 해치게 된다. 코루틴
은 이러한 콜백 기반 코드를 **Sequential Code(동기 코드 같이)**로 작성할 수 있게 해준다.
// Coroutine 방식
suspend fun createUser(id: String, password: String){
val user = repository.checkUser(id, password)
repository.signIn(user)
// 로그인 성공
Timber.d("login success")
}
다음과 같이 코루틴을 사용하면 비동기 동작을 동기 코드처럼 표현함으로써 코드의 가독성이 향상되었다. 더욱 직관적이고 추론하기 쉬운 코드는 예측 가능한 프로그램을 만들며 이는 에러 핸들링 및 디버깅 작업에 이점을 준다.
위의 예시에서 함수 앞에 suspend
키워드가 붙은 것을 볼 수 있다. suspend 키워드가 붙은 함수는 Kotlin 컴파일러가 어떤 작업을 해주길래 동기 코드 처럼 작성할 수 있는지 알아보자.
https://tech.devsisters.com/posts/crunchy-concurrency-kotlin/
코루틴은 Continuation Passing Style(CPS) 형태로 동작한다.
https://kotlinlang.org/spec/asynchronous-programming-with-coroutines.html
CPS
는 호출되는 함수에 Continuation을 전달하고, 각 함수의 작업이 완료되는 대로 전달받은 Continuation을 호출하는 방식을 말한다.
Continuation
인터페이스에는 context와 resumeWith가 있다.
CoroutineContext
는 코루틴이 실행되는 환경 및 문맥을 말하며, 현재 실행되는 코루틴의 상태 정보를 담고 있다.즉, CPS에선 Continuation을 전달하면서, 현재 일시 중단된 부분에서 재개가 가능하게 한다. Continuation은 재개되었을 때의 동작 관리를 위한 객체로, 연속적인 상태 간의 communicator라고 볼 수 있다.