ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ 코틀린 ] 코루틴2 : Coroutine 사용하기 - 기초
    Android & Kotlin 2022. 2. 2. 17:33

    코루틴의 개념을 먼저 이해하고 싶으시다면

    아래 게시글 선행을 추천드립니다.

     

    이번 편에서 코루틴을 사용하는 매우 간단한 방법을 소개합니다.

    코루틴에대한 시행착오 및 응용은 다음 포스팅에서 다루겠습니다.

     

    https://easycodediary.tistory.com/95

     

    [ 코틀린 ] 코루틴1 : Coroutine 이해하기

    1. 코루틴 이란? 코루틴이란 실행의 지연과 재개를 허용함으로서, 비 선점적 멀티태스킹을 위한 서브루틴을 일반화한 컴퓨터 프로그램 구성요소이다. (위키피디아 참고) 2. 루틴과 코루틴 루틴

    easycodediary.tistory.com

     

    인텔리제이에서 코루틴 라이브러리 추가하는 법

    https://stackoverflow.com/questions/52522282/using-kotlinx-coroutines-in-intellij-idea-project 

     

    Using kotlinx.coroutines in IntelliJ IDEA project

    I am trying to learn coroutines and so I fire up IntelliJ and create a scratch file. But when I type in my coroutines I get compiler complaints such as runBlocking is an unresolved reference. So th...

    stackoverflow.com

     

    0. 왜 코루틴 인가?

    1. 비동기적 코드를 기존 동기적를 짜던 방식대로 구현할 수 있다. 
    • 코루틴 사용전에 비동기 프로그래밍의 콜백이 소개됨.

    2. 실행 스레드를 쉽게 지정 및 변경할 수 있다. 

    • 코루틴을 사용하면 백그라운드 메인등 실행 스레드를 매우 쉽게 변경할 수 있습니다.

     

     

     

    출처: https://hanamon.kr/javascript

    비동기 프로그래밍을에서 아래 사진과 같은 콜백 지옥을 경험해본신적 있나요?

    어떤 작업전에 또 다른 작업이 선행되야하고 이것이 중첩된 결과입니다.

     

    1 . 코루틴 Scope

    코루틴은 제어범위 및 실행범위를 지정할 수 있습니다. 

    (아래 제시하지는 않았지만 플랫폼에 따라 제공하는 Scope가 있을 수 있습니다. ex) 안드로이드 : ViewModelScope )

    (runBlocking 또한 )

     

    GlobalScope : 앱이 실행될때 부터 종료될때 까지 실행 (프로그램 어디서나 제어 , 동작이 가능한 기본 범위)

    (일반적으로  GlobalScope 상에는 launch 나 async 사용이 권장 되지 않습니다)

        // 프로그램이 끝날때 까지 실행될 스코프 생성
        GlobalScope.launch {
    
            // 백그라운드 스레드로 전환하여 작업 
            launch(Dispatchers.IO) { }
    
            // 메인스레드로 전환하여 작업 
            launch(Dispatchers.Main) { }
        }

     

    CoroutineScope : 특정 목적의 Dispatcher를 지정하여 제어 및 동작이 가능한 범위 - 사용자 지정 범위

        // 메인 쓰레드에서 동작시킬 스코프 생성
        val scope1 = CoroutineScope(Dispatchers.Main)
        
        val scope2 = CoroutineScope(Dispatchers.Default)
        val scope3 = CoroutineScope(Dispatchers.IO)
        scope1.launch { 
            // 메인 쓰레드에서 동작시킬 내용
        }
        scope2.launch {  }
        scope3.launch {  }

     

     

    2. 코루틴 Context

    • 코루틴 작업을 어떠 스레드에서 실행시할 것이지를 결정하는 Dispatcher 가 대표적인 context 요소입니다.
    • + 연산을 통해 조합될수 있습니다.
    • 주요 요소로 Job 과 Dispatcher , Name 등이 있습니다.
    // Job , Diapatcher , Name , Exception 조합
    val coroutineContext = Job() + Dispatchers.IO + CoroutineName("context1")+ CoroutineExceptionHandler{context , throwable->  print("${context[CoroutineName]?.name} :: ${throwable.printStackTrace()}")}

     

    Job 객체 

    • 코루틴의 생명주기를 관리하며 생성된 코루틴 작업들은 부모-자식 관계를 가질 수 있다.
      • 규칙1. 부모가 취소되거나 실행 실패시 그 하위 자식들은 모두 취소된다.
      • 규칙2. 자식의 실패는 그 부모에 전달되며 부모 또한 실패한다. ( 다른 모든 자식도 취소됨)
    • [ job개체 ] . join() 을 통해서 join() 이 포함된 스코프를 멈추고 결과를 기다릴 수 있다.
    • [ job개체 ] . cancel()  을 통해서 코루틴을 중단시킬 수 있습니다.
    fun main() = runBlocking {
    
    
        val scope3 = CoroutineScope(Dispatchers.IO)
        val job3 = scope3.launch {
            // 비동기적으로 실행할 작업 내용
        }
        job3.join() // 작업 내용이 완료될 때까지 runBlocking 스코프를 멈추고 결과를 기다림
        job3.cancel() //작업취소
       }

    Dispatcher 

    코루틴을 어떤 쓰레드에서 실행할 것 인지를 지정해주는 객체 입니다.

     

    : 코루틴 엘리먼트중 하나로 빌더 내부에 선언하여 코루틴의 실행 스레드를 제한해줄 수 있다.

    • Dispatcher.Default
      • defaultDispatcher-worker 에서 실행됨
      • 코어수에 비례하는 스레드풀에서 수행 (IO 보다 더 적은 스레드를 갖는 스레드 풀)
      • IO 에 비해 더 규모 있는 작업에 유리(CPU 많이쓰는 것)
    • Dispatcher.Io
      • defaultDispatcher-worker 에서 실행됨
      • 코어 수보다 훨씬 많은 스레드를 가지는 스레드 풀
      • CPU 를 소모하지 않는 작업에 유리 -> 파일 읽기 , 네트워킹
    • Dispatcher.Main
      • 안드로이드 환경에서만 사용가능
      • 안드로이드 에서의 메인 스레드에서 코루틴 실행
    • newSingleTreadContext("스레드이름")
      • 새로운 스레드를 만들어서 사용할 수 있다.
      • 해당 컨텍스트를 통해 동일한 스레드를 사용할 수 있다. -> 공유자원에서 유용
    • withoutDispatcher : launch 에 아무 것 도 안넣었을때
      • 부모의 컨텍스트에서 수행됨

     

     

    3. 코루틴 Builder

    코루틴 스코프와 컨텍스틀를 이용하여 실제로 코루틴을 실행시키는 함수 입니다.

    대표적으로 lanuch 와 async 가 있으며 눈에 띄는 차이점으로는

    lanch 는 반환값이 없는 Job 객체async 는 반환 값이 있는 Defferd 객체를 반환 합니다.

    1. launch

    •  즉시실행하며 블록 내의 실행 결과를 반환하지 않는다
    •  상위 코드를 블록 시키지 않고(넌블록) 관리를 위한 job 개체를 즉시 반환한다.
      • job 객체는 코루틴의 상태를 알려준다. 
    •  join을 통해 상위 코드가 종료되지 않고 완료를 기다리게 할 수 있다.

    2. async

    •  비동기 호출을 위해 만든 코루틴으로 결과나 예외를 반환한다.
    •  실행 결과는 Deffered<T>로 반환
      • job 을 상속한 인터페이스로 결과값 수신을 연기함
      • 결과 값이 없는 job 에 결과값을 추가하여 확장함
    •  job.await 은 작업이 완료될 때까지 기다리게 된다.

    3. withContext

    • async의 await 처럼 결과 객체를 반환함
    • async 의 await 를 적용한 것과 같이 결과를 반환할때까지 밖의 블록을 재운다.

     

     

    코루틴 간단 사용법

    1. 코루틴이 실행될 Scope를 결정하여 생성합니다.

    (CoroutineScope, GlobalScope, ViewMocelScope(안드로이드 일때) ... )

     

    1. 어떤 쓰레드에서 코루틴을 실행시킬 것인지를 Dispatchers로 정합니다.(Dispatchers.Main, Dispatchers.IO, Dispatchers.Default)

     

    3. launch 또는 async 에 dispatcher 를 추가하고 코루틴을 실행 시킵니다.

     

         viewModelScope.launch(Dispatchers.IO) {
                //do-something
         }

     

    [참고]

    코루틴 끼리는 비동기적이지만 ,  코루틴 내부 코드는 동기적입니다.

     

     

    댓글

Designed by Tistory.