우아한테크코스

Kotlin coroutine 강의로 이해하기 - 2 : [우아한테크코스 5기 AN_베르]

베르_최성훈 2023. 7. 30. 20:00

 

다시 돌아온 코루틴!

 

그럼 바로 문제부터 시작해볼까요?

 

문제1 

다음 코드는 언제 끝날까요?

fun main() = runBlocking {
    val job = launch {
        while (true) {
            println("While in ${Thread.currentThread().name}")
        }
    }
}

 

 

 

 

정답

이 코드는 안끝납니다! 

launch 스코프로 실행하고 runBlocking 이 끝날 때 까지 기다리기 때문에 무한루프를 타게 됩니다.

 

문제 2

그럼 이 녀석은 언제 끝날까요?

fun main() = runBlocking {
    val job = launch {
        while (true) {
            println("While in ${Thread.currentThread().name}")
        }
    }
    println("종료")
    job.cancel()
    println("종료 끝")
}

 

정답

바로 끝납니다!

cancel() 로 job 을 끝내버리기 때문이죠

 

 

문제 3

그럼 코드는 끝나는데 몇 초 걸릴까요?

fun main() = runBlocking {
    val job = launch {
        while (true) {
            println("While in ${Thread.currentThread().name}")
        }
    }
    delay(1000L)
    job.cancel()
}

 

 

정답

1초..일줄 알았지만 사실 끝나지 않습니다!

delay 를 만나는 순간 제어권을 launch 스코프에서 가져가고 무한루프가 실행되기 때문이죠.

 

delay 의 내부를 보면 좀 더 이해할 수 있습니다!

yield 도 마찬가지입니다ㅎㅎ

이렇게 재밌는 코루틴을 공부해봅시다! 

 

Dispatcher

스레드 풀을 관리하고 코루틴을 실행 또는 재개할 스레드를 결정한다.

 

서버 통신과 같이 오래걸리고 가벼운 작업이 여러개의 스레드를 사용한다. 

따라서 코루틴을 잘 사용하려면 언제 어떤 dispatcher 를 사용할 지 잘 알아야합니다.

여러 Dispatcher 가 존재합니다.

 

Default Dispatcher

JVM의 공유 스레드 풀을 사용하며 동시 작업의 최대 수는 CPU의 코어 수(엄밀히 말하면 물리적 스레드 수)와 같다.

 

IO Dispatcher

  • IO Dispatcher는 Default Dispatcher와 스레드 풀을 공유한다.
  • 최대 64개까지의 스레드를 생성
  •  
  • withContext(Dispatchers.IO)로 감싸서 일시 중단 함수로 만들면 가장 좋다.

Main Dispatcher

  • 안드로이드에서만 존재하는 Dispatcher
  • 메인 스레드가 UI와 상호작용하는 데 사용
  • Main 스레드가 차단되면 전체 애플리케이션이 중지

 

 

CoroutineScope vs WithContext

CoroutineScope

코루틴의 수명 주기를 관리하기 위한 스코프를 제공한다.

해당 Dispatcher 에 새로운 스코프를 연다.

CoroutineScope(Dispatchers.IO).launch { }

 

WithContext

withContext(Dispatchers.IO) { launch { } }

컨텍스트를 일시적으로 변경한다.

with context 는 async await 이 합쳐진 형태다.

실행 블록이 완료되면 코루틴이 일시 중단되고 원래 컨텍스트(withContext가 호출된 곳)가 복원된다.

즉, 비동기 코드 안에서 사용하면 동기적으로 작동하게 할 수 있다.

 

GlobalContext

전체 애플리케이션 수명 주기 동안 존재한다. 앱이 죽을 때 까지 존재하고 계속 실행된다.

 

 

coroutineScope(소문자)

현재 스코프의 컨텍스트를 상속받는 새 코루틴 스코프를 연다.

 

 

ViewModelScope

아마 현재 안드로이드에서 가장 많이 사용하는 스코프가 아닐까 

 

이 범위에서 시작된 모든 코루틴 스코프는 뷰모델이 삭제되면 자동으로 취소된다.

ViewModel이 활성 상태인 경우에만 실행해야 할 작업이 있으면 유용하다.

 

class SomeViewModel(
    private val someDefaultRepository: SomeRepository
): ViewModel() {

    fun setSomething(something: String) {
        viewModelScope.launch(Dispatchers.IO) {
            someDefaultRepository.postSomething(something)
        }
    }
}