관리 메뉴

피터의 개발이야기

[kotlin] 비동기 처리, coroutine 장점은 무엇인가? 본문

Programming/Kotlin

[kotlin] 비동기 처리, coroutine 장점은 무엇인가?

기록하는 백앤드개발자 2024. 5. 27. 10:10
반응형

ㅁ 들어가며

ㅇ 코틀린 코루틴의 개념을 정리하였다.

ㅇ 최근 트랜드인 비동기처리에 있어서 코틀린 코루틴의 차이점에 대해 알아보았다.

 

ㅁ Coroutine이란?

Coroutines은 Co + Routines 약자로, Co 는 Cooperation을 의미하고, Routines는 하나의 테스크를 의미한다. 풀어서 말하자면, 서로 협력하는 함수를 의미한다. 

 

 

ㅁ 비동기 처리 코딩 방식

ㅇ 비동기 코딩방식의 변화를 알아보고, 코틀린 코루틴의 코드가 얼마나 더 직관적인지 알아보자.

 

Callback

fun goWork(person: Person) {
  val 잠든패카= person
  wakeUp(잠든패카){ 비몽사몽한패카 ->
    takeShower(비몽사몽한패카){ 깨끗한패카 ->
      putonShirt(깨끗한패카){ 옷입은패카 ->
        getOnBus(옷입은패카){ 버스를탄패카 ->
          finish(버스를탄용준){ 출근한패카 ->
            출근한패카.doWork()
          } // finish end
        } // getOnBus end
      }// putonShirt end
    }// takeShower end 
  } // wakeUp end
}

ㅇ Callback 함수의 기초는 람다 표현식이다.

   ㄴ 람다 표현식은 메소드의 매개변수로 전달될 수도 있으며, 메소드의 결과값으로 반환될 수 있다.

   ㄴ Java SE 8부터는 이러한 람다 표현식을 사용하여 자바에서도 함수형 프로그래밍을 할 수 있게 되었다.

   ㄴ 람다  방식을 이용해 하나의 테스크가 마치면 callback 형태로 구현하였다.

ㅇ 콜백으로 비동기처리를 구현하면 흔히 이야기 하는 콜백 지옥에 빠질 수 있다.

ㅇ 각 테스크를 지나고 콜백의 회차가 높아질수록 어질어질해지는 코드가 되어, 이를 해소하기 위해  "// 기능명 end"로 표시하였다.

 

RxKotlin

fun goWork(person: Person) {
  val 잠든패카= person
  
  Observable
    .just(person)
    .observeOn(MAIN_Thread)
    .subscribeOn(IO_Thread)
    .flatMap{ 잠든패카 -> wakeUp(잠든패카)}
    .flatMap{ 비몽사몽한패카 -> takeShower(비몽사몽한패카)}
    .flatMap{ 깨끗한패카 -> putOnshirt(깨끗한패카)}
    .flatMap{ 옷입은패카 -> getOnBus(옷입은패카)}
    .flatMap{ 버스를탄패카 -> finish(버스를탄패카)}
    .subscribet({ 출근한패카 -> 
      출근한패카.doWork()
	}, {
      실패했을때처리( )
	}
}

ㅇ RxKotlin는 옵저버 패턴 구조로 되어 있다. 

  ㄴ 옵저번 패턴이란,
    옵저버(관찰자)들이 관찰하고 있는 대상의 상태가 변경되면 각 관찰자들에게 알림을 받아 조치를 취하는 행동 패턴이다.
 

  ㄴ Pub/Sub(발행/구독) 모델로 알려져 있다.

ㅇ 콜백 코드에 비해 flatMap을 기준으로 이전 테스크의 결과를 받아 후속 테스크가 수행되기 때문에 보기에 편하다.

ㅇ 하지만, Rx의 캡슐화되고 함수화로 내제화된 코드를 배워야하는 러닝커버가 있다.

  ㄴ just, observerOn, subscribeOn의 개념뿐만 아니라 에러처리를 위한 개별 함수를 공부해야한다.

 ㄴ 내제화된 코드에서 수행할 때에 내 생각과 의도치 않게 움직이는 경우가 많았다.

 

Kotlin + coroutine

suspend goCompany(person: Person){
  val 잠든패카 = person

  try {
    val 비몽사몽한패카 = wakeUp(잠든패카)
    val 깨끗한패카 = takeShower(비몽사몽한패카)
    val 옷입은패카 = putonShtrt(깨끗한패카)
    val 버스를탄패카 = getonBus(옷입은패카)
    val 출근한패카 = finish(버스를탄패카)
    
    출근한패카.doWork()
  } catch (e: Exception){
    실패했을때처리( )
  }

ㅇ suspend를 사용하면 동기식 처럼 보이지만 비동기식으로 해석되어 실행되는 코드를 작성할 수 있다.

ㅇ 각 함수들의 작업은 언제 끝날지 모르지만 비동기 작업들의 순서는 정확히 지켜진다. 

ㅇ 이게 무슨 말인가? 동기랑 비동기랑 무슨 차이가 있지 모를 수 있다.

ㅇ 여기서 suspend에 대해 더 이해가 필요하다.

 

Coroutines의 기초 suspend 

coroutine을 이해하기 위해서는 suspend에 대해서 알아야 한다. suspend는 thread를 block하는 대신 처리를 중단한다. 

 

block
block은 thread를 점유하게 되어 thread는 다른 처리를 진행할 수 없다.

fun main(){
    println("Coroutine")
    Thread.sleep(3000L) // 3초 동안 thread를 점유한다.
    println("Hello")
}

결과: 

Coroutine
Hello

 

 

suspend
suspend는 coroutine 처리를 중단하고 thread를 해제한다. 해제하는 동안 다른 처리에 리소스를 활용할 수 있다.

import kotlinx.coroutines.*

fun main(): Unit = runBlocking {
    launch {
        delay(3000L) // 3초간 처리를 중단. 스레드가 다음 스팩을 수행하여 Hello가 표시된다.
        println("Coroutine")
    }
    println("Hello")
}

결과:

Hello
Coroutine

 

ㅁ 함께 보면 좋은 사이트

쾌락코딩 - 코틀린 코루틴(coroutine) 개념 익히기

devkuma - Kotlin 코루틴(Coroutines)

 

반응형
Comments