본문 바로가기

Android 개인공부

Coroutine 1부

반응형
  • 코루틴은 비동기적으로 실행되는 코드를 간소화하기 위해 Android에서 사용할 수 있는 동시 실행 설계 패턴
  • 코루틴은 Kotlin만의 고유한 개념이 아니며 다른 언어에서도 지원하고 있다.
    • Co: 함께
    • routine : 규칙적으로 하는 일의 통상적인 순서나 방법, 일반적으로 빈번히 사용할 수 있는 프로그램 또는 그 일부
  • 장점
    • 경량 : 코루틴은 실행 중인 스레드를 차단하지 않는 정지를 지원하므로 단일 스레드에서 많은 코루틴을 실행할 수 있다.
    • 메모리 누수 감소 : 구조화된 동시 실행을 사용하여 범위 내에서 작업을 실행
    • 취소 지원 : 실행 중인 코루틴 계층 구조를 통해 자동으로 취소가 전달
  • 일반적인 서브 루틴

fun main() {
	val addValue = plusOne(value)
}

fun plusONe(value: Int) {  // 서브루틴 진입
	val one = 1
	val addValue = value + one
	return adevalue // return을 만나면 탈출
}
  • 코루틴

fun drawPerson() {
	CoroutineScope.launch {
		drawHead()
		drawBody()
		drawLegs()
	}
}

suspend fun drawHead() {
	delay(2000)
}

suspend fun drawBody() {
	delay(2000)
}

suspend fun drawLegs() {
	delay(2000)
}
  • Main 함수가 drawPerson()을 호출하면 코루틴이 실행되고 suspend fun인 drawHead를 만나 아래 코드를 실행하지 않고 탈출 이후 다른 개발자가 정의한 다른 코드를 실행하다가 drawHead의 역할이 끝나면 탈출했던 drawPersn함수로 돌아와 drawBody부터 작업재개
  • 이러한 suspend 라는 키워드를 통해 함수를 중간에 빠져나왔다가, 다른 함수에 진입하고 하는 특성은 동시성 프로그래밍을 가능하게 함
  • 동시성 프로그래밍 ≠ 병렬성 프로그래밍

  • 왼쪽과 오른쪽 도화지를 아주빠르게 왔다 갔다 하면서 그림을 그리는 것 같은 셈
  • 이렇게 코루틴을 사용하여 쓰레드 하나에서 동시성 프로그래밍이 가능
  • 만약 쓰레드로 다음과 같이 동시성을 지원하게 된다면 CPU가 매번 쓰레드를 점유했다가 놓아주고를 반복하기에 컨텍스트 스위칭 비용이 많이 들게 된다.
  • 2000개 미만의 스레드에는 1.5GB 이상의 메모리가 필요하며 100만 개의 코루틴은 700MB 미만의 메모리가 필요하다 → 코루틴은 매우 가볍다 (경량)

 

  • CPS?
  • 코틀린의 코루틴은 suspend 키워드로 마킹된 함수를 CPS(Continuation Passing Style)로 변환하고, 이를 코루틴 빌더를 통해 적절한 스레드 상에서 시나리오에 따라 동작하도록 구성
interface Continuation<in T> {
  val context: CoroutineContext

  // 일시 중단을 일으킨 작업의 결과이다. 
  // 해당 함수가 Int 를 반환하는 함수를 호출하기위해 일시중지가 되면, T 값은 Int 가 된다.
  fun resume(value: T)

  // 예외를 전파할 때 사용된다.
  fun resumeWithExceptioin(exception: Throwable)
}
interface Continuation<in T> {
  val context: CoroutineContext

  // 일시 중단을 일으킨 작업의 결과이다. 
  // 해당 함수가 Int 를 반환하는 함수를 호출하기위해 일시중지가 되면, T 값은 Int 가 된다.
  fun resume(value: T)

