Android

4. Kotlin Coroutine - CoroutineScope/Context/Job

Sara.H 2024. 5. 21. 23:44

CoroutineScope : launch/async 와 같은 코루틴 빌더로 생성된 코루틴을 매니징 하는 친구. 진행중인 코루틴은 scope.cancel() 을 통해 취소할 수 있음. 사실상 코루틴을 생성하려면 항상 CoroutineScope 가 필요한데, 안드로이드의 라이프사이클 클래스들에서는 이미 유틸로 제공하는 scope 들이 있다. (viewModelScope, lifecycleScope) 

 

CoroutineContext : CoroutineScope 를 생성할 때 인자로 넣어주는 애들을 코루틴 콘택스트라고 한다. 코루틴의 행위를 정의하는 것들을 퉁쳐서 콘택스트라고 한다. Job, CoroutineDispatcher, CoroutineName, CoroutineExceptionHandler 로 이루어져 있다. 새로운 코루틴이 만들어지면 Job 은 항상 새롭게 생성되고, 나머지는 부모 스코프 혹은 자신이 생성된 스코프로부터 물려받는다. 

 

// Job and Dispatcher are combined into a CoroutineContext which
// will be discussed shortly
val scope = CoroutineScope(Job() + Dispatchers.Main)
val job = scope.launch {
// new coroutine
}


val scope = CoroutineScope(Job() + Dispatchers.Main)
val job = scope.launch {
// New coroutine that has CoroutineScope as a parent
val result = async {
// New coroutine that has the coroutine started by
// launch as a parent
}.await()
}

 

이런 모양이다. CoroutineScope 안에 넣어주는 애들을 합쳐서 코루틴 콘택스트라고 한다. 

 

Job: Coroutine 을 새로 생성하면 항상 새로운 Job 인스턴스를 반환한다. 생성된 코루틴을 고유하게 구분해주는 식별자이며, 코루틴을 관리할 수 있는 핸들이다. CoroutineScope 의 인자로 Job 을 넘겨주어서 코루틴 라이프사이클을 관리할 수 있는 핸들로서 사용할 수 있음. 

 

Job 의 lifecycle : 

New, Active, Completing, Completed, Cancelling, Cancelled 

이런 상태들을 거치는데, 

개발자는 이런 상태에 직접적으로 접근할 수는 없다. 단지 isActive, isCancelled, isCompleted 세 가지 프라퍼티에 접근 가능하다. 

 

Job 이 실행중에 있다가, 

오류가 나거나 job.cancel() 이 호출이 되면 isActive = false, isCancelled = true 상태가 된다. 

즉, Job 의 상태는 Active 에서 Cancelling 상태로 전이가 일어난다 

그 Job 의 모든 자식들이 작업을 끝냈다면 그제서야 Cancelling 에서 Cancelled 상태로 전이가 일어나고, 

이 때 isCompleted = true 가 된다. 

 

부모 context 가 있고, 그 안에 scope.launch 를 통해 새로운 코루틴을 만든다면 

Job 빨간색과 구분되는 Job 초록색이 생긴다. 

 

Job 의 구현에 다른 종류를 넣어줄 수 있는데 (가령, SupervisorJob - 코루틴 스코프가 exception 처리를 하는 방식을 바꾼다) 

그렇게 된다면 해당 scope 로 생성된 코루틴은 부모가 사실상 SupervisorJob 이 되는 것이다. (나중에 더 자세히 설명)