Kotlin coroutines on Android  |  Android Developers

안드로이드 코루틴 공식문서를 참고하고 정리한 포스팅 입니다.

코루틴이 뭐야?

코루틴은 실행을 일시 중단 하고 재개 할 수 있는 비동기 프로그래밍을 위한 라이브러리. 서브루틴을 사용하여 어떤 작업을 하기 위해 함수가 호출이 되고 함수의 동작이 끝나면 자신을 호출했던 메인루틴으로 돌아옴.

안드로이드에서 코루틴을 사용하는 예제

구글 권장 아키텍처 가이드에 맞춰 코루틴을 사용하는 예제를 살펴보자.

시나리오는 다음과 같다.

<aside> 📖 네트워크 요청을 보내고, 결과를 기본 스레드로 반환한다.

</aside>

백그라운드 스레드에서 실행

UI 스레드에서 네트워크 요청을 할 경우에 응답을 받을 때까지 스레드가 대기하거나 차단된다. 스레드가 차단되는 경우엔 OS는 UI 작업을 하지 못하며, 앱이 정지되고 ANR이 표시될 수 있다.

// 네트워크 요청을 응답을 모델링하기 위한 Result 클래스
sealed class Result<out R> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
}

class LoginRepository(private val responseParser: LoginResponseParser) {
    private const val loginUrl = "<https://example.com/login>"

    // 동기식이며, 호출 스레드를 차단한다.
    fun makeLoginRequest(
        jsonBody: String
    ): Result<LoginResponse> {
        val url = URL(loginUrl)
        (url.openConnection() as? HttpURLConnection)?.run {
            requestMethod = "POST"
            setRequestProperty("Content-Type", "application/json; utf-8")
            setRequestProperty("Accept", "application/json")
            doOutput = true
            outputStream.write(jsonBody.toByteArray())
            return Result.Success(responseParser.parse(inputStream))
        }
        return Result.Error(Exception("Cannot open HttpURLConnection"))
    }
}

위 코드에서 makeLoginRequest 함수를 실행하면 비동기식이 아니기 때문에 호출한 스레드를 차단한다. 이는 네트워크 요청이므로, 메인 스레드에선 실행하면 안된다. 안전을 위해 코루틴을 사용해서 코드를 변경해보자.

class LoginRepository(...) {
    ...
    suspend fun makeLoginRequest(
        jsonBody: String
    ): Result<LoginResponse> {

        return withContext(Dispatchers.IO) {
            // Blocking network request code
        }
    }
}

makeLoginRequest 를 일시중단 함수로 설정해줬다. 코루틴에서 해당 함수를 호출한 경우 코루틴은 이 함수가 재개될 때 까지 일시정지되고, 다른 코루틴을 실행한다.

makeLoginRequest 함수는 viewModelScope.launch 에서 사용된다. 이는 설정을 안해줬을 경우 디폴트는 Dispatcher.Main이므로 코루틴 스코프를 설정해주거나, withContext 를 사용하여 알맞은 스코프로 변환해줘야 한다.

위 예제에선 withContext 를 사용하여 코루틴 컨텍스트를 변경해줌으로 네트워크 작업에 용이하다. withContext 의 작업이 끝나면, 요청 결과와 함께 기본 스레드에서 실행을 재개한다.