  // 예외를 전파할 때 사용된다.
  fun resumeWithExceptioin(exception: Throwable)
}
  • 해당 코드를 빌드하면 컴파일러는 해당 함수를 INVOKESTATIC com/smp/coroutinesample/basic/BasicSample4Kt.sum (IILkotlin/coroutines/Continuation; )Ljava/lang/Object; 다음과 같은 형식으로 변경
  • 컴파일러가 함수의 가장 마지막 파라미터로 Continuation object 를 임의로 추가 했음을 알 수 있으며, suspend 함수에 Continuation라는 파라미터가 생겨서 코루틴은 이 함수를 CPS 형식으로 이용할 수 있다.

 

  • CoroutineScope
    • 코루틴이 작동하는 범위를 설정
    • 코루틴의 실행 범위, 코루틴 블록을 제어할 수 있는 단위를 정의하는 인터페이스 형태로 정의되어 있음
  • GlobalScope
    • 프로그램 어디서나 제어와 동작이 가능한 기본 범위
    • 어플리케이션 자체의 라이프싸이클과 함께 동작하기 때문에 별도의 라이프싸이클 관리가 필요하진 않다.
    • 하지만 리소스또는 메모리 누수가 발생하기 쉽고 코루틴의 구조적인 동시성 원칙을 따르지 않기 때문에 지양해야 한다.
  • MainScope
    • UI 컴포넌트를 위한 Scope
    • SupervisorJob을 생성하고 이 Scope에서 만들어진 모든 코루틴을 Main Thread에서 실행하며 Dispachter는 Main을 갖는다.
    • SupervisorJob : 에러의 전파 방향을 자식으로 한정짓는 기능을함.
  • ViewModelScope
    • ViewModle을 대상으로 하는 CoroutineScope이며 ViewModel이 제거되면 코루틴 작업이 자동으로 취소되며 ViewModel이 Active 상태인 경우에만 작업이 실행됨
  • LifeSycleScope
    • 라이프싸이클 객체 대상인 Activity, Fragment, Service 등의 LifeCycle을 따르는 스코프
    • 해당 라이프 싸이클이 끝날 때 코루틴 작업이 자동으로 취소됨.
  • CoroutineBuilder
    • CoroutineScope의 확장함수로, 다양한 요구사항에 맞게 개별적인 코루틴을 만드는 방법
      • launch, async, withContext, runBlocking, actor, produce
  • Job 
    • 코틀린 코루틴을 컨트롤 하기 위한 것이며 job을 통해 하나 혹은 여러개의 코루틴을 제어 할 수 있음
    • job은 6가지의 상태를 가짐 

  • start : 현재의 coroutine의 동작 상태를 체크하며, 동작 중인 경우 true, 준비 또는 완료 상태이면 false를 return 한다.
  • join : 현재의 coroutine 동작이 끝날 때까지 대기한다. 다시 말하면 async {} await처럼 사용할 수 있다.
  • cancel : 현재 coroutine을 즉시 종료하도록 유도만 하고 대기하지 않는다. 다만 타이트하게 동작하는 단순 루프에서는 delay가 없다면 종료하지 못한다.
  • cancelAndJoin : 현재 coroutine에 종료하라는 신호를 보내고, 정상 종료할 때까지 대기한다.
  • cancelChildren : CoroutineScope 내에 작성한 children coroutine들을 종료한다. cancel과 다르게 하위 아이템들만 종료하며, 부모는 취소하지 않는다.

 

참고

https://wooooooak.github.io/kotlin/2019/08/25/코틀린-코루틴-개념-익히기/

https://onlyfor-me-blog.tistory.com/465

https://www.charlezz.com/?p=45962

https://velog.io/@jshme/코루틴의-동시성-내부

https://myungpyo.medium.com/코루틴-공식-가이드-자세히-읽기-part-1-dive-3-b174c735d4fa

https://medium.com/til-kotlin-ko/kotlin의-coroutine은-어떻게-동작하는가-789291da6a50

https://jslee-tech.tistory.com/43

https://kotlinworld.com/153

https://thdev.tech/kotlin/2019/04/08/Init-Coroutines-Job/

반응형

'Android 개인공부' 카테고리의 다른 글

MVVM  (0) 2022.07.21
Repository Pattern  (0) 2022.07.21
Android Custom Progress Dialog  (0) 2021.06.12
AAC LifeCycles  (0) 2020.12.16
Kotlin?  (0) 2020.11.26