brunch

You can make anything
by writing

C.S.Lewis

by 서준수 Aug 20. 2023

코루틴 빌더 (Coroutine Builder)

코틀린 코루틴 (2)

코루틴 빌더 (Coroutine Builder)


코루틴을 만드는 함수를 코루틴 빌더(Coroutine Builder)라고 한다. 앞서 살펴본 runBlocking도 코루틴 빌더이다. 코루틴을 만든다는 말에는 코루틴을 실행한다는 의미도 포함되어 있다.


대표적인 코루틴 빌더에는 runBlocking을 포함하여 launch, async, withContext 등이 있다. (좀 더 엄격히 구분하면 withContext는 Scoping Function이다.) 여기서는 가장 일반적인 launch를 예시로 살펴본다. 코루틴 빌더를 학습할 때 모두 살펴보면 좋다고 생각할 수도 있다. 하지만 지금은 코루틴 빌더가 무엇인지 개념을 알아가는 것이 목표이다. 왜냐하면 다른 코루틴 빌더를 알기 위해서는 필요한 다른 개념들이 있기 때문이다. launch도 마찬가지로 추후에 다시 등장할 것이다.


그리고 이제부터 runBlocking을 사용할 때 expression body로 사용할 것이다. 왜 처음에는 block body로 사용했냐면 혹시라도 runBlocking은 꼭 expression body로 써야 한다고 오해할까 봐 그렇게 했다.


이번에도 일단 코드를 먼저 보자. 다음 코드의 실행 결과는 어떻게 될까?

launch의 등장으로 혼란스러울 것이다. 하지만 runBlocking이 어떤 역할을 하는지 기억한다면 조금은 예상할 수 있다. runBlocking은 코루틴이 완료될 때까지 현재 스레드를 차단(blocking)한다고 했다. 차단은 runBlocking 블록 내부의 모든 작업이 실행될 때까지 스레드를 차지하는 것을 의미한다고 했다. launch는 새로운 코루틴을 만드는 코루틴 빌더라고 했다.


실제로 실행해 보면 예상처럼 동작한다. 실행 결과는 다음과 같다.

Start, main thread!
End, main thread!
Hello, main thread!

실행 결과를 살펴보면 모두 메인 스레드에서 실행된 것을 볼 수 있다. 이것으로 runBlocking이 현재 차단한 스레드는 메인 스레드라는 것을 알 수 있다.


runBlocking 내부에서 실행은 순차적으로 발생한다. 여기서 이런 결과가 나온 것은 launch가 비동기적으로 실행되기 때문이다. 실행 결과를 보면 이미 runBlocking은 종료되었다. 즉 runBlocking은 launch의 완료를 기다려주지 않는다. runBlocking의 종료가 메인 스레드의 파괴를 의미하는 것은 아니기 때문에 메인 스레드에서 실행된 launch는 비동기적으로 실행 후 완료되는 것이다.


runBlocking도 코루틴 빌더라고 했다. 때문에 launch도 runBlocking을 통해서 알게 된 특징들과 공통되는 부분이 있다. runBlocking의 블록 내 수신 객체가 CoroutineScope였던 것처럼 launch의 블록 내 수신 객체도 마찬가지로 CoroutineScope이다. 따라서 launch 블록 내부에서 새로운 코루틴 실행되는 것이다.


다른 부분도 있다. 먼저 runBlocking의 가장 큰 특징인 현재 스레드 차단 기능은 launch에게 없다. 또한 launch는 CoroutineScope 내에서만 선언될 수 있다. 따라서 runBlocking을 제거하거나 runBlocking 블록 외부에서 launch를 선언하면 에러가 발생한다.


그러면 의문이 들 수 있다. runBlocking은 주로 main() 함수 또는 테스트에서 사용한다고 했다. 그러면 runBlocking을 사용하지 않고서는 어떻게 launch를 사용하지? CoroutineScope를 선언하는 방법이 있지 않을까? 이 정도로 예상하고 넘어가면 된다.


그리고 launch의 주요한 특징은 새로운 코루틴을 만들어서 동시에 코드가 실행되도록 하는 것이다. 조금 더 자세히 설명하자면 launch를 통해 생성되는 새로운 코루틴은 각각 독립적이며, 만약 launch A와 launch B가 있다면 비동기적으로 동작하여 동시성을 이룬다. (비동기, 동시성 이런 개념을 몰라서 이해가 안 된다면 그냥 읽고 넘어가면 된다.) 추후에 다른 개념들을 학습하고 다시 launch를 다룰 때 더 자세히 살펴볼 수 있을 것이다.


아무튼 여기서 중요한 것은 launch가 CoroutineScope 내에서 선언되어야 한다는 것이고 그렇다는 것은 다른 코루틴 빌더도 마찬가지라는 의미다. 또 비동기적으로 동작하는 것도 동일하다. 결국 코루틴은 이러한 코루틴 빌더를 통해서 만들어지고 비동기적인 작업을 하는 녀석이다.


요약하자.

- 코루틴을 만드는 함수를 코루틴 빌더라고 한다.
- 코루틴 빌더는 CoroutineScope 내부에 선언되어야 한다.
- 코루틴 빌더 블록 내부 역시 CoroutineScope이다.
- 코루틴 빌더를 통해 생성된 코루틴은 비동기적으로 동작한다.
- runBlocking은 내부 코루틴의 완료를 기다려 주지 않는다.
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari