본문 바로가기

Language/Kotlin

코루틴

반응형

코루틴은 왜 만들어졌을까?

코루틴을 알아보기에 앞서 코루틴이 왜 만들어졌는지 찾아보았다.

다음 영상은 꼭 보는 것을 추천한다.

https://www.youtube.com/watch?v=BOHK_w09pVA 

구글 I/O

위 영상을 보면 코루틴은 Dream Code를 위해 만들어진 라이브러리라고 한다.

여기서 Dream Code는 다음과 같다.

val user = fetchUserData()
textView.text = user.name

 

fetchUserData 함수는 HttpConnection이나 Retrofit으로 서버 api를 조회해 유저 데이터를 받아오는 것을 뜻한다.

안드로이드에서는 메인쓰레드로 서버 api를 조회할 수 없기 때문에  이 코드가 정상적으로 동작하지 않는다. 또한 메인쓰레드에서 Http 커넥션을 할 수 있게 바뀐다고 해도 서버 상황에 따라 클라이언트는 ANR이 발생할 확률이 높아지기 때문에 위와 같은 코드는 비현실적이라는 것을 알 수 있다.

비현실적이지만 개발자 입장에서는 쉽게 개발할 수 있기 때문에 위 코드를 Dream Code라고 표현한 것이다.

 

코드를 현실적인 코드로 바꿨을 때도 몇 가지 귀찮은 부분이 생긴다.

val subscription = fetchUserData { user->
	textView.text = user.name
}

override fun onStop() {
	subscription.cancel()
}

다음 코드는 Http 커넥션을 비동기로 처리하고 그 결과를 콜백으로 받음으로써 UI를 업데이트 한다. 이 작업은 쓰레드 씽크가 안맞으면 메모리 릭이 발생할 수 있기 때문에 생명주기에 맞게 작업을 취소해주었다.

 

위 코드에서 발생할 수 있는 문제점은 두 가지이다.

첫 번째로 로직이 복잡해지면 콜백이 난무하면서 콜백지옥이 펼쳐질 수 있다.

두 번째로 옵저빙 작업이 많아지면 하나 하나 모두 cancel을 해주어야 하기 때문에 매우 귀찮아질 수 있다.

이 두 문제점들을 해결하고자 만들어진 것이 코루틴이다. 

 

코루틴이란?

코루틴은 Co + Routine이 합쳐진 용어로 협동적인 루틴이라는 뜻을 가지고 있으며 중단, 재개, 범위라는 개념을 통해 비동기 작업을 더 손쉽게 사용할 수 있는 라이브러리이다.

그 외에도 일반 쓰레드보다 경량 쓰레드라는 점에서 속도 면에서 우월하다는 장점을 가지고 있다.

 

실행 우선순위, 범위, 중단, 재개, 취소를 한 눈에 확인할 수 있는 코드를 만들어 보았다.

package com.example.coroutinesample.basics

import kotlinx.coroutines.*

private val m_scope = CoroutineScope(Dispatchers.IO)

fun main()
{
    m_scope.launch {
        val userName = fetchUser()
        show(userName)
    }

    m_scope.launch {
        val userName = fetchUser()
        show(userName)
    }


    var i = 0
    while (i < 5)
    {
        println("Main Thread Work $i....")
        i++
        Thread.sleep(1 * 1000)
//        m_scope.cancel()
    }
}

suspend fun fetchUser() : String
{
    var userName : String = ""
    coroutineScope { // HttpConnection
        delay(2 * 1000)
        userName = "Hinos"
    }
    return userName
}

fun show(userName : String)
{
    println(userName)
}

m_scope.cancel() 적용했을 때
m_scope.cancel() 적용 안했을 때

 

위 예제를 통해서 알 수 있는 부분은 다음과 같다.

1. 코루틴 영역인 CoroutineScope를 먼저 실행시키는 것이 아니라 main Thread의 while문이 먼저 실행된다는 것

2. CoroutineScope 영역이 실행되어도 main Thread의 while문은 계속 실행된다는 것

3.  suspend fun fetchUser에서 콜백 대신 영역이 중단됐다가 다시 재개되어 String을 리턴한다는 것

4. 하나의 CoroutineScope로 여러 코루틴 빌더들을 가질 수 있고 cancel 했을 때 scope에 등록된 빌더들은 모두 cancel이 된다는 것

 

 

 

반응형