본문 바로가기
Kotlin

[Coroutine] Coroutine이란?

by 명훈스토리 2023. 2. 2.
SMALL

1. 비동기란?

코루틴을 공부하기 전에 비동기라는 개념부터 알아야 한다. 비동기는 결론적으로 작업을 동시에 하는 것을 의미한다.

코드에서는 비동기가 필요할 때가 있다. 예를 들어 네트워크를 통해 데이터를 가져오는 작업은 메인 스레드에서 하지 못하고, 많은 데이터를 갖고 오게 되면 시간이 오래 걸린다. 앱이 느리다는 인상을 주기에 메인 스레드가 아닌 별개의 스레드에서 네트워크 작업을 해야 한다.

 

2. Coroutine 사용법

Android Studio 앱 단 gradle에서 아래 코드를 추가한다.

 

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2'

 

스레드는 총 3가지가 있다.

Main : 메인 스레드. 화면 UI 작업이 수행되는 스레드

IO : 네트워크, DB 등 백그라운드 작업이 수행되는 스레드

Default : 정렬이나 무거운 계산 작업이 수행되는 스레드

 

Coroutine 메소드는 2가지가 있다.

launch

- 실행하고 잊는 형태

- 즉시 실행되며 실행 결과는 반환하지 않음

- 관리를 위한 Job 객체를 반환함

- join을 통해 완료를 대기할 수 있음

 

async

- 결과나 예외를 반환함

- 실행 결과는 Deferred<T>를 통해서 반환하며 await를 통해 받을 수 있음

- await는 작업이 완료될 때까지 기다림

 

CoroutineScope(Dispatchers.IO).async { 
    
}

예를 들어 위 코드는 '네트워크 작업을 하는 스레드로 비동기 작업을 할테니 결과나 예외를 반환해주세요'라는 의미이다.

 

CoroutineScope(Dispatchers.Main).launch { 
    val html = CoroutineScope(Dispatchers.IO).async { 
        getHtml()
    }.await()
    
    textView.text = html.toString()
}

예를 들어 위 코드는 await()로 작업이 완료될 때까지 기다린다는 뜻으로 작업이 완료되면 html에 값이 들어가며 그 값을 텍스트뷰에 세팅하는 UI 작업을 한다.

 

CoroutineScope(Dispatchers.Main).launch {
    val html = CoroutineScope(Dispatchers.IO).async {
        getHtml()
    }.await()

    textView.text = html.toString()
}

// 다른 UI 작업이다
Toast.makeText(this, "토스트가 먼저 노출됨", Toast.LENGTH_SHORT).show()

따라서 위 코드를 실행하게 되면 토스트가 먼저 뜨고 CoroutineScope 괄호 안은 별도의 스레드이기에 나중에 실행된다.

 

3. Coroutine Delay

네트워크와 달리 내부 DB 작업은 메인 스레드에서 실행해도 되지만 만약 내부 DB 작업과 RecyclerView 등의 UI를 메인 스레드에서 같이 사용하다 보면 내부 DB 데이터 조작이 오래 걸릴 때 RecyclerView의 갱신이 되고 내부 DB 로직이 실행될 수 있다. 말하자면 삭제가 이루어지지 않은 것처럼 보일 수 있다.

val handler = android.os.Handler()
handler.postDelayed({
    recyclerView 갱신
}, 1000)

이 때는 Handler를 사용하는방법이 있지만 단점이 있다.

- 항상 똑같은 시간만큼 기다려야 하기에 데이터를 갖고 오는 시간이 빨라도 지정한 시간만큼 지나야 다음 명령어를 실행할 수 있다. 시간을 낭비하는 것이다.

- 데이터가 많아서 지정한 시간보다 오래 걸리면 다음 명령어가 실행되기에 Handler가 의미가 없어진다.

 

CoroutineScope(Dispatchers.Main).launch { 
    val temp = CoroutineScope(Dispatchers.Default).async { 
        // 내부 DB 데이터 삭제 코드
    }.await()
    
    // recyclerView 갱신 코드
}

따라서 이럴 때 Coroutine을 사용하면 된다. 네트워크 작업이 아니기에 Dispatchers.IO가 아니라 Dispatchers.Default를 넣고 비동기로 DB 작업을 하고 기다렸다가 데이터를 삭제하고 나면 recyclerView를 갱신해주는 것이다.

LIST

'Kotlin' 카테고리의 다른 글

[Paging] Paging이란?  (0) 2023.02.03
[ViewModel] ViewModel이란?  (0) 2023.02.03
[LifeCycles] LifeCycles란?  (0) 2023.02.03
[TIL] Room DB 사용법  (0) 2023.02.02
[TIL] Room DB와 Realm DB의 차이  (0) 2023.01.31

댓글