[Kotlin] Coroutine 첫 인상 살펴보기

H43RO·2021년 8월 20일
13

Kotlin 과 친해지기

목록 보기
4/18
post-thumbnail

💡 코틀린 공식 문서를 참고하여 작성한 글입니다 - Coroutines basics | Kotlin

코루틴 첫 인상 살펴보기

코루틴은 일시 중단이 가능한 (Suspendable) 작업 객체이다. 동시성을 보장한다는 관점에선 쓰레드와 비슷한 개념이다. 하지만, 코루틴은 그 어떤 쓰레드에도 종속되지 않는다. 한 코루틴 작업을 여러 쓰레드를 왔다갔다 하며 실행시킬 수도 있다. 만약 Thread 와 Coroutine 의 차이를 잘 모르겠다면, 이전에 필자가 작성한 포스팅을 참고하면 좋을 것 같다.

코루틴은 경량 쓰레드 (Light-weight Thread) 라는 개념으로 표현이 되곤 하는데, 실제 사용해보면 쓰레드와 용법, 뉘앙스가 매우 다르다.

그럼 코루틴을 대강 어떻게 사용하는 지 익히기 위해, 막무가내로 먼저 아래 기본 코루틴 예제를 살펴보고 코드를 하나씩 뜯어보자.

import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {  // Coroutine Scope
    launch {  // 새로운 코루틴 객체를 생성 & 해당 코루틴 동작 시작
        delay(1000L)  // Non-blocking 1초 딜레이 커맨드
        println("World!")  // 1초 후에 출력됨!
    }
    println("Hello!")  // Main Coroutine 은 delay 되지 않고 이어서 수행됨
}

// [실행결과]
// Hello
// World!

🚀 launch

이 키워드는 코루틴을 만드는 녀석 (Coroutine Builder) 이다. 다른 코드들과 동시에, 독립적으로 동작하는 코루틴 객체를 생성한다. 즉, 해당 코루틴이 속한 쓰레드를 블로킹하지 않는다. launch 스코프 내에 delay 를 1초 줬기 때문에, 바깥에 있는 println("Hello!") 가 먼저 동작되게 된다.

⛔️ delay

특별한 'Suspending (일시 중단)' 함수이다. 해당 코루틴을 특정 시간동안 일시 중단하는 기능을 수행한다. 그렇다고 속해있는 쓰레드가 통째로 Blocking 이 되는 것이 아니고, 일시 중단되는 동안 다른 코루틴이 동작하게 된다. (코루틴과 쓰레드의 차이점을 안다면, 이 말이 이해가 될 것이다.)

🏃🏻 runBlocking

이 키워드 또한 코루틴 객체를 만들게 되는데, 주목할 점은 코루틴 요소가 포함되지 않는 일반적인 코드 블럭과 이 runBlocking 스코프 내의 코루틴 동작 코드 블럭들을 이어준다는 점이다. 그래서 runBlocking 이 중괄호로 감싸고 있는 영역 자체를 Coroutine Scope 라고 한다.

그럼 한 번, runBlocking 녀석을 지워보자. 어떤가, 실행이 되는가?

Unresolved reference: launch

에러가 난다. launch 키워드는 코루틴 객체를 생성하는 녀석이므로, 반드시 runBlocking 스코프가 정의한 코루틴 스코프 내에 선언할 수 있기 때문에 참조할 수 없는 키워드라고 오류를 뿜는 것이다.

근데 runBlocking 이라는 이름의 의미는 뭘까? runBlocking 이라는 이름은 runBlocking 사용 시 이것이 속한 쓰레드를, 해당 코루틴 스코프 내의 모든 코루틴 동작들의 실행이 완료될 때 까지 블로킹한다는 뜻에서 비롯되었다.

그래서, 실제 프로덕션 코드에서는 runBlocking 을 거의 사용하지 않는다 (혹은 사용해선 안된다). 쓰레드는 고비용 리소스고, 이를 블로킹하는 것은 매우 비효율적이며, 코루틴의 존재 의의를 침해하는 수준이기 때문이다. 대신 테스트 코드 작성 시 종종 사용되고, 지금은 일단 이런 게 있다고 알아두면 된다. (나중에 runBlocking 에 대하여 자세히 다루는 포스팅도 올려보겠다)


구조화된 동시성

코루틴은 구조화된 동시성 원칙을 따른다. 구조화된 동시성 원칙이란, 새로운 코루틴 객체는 반드시 코루틴의 수명을 제한하는 특정 '코루틴 스코프' 내에서 실행되어야 한다는 원칙이다. 아까 다룬 예제를 다시 보면, runBlocking 이 그 역할을 하고 있다. 1초 딜레이 이후 World! 가 출력될 때 까지 기다렸다가, 출력이 되면 종료되는 이유이다.

우리는 앱 개발을 하면서, 수많은 코루틴을 만들고 지지고 볶고 할 것이다. 이럴 때 구조화된 동시성 원칙은 우리가 만든 코루틴 각각이 손실되지 않는 것을 보장하게 된다. 각 코루틴 스코프는, 스코프 내의 하위 코루틴들 각각이 모두 완료될 때 까지 종료될 수 없기 때문이다. 또한, 이러한 특성 덕분에 코루틴 코드에서 발생하는 모든 오류를 절대 빼먹지 않고 리포팅하도록 보장한다.


다음은 다양한 예제를 통해 코루틴 기본 용법을 익혀보는 포스팅을 업로드할 예정이다.

profile
어려울수록 기본에 미치고 열광하라

0개의 댓글