코루틴(Coroutine) |Kotlin Study

hoya·2021년 12월 18일
0

Kotlin Study

목록 보기
2/7
post-thumbnail

👨‍👨‍👦‍👦 Coroutine

코루틴은 실행을 지연하고 재개할 수 있도록 하여 비선점형 멀티태스킹을 위한 서브루틴을 일반화하는 컴퓨터 프로그램 구성 요소입니다. - Wikipedia

말이 굉장히 난해한데, 어떤 뜻인지 하나하나씩 파헤쳐보도록 하자.

📌 Routine? Subroutine?

루틴은, 어떤 작업을 정의한 명령어의 집합을 의미한다. 이를 이용해 프로그램을 더 짧으면서 읽고 쓰기 쉽게 만들 수 있고, 하나의 루틴이 다수의 프로그램에서 사용될 수 있다. 단순히 하나의 함수가 루틴을 의미하는 것은 아니고, 복잡한 루틴의 경우 여러 함수를 조합해서 만들기도 한다. 결국, 크고 작은 여러 루틴을 합치며 프로그램이 만들어지는 것이다.

프로그램의 주된 흐름에 해당하는 루틴을 메인루틴이라고 부르며, 이 메인루틴이 간단한 작업을 처리하기 위해 호출하는 루틴을 서브루틴이라고 부른다. 쉽게 정리하자면, 서브루틴을 함수와 비슷한 느낌이라고 생각하면 된다.

서브루틴은 시작과 끝이 명확하다. return 이라던지, }와 같이 닫는 괄호를 만나면 서브루틴을 빠져나와 호출자로 돌아가게 된다. 이로 인해 메인루틴에 종속적이다.

자, 루틴과 서브루틴에 대해 간략하게 알아보았으니 지금부터 코루틴과 일반 루틴의 차이를 알아보도록 하자.

  1. 코루틴은 메인루틴, 서브루틴의 개념이 존재하지 않는다.
  2. 코루틴은 끝이 명확하지 않다. 함수에 진입할 수 있는 지점도 여러개이고, 함수를 빠져나갈 수 있는 지점도 여러개이다. 즉, return을 만나지 않더라도 언제든지 나갈 수 있고 다시 들어올 수 있다.
  3. 이로 인해, 메인루틴에 종속적이지 않고 대등하게 데이터를 주고받을 수 있다.

위의 코루틴의 차이들을 보면, 코루틴이라는 이름에 대해 이해가 갈 것이다. co + routine 으로 구성이 되어있는데, co 라는 의미가 협력 이라는 의미이다. 이름에서 알 수 있듯이 코루틴과 코루틴은 서로 대등한 관계를 지니고 있으며, 언제든지 호출하며 협력할 수 있다는 것이 핵심이라고 볼 수 있다.


📌 지연(suspend)? 재개(resume)?

위에서 코루틴은 함수에 진입할 수 있는 지점도 여러개, 빠져나갈 수 있는 지점도 여러개라고 적었는데, 이와 관련된 키워드가 바로 suspendresume 이다. 아래의 코드를 보며 두 키워드에 대해 알아보자.

fun main() {
    doSomeThing()
    
    println("on Main Thread")
}

fun doSomeThing() {
   onCoroutine { // 실제 사용하지 않는 코루틴 빌더이나, 예를 쉽게 들기 위해 사용
	doSomethingOne()
	doSomethingTwo()
   }
}

suspend fun doSomethingOne() {
    delay(1000L) // 아무것도 하지 않는 일을 한다.
    println("coroutine 1 on")
}

