Coroutine 코루틴

aram·2023년 3월 18일
0

Coroutine

비동기 프로그래밍을 하기 위해 코틀린에서 지원하는 라이브러리. 단일 스레드에서 많은 작업이 가능하여 메모리를 절약하고 스레드를 더 잘게 쪼개 사용하기 위한 개념이다.

스레드와 다른 점

코루틴은 작업 하나하나에 Thread 를 할당하는 것이 아닌 'Object' 를 할당해주고, 이 Object 를 자유롭게 스위칭함으로써 메모리와 Context Switching 비용 낭비를 대폭 줄일 수 있다.

예를 들어 Thread A 가 Thread B 의 결과가 나오기까지 기다려야 한다면, Thread A 은 블로킹되어 Thread B 로 Context Switching이 일어나고 결과가 나올 때 까지 해당 자원을 쓰지 못한다.

반면 코루틴에서 Object 1 이 Object 2 의 결과가 나오기까지 기다려야 한다면, Object 1 은 Suspend 되지만, Object 1 을 수행하던 Thread 는 그대로 유효하기 때문에 Object 2 도 Object 1 과 동일한 Thread 에서 실행될 수 있다.

suspend

함수 앞에 suspend 키워드를 붙이면 코루틴 내에서만 사용이 가능하다. 코루틴 내에서 suspend 함수가 호출된 경우 부모 루틴에서 코드를 잠시 멈추어 상태를 저장했다가, suspend 함수의 처리가 완료 되었을 때 부모 루틴이 다시 복원되어 그 다음 코드가 실행된다.

코루틴의 빌더

  • launch - 결과를 반환하지 않는 실행 후 망각 코루틴
  • async - await()을 통해 코루틴 결과를 기다릴 수 있다.
  • withContext - 부모 코루틴과 다른 컨텍스트(스레드)에서 코루틴을 실행 시킬 수 있다.
  • runBlocking - 코루틴을 실행하고 완료될 때까지 현재 스레드를 중단시킨다.

Dispatcher

  • Main - UI와 상호작용하는 경우
  • IO - 디스크 또는 네트워크 작업
  • Default - CPU를 많이 사용하는 경우

예시

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

        // Move the execution of the coroutine to the I/O dispatcher
        return withContext(Dispatchers.IO) {
            // Blocking network request code
        }
    }
}

class LoginViewModel(
    private val loginRepository: LoginRepository
): ViewModel() {

    fun login(username: String, token: String) {

        // Create a new coroutine on the UI thread
        viewModelScope.launch {
            val jsonBody = "{ username: \"$username\", token: \"$token\"}"

            // Make the network call and suspend execution until it finishes
            val result = loginRepository.makeLoginRequest(jsonBody)

            // Display result of the network request to the user
            when (result) {
                is Result.Success<LoginResponse> -> // Happy path
                else -> // Show error in UI
            }
        }
    }
}

로그인 함수가 실행되는 과정

  • 앱이 기본 스레드의 View 레이어에서 login() 함수를 호출합니다.
  • launch가 기본 스레드에 새 코루틴을 만들고 코루틴이 실행을 시작합니다.
  • 코루틴 내에서 이제 loginRepository.makeLoginRequest() 호출은 makeLoginRequest()withContext 블록 실행이 끝날 때까지 코루틴의 추가 실행을 정지합니다.
  • withContext 블록이 완료되면 login()의 코루틴이 네트워크 요청의 결과와 함께 기본 스레드에서 실행을 재개합니다.

참고 : https://developer.android.com/kotlin/coroutines?hl=ko
https://velog.io/@haero_kim/Thread-vs-Coroutine-%EB%B9%84%EA%B5%90%ED%95%B4%EB%B3%B4%EA%B8%B0

0개의 댓글