시배's Android

Kotlin Coroutines Deep Dive | 11장. 코루틴 스코프 함수 본문

Book/Kotlin Coroutines Deep Dive

Kotlin Coroutines Deep Dive | 11장. 코루틴 스코프 함수

si8ae 2024. 1. 31. 21:57
//이렇게 구현하면 안 됩니다!!
suspend fun getUserProfile() : UserProfileData {
	val user = GlobalScope.async { getUserData() }
    val notifications = GlobalScope.async { getNotifications() }
    
    return UserProfileData(
    	user = user.await(),
        notifications = notifications.await()
    )
}
  • GlobalScope는 그저 EmptyCoroutineContext를 가진 스코프일 뿐입니다.
  • 이때 aync 코루틴은 취소가 될 수 없습니다.
  • 부모로부터 스코프를 상속받지 않습니다.
  • 메모리 누수가 발생할 수 있으며 쓸데없이 CPU를 낭비합니다.
  • 코루틴을 단위 테스트하는 도구가 작동하지 않아 함수를 테스트하기 아주 어렵습니다.
  • 스코프를 인자로 넘기는 방법 또한 좋지 않습니다.
  • 스코프가 함수로 전달되면 스코프에서 예상하지 못한 부작용이 발생할 수 있습니다.
  • async에서 예외가 발생하면 모든 스코프가 닫히게 됩니다.
  • 또한 스코프에 접근하는 함수가 cancel 메서드를 사용해 스코프를 취소하는 등 스코프를 조작할 수도 있습니다.

coroutineScope

  • coroutineScope의 본체는 리시버 없이 곧바로 호출됩니다.
  • coroutineScope 함수는 새로운 코루틴을 생성하지만 새로운 코루틴이 끝날 때까지 coroutineScope를 호출한 코루틴을 중단하기 때문에 호출한 코루틴이 작업을 동시에 시작하지는 않습니다.
  • 생성된 스코프는 바깥의 스코프에서 coroutineContext를 상속받지만 컨텍스트의 Job을 오버라이딩 합니다. 
  • 생성된 스코프는 부모가 해야 할 책임을 이어 받습니다.
  • 부모로부터 컨텍스트를 상속받습니다.
  • 자신의 작업을 끝내기 전까지 모든 자식을 기다립니다.
  • 부모가 취소되면 자식들 모두를 취소합니다.
  • 코루틴 빌더와 달리 coroutineScope나 스코프에 속한 자식에서 예외가 발생하면 다른 모든 자식이 취소되고 예외가 다시 던져집니다.
  • coroutineScope 함수는 기존의 중단 컨텍스트에서 벗어난 새로운 스코프를 만듭니다.
  • 부모로부터 스코프를 상속받고 구조화된 동시성을 지원합니다.
코루틴 빌더 (runBlocking 제외) 코루틴 스코프 함수
launch, async, produce coroutineScope
supervisorScope
withContext, withTimeout
CoroutineScope의 확장 함수 중단 함수
CoroutineScope 리시버의 코루틴 컨텍스트를 사용 중단 함수의 컨티뉴에이션 객체가 가진 코루틴 컨텍스트를 사용
예외는 Job을 통해 부모로 전파됨 일반 함수와 같은 방식으로 예외를 던짐
비동기인 코루틴을 시작함 코루틴 빌더가 호출된 곳에서 코루틴을 시작함

withContext

  • withContext의 인자로 컨텍스트를 제공하면 부모 스코프의 컨텍스트를 대체합니다.

supervisorScope

  • supervisorScope 함수는 호출한 스코프로부터 상속받은 CoroutineScope를 만들고 지정된 중단 함수를 호출한다는 점에서 coroutineScope와 비슷합니다.
  • 둘의 차이는 컨텍스트의 Job을 SupervisorJob으로 오버라이딩하는 것이기 때문에 자식 코루틴이 예외를 던지더라도 취소되지 않습니다.
  • withContext(SuperVisorJob())을 사용하면 withContext는 여전히 기존에 가지고 있던 Job을 사용하며 SupervisorJob()이 해당 잡의 부모가 됩니다.
  • 따라서 하나의 자식 코루틴이 예외를 던진다면 다른 자식들 또한 취소가 됩니다.

withTimeout

  • withTimeout은 인자로 들어온 람다식을 실행할 때 시간 제한이 있다는 점이 다릅니다.
  • CancellationException의 서브타입인 TimeoutCancellationException을 던집니다.
  • 해당 코루틴만 취소가 되고 부모에게는 영향을 주지 않습니다.