1. Coroutine Context란
코루틴이 실행될 때 이를 관리하고 제어하는 여러 요소들이 결합된 객체이다.
2. 구성 요소
여러 키-값 쌍으로 이루어진 데이터 구조이다.
- Job
- 코루틴의 생명 주기를 관리한다.
- Job은 부모-자식 관계를 형성하여 구조적 동시성을 구현하는 데 중요한 역할을 한다.
- 구조적 동시성이란 부모 코루틴이 자식 코루틴의 생명 주기를 관리하는 구조를 의미한다.부모 코루틴이 취소되면 모든 자식 코루틴도 자동으로 취소되며 자식 코루틴이 완료되기 전에는 부모 코루틴이 종료되지 않는다.
- Dispatcher
- 코루틴이 실행될 스레드나 스레드 풀을 지정한다.
- CoroutineName
- 코루틴에 이름을 부여
- CoroutineExceptionHandler
- 코루틴 내부에서 발생한 예외를 처리하기 위한 핸들러
3. Coroutine Context와 Element의 병합
Coroutine Context는 연산자 +를 사용하여 추가할 수 있다.
Context는 각 요소가 중복되지 않는 경우 모든 요소를 포함하며 중복되는 경우 나중에 추가된 요소가 우선한다.
val context1 = Dispatchers.IO + CoroutineName("Context1")
val context2 = Dispatchers.Default + CoroutineName("Context2")
val mergedContext = context1 + context2
println(mergedContext[CoroutineName]) // Output: CoroutineName("Context2")
4. 커스텀 Context 필요성
- 명확한 스레드 관리
- 당연하게도 적절한 디스패쳐를 설정해 효율적으로 코루틴을 사용할 수 있게 해준다.
- 디버깅 및 로깅
- 코루틴이 복잡해질수록 어떤 코루틴이 어떤 작업을 수행하는지 식별하기 어려워질 수 있다. CoroutineName을 사용하면 디버깅이나 로깅 시 어떤 코루틴에서 로그가 발생했는지 쉽게 추적할 수 있게 된다.
launch(CoroutineName("DataFetch")) {
println("Running: ${coroutineContext[CoroutineName]?.name}")
}
- 특별한 예외 처리
- 기본적으로 코루틴 예외는 부모 코루틴으로 전파되지만 특정 코루틴에서만 별도로 처리해야 하는 상황이 있을 수 있다.
val handler = CoroutineExceptionHandler { _, exception ->
println("Caught exception: $exception")
}
launch(handler) {
throw RuntimeException("Test exception")
}
- 구조적 동시성 관리
- 여러 코루틴의 생명 주기를 관리하기 위해 커스텀 Job을 추가하거나 부모 코루틴과 다른 생명 주기를 가진 코루틴을 만들어야 할 수 있다.
val parentJob = Job()
launch(parentJob) {
// 이 코루틴은 parentJob의 영향을 받음
}
참고
'개념 저장소 > coroutine' 카테고리의 다른 글
코루틴에서의 예외 처리 (0) | 2024.12.22 |
---|---|
구조화된 동시성 (2) | 2024.12.21 |
Deferred, async/await, withContext (0) | 2024.12.09 |
Job과 코루틴 제어 (0) | 2024.12.08 |
Dispatcher (2) | 2024.12.07 |