Lined Notebook

Coroutines?

by HeshAlgo

코루틴을 공부하기에 앞서 왜 코루틴을 써야하는지 간단하게 생각해보았습니다. 

서비스가 점점 커지면서 대용량의 트래픽을 처리하기 위해 좋은 성능을 내기 위한 방법들은 여러가지가 있겠지만 그 중 하나는 비동기 프로그래밍을 사용하는 방법이지 않을까 싶습니다. 

우리 회사는 MSA로 전환한 이후 부터 언어를 Kotlin으로 사용하고 있습니다.

Kotlin을 사용하게 되면서 Coroutines도 같이 사용을 하고 있는데 이제는 이 Coroutines에 대해서...어떻게 동작이 이루어지고 runBlocking, launch, asnyc 등과 같은 함수들에 대해서도 알아야 되지 않을까 싶습니다. 😭😭😭

그동안 모르고 사용해왔던 저의 모습을 반성하면서 이제는 제대로 알고 사용하기위해 해당 글을 작성해봅니다. 

 

1. Coroutines?

코루틴은 실행을 일시 중단(suspend)하고 재개(resume)할 수 있는 여러 진입지점을 허용합니다.

우리가 평소에 짜는 함수 호출의 경우 return문을 만나기 전까지 쓰레드는 블락되어 있습니다.

메인쓰레드가 1번 부터 실행을 시작하여 2번인 callFunction()을 호출 후 return문을 반환한 뒤 3번 함수의 실행을 끝으로 main 함수는 종료됩니다.

즉, 2번인 callFunction을 진입하는 동시에 메인 쓰레드가 Block 됩니다.

여기까지는 프로그래머라면 기본적으로 알고있는 상식일겁니다. 

 

하지만, 코루틴은 다릅니다.

return문이나 마지막 닫는 괄호를 만나지 않더라도 언제든지 탈출(suspend)이 가능하고 재개(resume)가 가능합니다.

 

1) 협력형 멀티 태스킹

네모 블럭을 함수로 표현하겠습니다.

코루틴의 동작을 간단하게 설명드리자면 Main 쓰레드가 코루틴 스코프에 진입을 하게 되고 파란색 네모란 함수에 진입을 했을때 굳이 return문을 안만나도 해당 함수를 빠져나갈수 있습니다. 그리고 언제든지 다시 나갔던 그지점으로 돌아와 재개할수 있습니다. 

이게 무슨말인가?? 싶기도 한데 한번 밑의 코드의 예시를 보도록 하겠습니다.

1) Main Thread가 coroutinScope에 진입을 합니다.

-> 해당 Scope에 진입했다는 것은 진입점과 탈출점이 여러개가 될 수 있는 자격이 주어집니다!

 

2) coroutinScope에 진입 후 Coroutine Start!!!라는 메세지가 찍힙니다.

-> coroutinScope에 진입은 하였지만 suspend라는 키워드를 만나지 않았기 때문에 별다른 효과를 보진 못할것입니다.

 

3) runFunction1()이라는 함수에 진입을 합니다. 여기서! runFunction1()이라는 함수는 suspend키워드를 가지고 있습니다.

-> 해당 runFunction1() 함수에 진입을 한 후 return문에 도달할때까지 기다리지 않아도 언제든지 해당 Main Thread는 중간에 빠져나올수 있습니다.

-> 그러면 runFunction1()은 실행이 되지 않는것인가??? 아닙니다!! Main Thread에서 동시성 프로그래밍으로 작동할수도 있고 다른 Thread에서 돌아갈수도 있고 개발자가 코드를 어떻게 짜느냐에 따라 다릅니다.

여기서는 그냥 다른 Thread에 의해서 실행이 되고 있다고 생가하면 될것 같습니다.

 

4) 그렇게 Main Tread가 다른 일을 하다가 runFunction1()의 할일이 끝났다고 연락을 받게 되면 아까 중간에 탈출했던 coroutinScope로 다시 진입을 하게 됩니다. 그리고 runFunction1()에서 멈춰있었으니 그 다음 runFunction2()부터 다시 재개(resume)합니다.

 

후..이게 제가 첫 신입때는 뭔말인가...싶었는데 이제는 어느정도 동작의 흐름이 이해가 되서 정리가 되는것 같습니다.

아무튼 기본적으로 해당 코루틴은 이런식의 흐름을 갖는다고 이해하면 될 것 같습니다.

해당 개념을 협력형 멀티 태스킹이라고도 불리기 때문에 머릿속에 잘 기억해두면 좋을것 같습니다.

 

2) 동시성 프로그래밍

동시성 프로그래밍이란 동시에 여러 작업을 수행할 수 있는 능력을 가지도록 설계하고 구현하는 프로그래밍 방식입니다.

위에 코루틴 스코프에 진입하게 되면 중간에 빠져나오고 들어가고, 빠져나오고 들어가고의 기능을 수행하는것은 동시성 프로드래밍을 가능하게 합니다. 

 

동시성 프로그래밍은 병렬성 프로그래밍과 다른 개념입니다.

동시성 프로그래밍의 예를 들면 요리를 할때 오른손으로 스테이크도 굽고 소스도 만들고를 빠르게 왔다갔다 하면서 작업을 해 마치 동시에 요리를 하는것처럼 보이는 것입니다. 

병렬성 프로그래밍은 오른손엔 스테이크를 굽고 왼손에는 소스를 만들고의 작업을 하는 방식으로 이해하시면 될 것 같습니다.

그렇게 때문에 코루틴은 동시성을 지원합니다.

Main Tread에서 코루틴이 2개가 있다고 가정합니다.

먼저 왼쪽은 스테이크를 굽는 과정이고 오른쪽은 소스를 만드는 과정입니다.

Main Tread가 먼저 왼쪽 코루틴인 cookSteak()를 만났다고 가정했을때, 해당 Main Thread는 coroutinScope에 진입과 동시에 중간에 나갔다 들어올수 있는 힘을 얻게 됩니다.

그리고 steakSeasoning()을 만나게 되면 해당 Main Thread는 cookSteak() 코루틴을 빠져나옵니다. 

그렇다고 해서 Main Tread는 놀지 않고 다른 suspend 함수를 찾거나 돌아가야 되는지의 일을 합니다. 

왼쪽 코루틴을 빠져나온 Main Tread는 이제 오른쪽 코루틴을 만나게 되어 cookSource()에 진입합니다. 

오른쪽 코루틴도 왼쪽과 동일하게 동작이 이루어지고 스테이크를 굽고, 소스를 만들고의 왔다갔다의 작업을 굉장히 빠르게 수행합니다.

이렇게 코루틴을 사용해 하나의 Thread에서 동시성 프로그래밍이 가능합니다.

 

코루틴은 위와 같은 동작방식으로 이루어진다고 생각하면 될것같습니다.

내용이 많이 어렵기도하고...한번만 봐서는 이해가 잘 안갈수도 있기 때문에 여러번 반복해서 

머릿속으로 이해될때까지 입력해놓는것이 좋은 방법이라 생각됩니다.

 

블로그의 정보

꾸준히 공부하는 개발 노트

HeshAlgo

활동하기