suspend fun doSomethingTwo() {
    delay(1000L)
    println("coroutine 2 on")
}

  1. doSomeThing() 함수를 만나며 코루틴 블럭을 생성한다.
  2. 메인 스레드와 코루틴 블럭을 왔다갔다하며 suspend 함수를 찾는다. (동시성)
  3. doOne() 함수를 만나며, 코루틴 블럭을 빠져나오고, 메인 스레드는 자신의 역할을 수행한다. 그 와중에도 코루틴 블럭에서 doOne() 함수는 실행되고 있다.
  4. delay가 종료되면서 println 메소드를 실행하고, doOne() 함수가 끝나며 다시 코루틴 블럭으로 돌아온다.
  5. doTwo() 함수를 만나며 위의 과정을 반복한다.

위의 과정을 보면 코루틴 블럭을 언제든지 나가고, 다시 진입하는 것을 확인할 수 있다. suspend 함수를 만나면 코루틴 블럭을 빠져나가고, 그 함수가 종료되면 resume, 즉 재개되어 다시 코루틴 블럭으로 돌아오는 것이 핵심이다. 그리고 이는 동시성이라는 키워드를 자연스럽게 떠올리게 하는데, 어떤 식으로 연관이 되는건지 이어서 알아보도록 하자.


📌 선점? 비선점?

선점과 비선점 관련해서는 운영체제 관련 지식이 조금 필요하다. 기본적으로, 운영체제는 프로세스, 스레드와 같은 Task를 관리한다. 이 역할을 스케줄러가 담당하는데, 스케줄러는 CPU의 공간을 효율적으로 활용하기 위해 우선순위에 따라 태스크를 실행한다. 그림과 함께 이해해보자.

  1. 태스크 생성시 대기 큐로 이동되고, 대기 큐에 있는 태스크를 우선순위에 따라 스케줄러가 실행 큐로 보낸다.
  2. 실행 큐에서도 우선순위에 따라 스케줄러가 CPU로 보낸다.
  3. CPU의 코어에서 이를 실행하고, 실행이 너무 길면 다시 대기 큐로 보낸다.

대략 위의 그림과 같이 스케줄링이 진행되는데, 여기서 나오는 것이 선점과 비선점이다. 코어에서 이미 실행되고 있는 태스크가 있을텐데, 이를 중단시키고 강제로 다른 태스크를 올리는 것선점형 스케줄링, 태스크의 실행을 보장하고 순서대로 처리되게 하는 것비선점형 스케줄링이다. 특히 비선점형 스케줄링의 경우 Context Switching에 의한 오버헤드가 적다.

코루틴은 비선점 멀티태스킹을 채택했고, 그럼으로서 등장하는 특징이 바로 동시성이다. 동시성은 병행성의 반대 이야기로, 동시에 실행되는 것처럼 보이지만 사실은 하나하나씩 번갈아가며 실행하는 것을 의미한다.

주의점으로 위에서 예로 든 코드를 보면 알겠지만, 코루틴의 경우 대기 및 실행, 지연등의 시점이 운영체제의 스케줄러가 아니라 프로그래머가 직접 결정하거나 이벤트에 의해 결정된다는 것을 유념해야 한다.


📝 정리

  • 코루틴은 비선점형 멀티태스킹이다.
  • 코루틴은 협력형 멀티태스킹으로, 서로를 언제든지 호출이 가능하며 협력하여 작업을 처리한다.
  • 코루틴은 언제 어디서든 빠져나가고 다시 돌아올 수 있다.
  • 코루틴은 동시성 프로그래밍을 지원한다.
  • 코루틴은 스케줄러가 아닌 프로그래머 혹은 이벤트에 의해 실행, 지연, 재개 시점이 결정된다.
  • 코루틴은 하나의 스레드 안에서 돌아가기 때문에 Context Switching 비용이 발생하지 않는다. 즉, 코루틴은 가벼운 비용으로 비동기 작업을 실행할 수 있다.

참고 및 출처

지식나눔으로 누구에게나 따뜻한 블로그
코틀린, 코루틴 기초
오리의 프로그래밍 팁 02 - 코틀린의 코루틴 이해하기
코틀린 코루틴(coroutine) 개념익히기

profile
즐겁게 하자 🤭

0개의 댓글