It's easy, if you try

[안드로이드] Corutine 이란? (Kotlin) 본문

안드로이드

[안드로이드] Corutine 이란? (Kotlin)

s5he2 2021. 2. 10. 23:42
반응형

코루틴이 뭘까 ? (Corutine)

코틀린 뿐만 아니라 파이썬, Javascript 등 여러언어에서 지원하고 있는 개념 !

새로운 개념이 아닌 초창기부터 존재하던 개념이다.

근데 왜 지금 공부하는 걸까?

코루틴을 사용하면 비동기 처리가 너무나도 쉽게 이루어질 수 있다.

코루틴 키워드 3가지

  1. 협력형 멀티 태스킹
  2. 동시성 프로그래밍 지원
  3. 비동기 처리를 쉽게 도와줌

 

특징1. 협력형 멀티 태스킹 (Co + rutine)

Co: 협력, 함께 라는 의미를 지니고 있다.

rutine:  하나의 태스크, 함수

 

즉, 코루틴은 협력하는 함수이다.

여기서 rutine은 main/ sub로 나누어지는데 흔하게 볼 수 있는 main 함수와 sub 함수 같은 개념으로 이해하면 편하다.

일반 함수는 루틴에 진입점(함수 호출)과 탈출점(return이나 닫는 괄호’}’)이 명확하다. 코루틴은 진입점과 탈출점이 여러개이다.

suspend 로 선언된 함수를 만나면 코루틴 밖으로 잠시 나갈 수 있다.

fun drawPerson () {
  startCorutine {  // startCourutine은 실제로 존재하는 코루틴 빌더는 아니다. 이해를 돕기 위해 작성했다.
    drawHead()
    drawBody()
  }
}
​
suspend fun drawHead() {
  delay(2000)
  ...
}
​
suspend fun drawBody() {
  delay(1000)
  ...
}
  1. 스레드의 main 함수가 drawPerson() 호출, 하나의 코루틴 블럭(함수)이 생성된다.
  2. 코루틴 함수가 실행되는 과정에서 suspend 키워드를 가진 함수를 만나게 되면, 더 이상 아래 코드를 실행하지 않고 멈추고(suspend) 코루틴 block을 탈출한다.
  3. ⭐️ 메인 스레드의 다른 코드들이 실행된다. (그리고 여전히 drawHead 는 어디선가 실행되고 있다.)
  4. 다른 코드들이 실행되다가도, drawHead가 끝이 나면 다시 코루틴(1번 블럭)으로 진입해 멈춘 부분(drawHead) 아래부터 다시 실행된다.

 

특징 2. 동시성 프로그래밍

반대 되는 개념으로는 병렬성 프로그래밍이 있다.

예를 들어, 1번 도화지와 2번 도화지에 그림을 그린다고 하자.

  • 동시성 프로그래밍 : 한 손으로만 1번 도화지에 조금, 2번 도화지에 조금 그리는 것을 빠르게 반복한다. 멀리서 봤을 땐 마치 동시에 그림이 그려지는 것처럼 보일 것이다.
  • 병렬성 프로그래밍 : 두 손을 이용해 1번 도화지와 2번 도화지에 그림을 그리는 것이다. 실제로 같은 시간동안 그림이 그려지고 있다.
fun drawPerson () {
  startCorutine {  // startCourutine은 실제로 존재하는 코루틴 빌더는 아니다. 이해를 돕기 위해 작성했다.
    drawHead()
    drawBody()
  }
}
​
suspend fun drawHead() {
  delay(2000) // 2초동안 작업을 하지만 Thread를 블락 시키지 않으므로 다른 일을 할 수 있다.
  ...
}
​
suspend fun drawBody() {
  delay(1000)
  ...
}

다시 위 코드를 보며 예시를 생각해보자. 쓰레드에서 suspend 함수인 drawHead()를 만났을 때, 코루틴을 빠져나갈 수 있다. 이때, 메인쓰레드는 다른 suspend 함수들을 찾거나 resume 되어지는 다른 코드들을 찾는다.

  • 만약 drawHead() 안에서 다른 쓰레드를 실행시킨다면 병행적으로도 실행이 가능하다.

코루틴을 빠져나온 쓰레드가 다른 코루틴안의 suspend 함수를 만나게 되면 이때, 동시성 프로그래밍이 가능해진다. (도화지 예시와 같은 현상이 일어난다.)

또한 코루틴을 생성해서 동시성 프로그래밍을 하는 것은, 쓰레드를 사용해서 동시성 프로그래밍을 하는 것과 차원이 다른 효율성을 제공한다.

 

왜?

쓰레드를 이용해 동시성 프로그래밍을 가능하게 하려면, CPU가 A쓰레드를 조금, B쓰레드를 조금씩 매번 점유했다가 놓아주어야하는데(이를 컨텍스트 스위칭이라고 한다.) 이 작업은 함수를 왔다 갔다(코루틴) 하는 방식과는 다르게 꽤 비용이 드는 작업이다!

"함수형 코루틴" 에서는 이를 2000개 미만의 스레드는 1.5GB 이상의 메모리가 필요하지만, 100만 개의 코루틴은 700MB 미만의 메모리가 필요하다고 말하고 있다.

 

특징 3. 비동기 처리를 쉽게 도와준다.

코루틴 suspend 함수 내에 비동기 코드를 쉽게 구현할 수 있다.

예시

짜장면을 시켰는데, 짜장면을 먹기까지의 과정은

  1. 짜장면 비닐 벗기기
  2. 소스 붓기
  3. 섞기
  4. 먹기

이다. 이 과정들은 동시에 일어날 수 없고, 얼마나 걸릴지 알 수 없는 비동기 작업이다. 이를 KotlinCorutine을 이용해 구현해보자

suspend eatDinner(food: FOOD) {
 val 짜장면 = food
 try {
   val 비닐 벗겨진 짜장면 = removeVinyl(짜장면)
   val 소스가 부어진 짜장면 = addSauce(비닐 벗겨진 짜장면)
   val 섞어진 짜장면 = shackPlate(소스가 부어진 짜장면)
   val 다먹은 짜장면 = eatJjaJang(섞어진 짜장면)
   
   다먹은 짜장면.doRecycle()
} catch (e: Exception) {
   실패시 처리()
  }
}

위에 보이듯이 분명한 비동기 코드이지만 아주 간단히 구현됐다!

이는 eatDinner()가 코루틴 함수이기 때문이다. eatDinner()에서 removeVinyl 함수를 만남과 동시에 잠시 eatDinner()를 빠져 나갔다가 removeVinyl의 일이 끝나면 다시 eatDinner()로 돌아올 수 있기 때문에 비동기 작업들의 순서가 정확히 지켜질 수 있는 것이다!

 

마무리

비동기 처리를 이렇게 쉽게 도와주는 코루틴을 이제라도 알아서 다행인 것 같다. 

 

참고

코틀린 코루틴(corutine) 개념 익히기

반응형
Comments