Coroutine 01

Kotlin coroutine

kotlinx.coroutines 에는 다양한 표현들이 있습니다. launch 또는 async 등등의 코루틴의 핵심 요소들이 있습니다. 이러한 표현들을 사용하여 코루틴을 어떻게 프로젝트에서 사용하는지 소개 합니다.

Kotlin basics

코루틴의 기본적인 컨셉입니다.

fun main(args: Array<String>) {
    launch { // launch new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

launch 를 이용하여 코루틴을 시작 합니다. launch 로 넘겨준 블록은 백그라운드에서 실행이 됩니다. 그리고 기본적으로는 블록안의 코드는 순차적으로 실행이 됩니다. 그래서 위의 코드의 실행 결과를 살펴보면

Hello,
World!

코루틴은 light-weight threads 경량화된 쓰레드 이고, launch 같은 애들을 coroutine builder라 부르며 코루틴은 해당 키워드로 실행이 됩니다. 또한 코루틴의 블록 안에는 suspend 키워드가 붙은 함수만을 사용해야 한다. 또한 launchjob 을 반환하는데 이 객체를 통해 cancel 을 할수 있고, 또는 join 함수를 통해 job이 끝날때 까지 기다릴수 있다.

fun main(args: Array<String>) = runBlocking<Unit> {
    val job = launch { doWorld() }
    println("Hello,")
    job.join()
}

// this is your first suspending function
suspend fun doWorld() {
    delay(1000L)
    println("World!")
}

이러한 점들을 활용하여 일반적으로 많이 사용될 만한 흐름을 좀더 깔끔하고 간결하게 코드를 작성할수 있게 된다. 우선은 단순히 동기적으로 코드를 나열하면 아래와 같은 코드가 된다.

fun requestToken(): Token { ... }
fun createPost(token: Token, item: Item): Post { ... }
fun updateUI(post: Post) { ... }

fun postItem(item: Item) {
  val token = requestToken()
  val post = creatPost(token, item)
  updateUI(post)
}

위와 같은 코드로 그대로 실행한다면 UI 쓰레드에서 긴 시간의 작업을 하게 되며 UI가 끊기는 현상을 볼수 있게 될 것이다. 그것을 해결하기 위하여 보통 가장 많이 이용하는 방법이 callback 을 이용하여 백그라운드 쓰레드로 처리한후 callback 으로 알려주는 방식이다. 코드는 아래와 같이 될 것이다.

fun requestTokenAsync(cb: (Token) -> Unit) { ... }
fun createPostAsync(token: Token, item: Item, cb: (Post) -> Unit) { ... }
fun updateUI(post: Post) { ... }

fun postItem(item: Item) {
  requestTokenAsync { token ->
    creatPostAsync(token, item) { post ->
      updateUI(post)
    }
  }
}
comments powered by Disqus