본문 바로가기
Develop/Reactor+Coroutine

[Coroutine] 코루틴 스코프 함수

by 연로그 2024. 6. 29.
반응형

코루틴 스터디를 하며 정리 중인 시리즈 글

  1. 왜 코루틴을 써야할까?
  2. [Coroutine] 코루틴 빌더, 코루틴 컨텍스트
  3. [Coroutine] 구조화된 동시성
  4. [Coroutine] 코루틴 스코프 함수
  5. [Coroutine] 디스패처
  6. [Coroutine] 코루틴과 공유상태

 


🎉 coroutineScope

 

코루틴 스코프 함수는 중단함수 내에서 스코프가 필요할 때 사용한다. coroutineScope는 코루틴 스코프 함수의 일종이다.

 

🔸 coroutineScope 로 인해 중단되는 코루틴

coroutineScope는 새로운 코루틴을 생성하면 작업이 끝날 때까지 coroutineScope를 호출한 코루틴을 중단시킨다. 아래 예제를 보면 println이 순차적으로 진행되는 것을 볼 수 있다.

suspend fun main(): Unit = runBlocking {
    launch { println("launch 1") }
    coroutineScope {
        delay(100)
        launch { println("launch 2") }
    }
    launch { println("launch 3") }
}

 

🔸 coroutineScope 와 예외

coroutineScope에 속한 자식에서 예외가 발생하면 다른 모든 자식이 취소되고, 예외가 다시 던져진다.

@Test
fun 자식에서_예외_발생_시_다른_자식들도_취소() = runTest {
    val job = launch {
        coroutineScope {
            launch {
                println("자식 1")
                throw RuntimeException()
            }
            launch {
                delay(1000)
                println("자식 2")
            }
        }
    }
    job.join()
}

 

 


🎉 그 외

 

사실 코루틴 스코프 함수는 coroutineScope 외에도 supervisorScope, withContext, withTimeout 등도 있다. 예제를 통해 간단히 확인하고 넘어가도록 하겠다.

 

🔸 supervisorScope 

  • Job 대신 SupervisorJob 사용
  • 자식 코루틴이 예외를 던져도 취소되지 않음
  • 서로 독립적인 작업을 시작하는 함수에서 주로 사용
@Test
fun supervisorScope_예제() = runTest {
    supervisorScope {
        launch {
            println("launch 1")
            throw Error()
        }
        launch {
            delay(100)
            println("launch 2")
        }
    }
}

 

🔸 withContext

  • 스코프의 컨텍스트 변경 가능
  • 기존 스코프와 컨텍스트가 다른 코루틴 스코프를 설정하기 위해주로 사용
@OptIn(ExperimentalStdlibApi::class)
@Test
fun withContext_예제() = runTest {
    println(coroutineContext[CoroutineDispatcher.Key])
    
    withContext(Dispatchers.IO) { 
        println(coroutineContext[CoroutineDispatcher.Key])
        launch { println(coroutineContext[CoroutineDispatcher.Key]) }
    }
}

 

 

🔸 withTimeout

  • 람다 수행 시 시간 제한이 있음
  • 시간 제한이 넘으면 TimeoutCancellationException 발생
  • TimeoutCancellationException이 발생하면 해당 코루틴만 취소되고, 부모에게 영향을 주지 않음

 

예제1

@Test
fun withTimeout_예제() = runTest {
    withTimeout(1000) {
        launch {
            println("launch no delay")
        }
        launch {
            delay(1000) // TimeoutCancellationException 발생
            println("launch with delay")
        }
    }
}

 

예제2

@Test
fun withTimeout_예제() = runTest {
    println("start")
    launch {
        withTimeout(1000) {
            launch {
                delay(1000)
                println("launch with delay")
            }
            launch {
                println("launch without delay")
            }
        }
    }

    delay(1000)
    println("end") // withTimeout으로 인한 예외는 부모 코루틴에는 영향주지 않아 무사히 출력
}

 


참고

반응형