ㅇ coroutine이란?
- 실행을 일시 중단(suspend)/다시 실행(resume) 시킬 수 있는 기술
- 비동기 프로그래밍을 위해 사용되기 때문에, 개념적으로는 일종의 경량 스레드(light-weight thread)로 볼 수 있지만, 특정 thread에 종속되지 않기 때문에 실질적으로는 매우 다름
- 안드로이드 개발에서는 UI thread는 유지하면서 네트워크 호출, 파일 입출력, DB 작업 등의 비동기 작업을 효율적으로 처리하기 위해 많이 사용
ㅇ coroutine의 장점
1. 비동기 작업 처리
- 시간이 많이 걸리는 비동기 작업을 메인 thread와 별도 thread에서 처리하여 효율적
- main thread에서 사용할 경우 ANR(Application Not Responding)이 발생할 수 있다.
2. UI와의 자연스러운 상호작용
- 안드로이드 앱은 UI 업데이트를 반드시 main thread에서 처리해야 한다.
- coroutine을 사용하면 Dispatchers.Main을 통해 UI를 안전하게 처리 가능
3. 경량성
- thread보다 훨씬 가볍기 때문에 메모리 사용량이 적고 context switching 비용이 낮다.
ㅇ 주요 요소
CoroutineScope
- coroutine의 실행 범위를 정의하는 컨테이너
- 안드로이드에서는 주로 lifecycleScope, viewModelScope와 같은 구조화된 coroutine scope를 활용
Dispatcher
- coroutine이 실행되는 thread나 context를 지정
- 종류
- Dispatchers.Main : 안드로이드의 메인(UI) thread에서 실행
- Dispatchers.IO : 입출력 작업(파일, 네트워크, DB)에 최적화
- Dispatchers.Default : CPU 집중 작업에 적합
- Dispatchers.Unconfined : thread에 종속x(특수한 경우에 사용)
Suspend 함수
- coroutine 내부에서 실행
- 비동기 작업 중 다른 coroutine의 작업을 차단하지 않고 기다릴 수 있음
- ex) delay(), withContext(), 네트워크 호출 등
Structured Concurrency
- coroutine은 부모-자식 관계를 가짐
- 부모 coroutine이 취소되면 자식 coroutine도 모두 취소
- 중간에 빠지거나 사라지지 않도록 보장해주고, 마찬가지로 error도 확실하게 뜰 것을 보장
ㅇ 실제 적용 예시
CoroutineScope 만들기
- runBlocking : non-coroutine인 fun main()과 coroutine scope(runBlocking{...})를 이어주는 coroutine builder.
실행되는 thread를 runBlock{...} 안의 모든 coroutines이 수행될 때까지 멈춤(block).
thread를 block 시키는 것은 매우 비효율적이므로 주로 top-level에서만 쓰임.
- launch : coroutine builder. runBlocking과는 다르게 coroutine scope 안에서만 정의됨.
- delay : coroutine을 특정 시간 동안 일시 중단(suspend) 시킴. 다만, 기반 thread를 정지하는건 아니기 때문에 다른 coroutine들이 실행될 수 있음.
fun main() = runBlocking { // this: CoroutineScope
launch { // launch a new coroutine and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello") // main coroutine continues while a previous one is delayed
}
- 결과:
Hello
World!
CoroutineScope를 만드는 다른 방법
class MyClass() {
private val myScope = CoroutineScope(Dispatchers.IO) // coroutine scope를 정의
...
suspend fun myFunc(...) {
try {
...
override fun myFunc1(...) {
myScope.launch(Dispatchers.IO) { // 위에서 정의한 coroutine 실행
...
}
}
override fun myFunc2(...) {
myScope.launch(Dispatchers.IO) { // 위에서 정의한 coroutine 실행
...
}
}
},
)
} ...
}
suspend 함수를 이용한 함수 분리하기
- suspend : suspending 함수를 만드는 keyword.
suspend 함수는 coroutine 안에서 일반 함수처럼 사용될 수 있음
delay와 같은 다른 suspending 함수를 사용할 수 있음
fun main() = runBlocking { // this: CoroutineScope
launch { doWorld() }
println("Hello")
}
// this is your first suspending function
suspend fun doWorld() {
delay(1000L)
println("World!")
}
'CS > Android' 카테고리의 다른 글
Build Variant (1) | 2024.12.26 |
---|---|
Coroutine (2) (0) | 2024.12.24 |
공통 객체 이용하기 - CompositionLocal (0) | 2024.12.17 |
Navigation (0) | 2024.12.16 |
Composable & Preview (0) | 2024.12.13 |