Coroutine에 대해서 알아보자.
Coroutine이란?
Co(함께, 동시에) + routine(작업들의 집합)
Coroutine은 비동적인 작업을 효율적으로 처리하기 위한 기술입니다. 코루틴은 스레드와 마찬가지로 동시성을 다루지만, 스레드와는 달리 코루틴은 하나의 스레드에서 여러 개의 작업을 처리할 수 있습니다.
코루틴은 일반적으로 suspend 함수를 사용하여 구현됩니다. suspend 함수는 실행 중지가 가능한 함수로, 실행이 중지된 후 다시 실행될 수 있습니다. 이를 통해 코루틴은 비동기 작업을 중단하고 다른 작업을 수행한 후 다시 이어서 작업을 진행할 수 있습니다.
코루틴은 비동기 작업을 간결하고 가독성 높은 코드로 작성할 수 있게 해주며, 코루틴 컨텐스트를 이용하여 작업의 스케줄링과 취소를 쉽게 처리할 수 있습니다. 이러한 장점으로 인해 코틀린에서는 코루틴을 많이 사용하고 있습니다.
Android에서 코루틴 사용
Android 앱에서는 네트워크 호출, 파일 다운로드, 데이터베이스 쿼르 등과 같은 비동적인 작업을 수행해야 하는 경우가 많습니다. 이러한 작업은 Ui스레드에서 수행할 경우 앱의 성능에 영향을 미칠 수 있으므로 백그라운드 스레드에서 실행해야 합니다. 코루틴은 이러한 작업을 보다 쉽고 간결학 처리할 수 있도록 도와줍니다.
build.gradle에서 종속 항목 추가
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
}
suspend fun fetchData() {
withContext(Dispatchers.IO) {
val response = apiService.getData()
if (response.isSuccessful) {
val data = response.body()
// UI에 데이터 업데이트
withContext(Dispatchers.Main) {
updateUI(data)
}
}
}
}
이 코드에서 'withContext' 함수는 현재 코루틴은 컨텍스트를 변경합니다. 'Dispatchers.IO'를 사용하여 백그라운드 스레드에서 작업을 실행하고, 작업이 완료되면 'Dispatchers.Main'을 사용하여 Ui스레드에서 데이터를 업데이트합니다.
Android에서는 코루틴을 사용하여 Ui를 업데이트할 수 있습니다. 이를 통해 코드를 보다 간결하고 가독성 높은 형태로 작성할 수 있습니다.
Dispatchers
Dispatchers는 코루틴에서는 코루틴 실행을 관리하는 기능을 제공하는 클래스입니다. 다양한 Dispatchers를 사용하여 코루틴이 어떤 스레드에서 실행될지 결정할 수 있습니다.
- Dispatchers.Default
- 기본 스레드 풀을 사용합니다.
- CPU 바운드 작업에 적합합니다.
- Dispatchers.IO
- I/O 작업에 최적화된 스레드 풀을 사용합니다.
- 파일 읽기/쓰기, 네트워크 호출 등 I/O 작업에 적합합니다.
- Dispatchers.Main
- Android에서 Ui 스레드와 연결됩니다.
- Ui 업데이트와 같은 작업은 항상 Main Dispatcher에서 실행해야 합니다.
- Dispatchers.Unconfined
- 실행 위치가 지정되지 않은 Dispatcher입니다.
- 현재 스레드에서 즉시 실행됩니다.
- 주로 테스트 용도로 사용됩니다.
위에서 설명한 Dispatchers는 코틀린에서 제공하는 기본 Dispatchers입니다. 또한, 사용자 정의 Dispatchers를 만들어 사용할 수 도 있습니다. 또한, 사용자 정의 Dispatchers를 만들어 사용할 수도 있습니다. 코루틴을 사용하여 적절한 Dispatchers를 선택하여 스레드 관리와 성능 개선에 도움이 됩니다.
동기 / 비동기
동기(Synchronous)와 비동기(Asynchronous)는 프로그래밍에서 자주 사용되는 용어로, 어떤 작업이 수행되는 방식을 나타냅니다.
동기는 순차적인 방식으로 작업이 수행되며, 한 작업이 완료되어야 다음 작업을 수행할 수 있습니다. 다시 말해, 어떤 작업이 수행되는 동안에는 다른 작업을 수행할 수 없습니다. 이는 일반적으로 코드의 구조가 간단하고 직관적이며, 작업의 상태를 추적하기 쉽다는 장점이 있습니다. 하지만 작업이 완료될 때까지 대기해야 하므로 시간이 오래 걸리거나 작업이 많아지면 성능에 영향을 미칩니다.
반면에, 비동기는 작업이 병렬적으로 수행되며, 한 작업이 완료되지 않아도 다른 작업을 수행할 수 있습니다. 이는 일반적으로 코드의 구조가 복잡하고, 작업의 상태를 추적하기 어려우며, 비동기적으로 작업을 수행할 때 발생할 수 있는 여러 문제를 다루어야 한다는 단점이 있습니다. 그러나 비동기적으로 작업을 수행하면 여러 작업을 동시에 수행할 수 있으므로 시간을 절약할 수 있습니다.
예를 들어, 웹 페이지를 로딩하는 작업이 있다면, 동기적인 방식으로 로딩을 하게 되면 페이지 전체가 로딩될 때까지 다른 작업을 수행할 수 없습니다. 반면에 비동기적인 방식으로 로딩을 하게 되면, 페이지의 일부분이 로딩되는 동안에도 다른 작업을 수행할 수 있습니다. 이는 사용자 경험을 향상시키고, 앱의 성능을 향상시키는 데에 큰 도움이 됩니다.
launch/async
launch와 async는 모두 코루틴을 실행하는 함수이며, 두 함수 모두 비동기적으로 작업을 수행할 수 있습니다.
launch 함수는 코루틴을 실행하고, 반환값이 없는 작업을 비동기적으로 실행합니다. 이 함수는 호출된 후 바로 반환되며, 실행 중인 코루틴이 완료되지 않아도 다음 작업을 수행할 수 있습니다. 따라서 launch 함수는 비동기적으로 작업을 실행하는 함수입니다.
async 함수는 launch와 마찬가지로 코루틴을 실행하지만, 반환값이 있는 작업을 비동기적으로 실행합니다. async 함수는 호출된 후 바로 Deferred 객체를 반환하며, Deferred 객체는 await 함수를 호출하여 작업이 완료될 때까지 대기할 수 있습니다. 따라서 async 함수는 비동기적으로 작업을 실행하면서도 작업 결과를 반환하는 함수입니다.
그러나 launch 함수와 async 함수가 동기적인지 비동기적인지는 사용하는 방법에 따라 달라집니다. 코루틴 내부에서 launch 함수나 async 함수를 호출하면, 해당 함수가 비동기적으로 실행됩니다. 그러나 runBlocking과 같은 블로킹 함수 내에서 launch 함수나 async 함수를 호출하면, 해당 함수가 블로킹 함수의 실행을 차단하므로 동기적으로 실행됩니다. 따라서 코루틴을 사용할 때는 실행하려는 함수와 사용하는 방법에 주의해야 합니다.
await() - 코루틴에서의 딜레이 처리
await() 함수는 Deferred 객체가 가진 작업이 완료될 때까지 대기하고, 작업 결과를 반환하는 함수입니다. Deferred 객체는 비동기적으로 작업을 실행하는 async 함수에서 반환되며, 작업 결과를 포함한 Job 객체를 감싸고 있습니다.
await() 함수를 호출하면, 해당 Deferred 객체가 가진 작업이 완료될 때까지 대기하고, 작업 결과를 반환합니다. 이 때 await() 함수는 호출하는 코루틴의 실행을 차단하지 않습니다. 대신, 해당 코루틴이 대기 상태가 되며, 코루틴 컨텍스트를 반환하여 다른 작업을 수행할 수 있게 합니다.
await() 함수는 async 함수를 사용하여 반환된 Deferred 객체의 작업 결과를 쉽게 가져올 수 있도록 도와주는 함수입니다. 따라서 async 함수를 사용하여 비동기적으로 작업을 실행할 때는 await() 함수를 호출하여 작업 결과를 처리할 수 있습니다.
'Android > Study' 카테고리의 다른 글
[Android] MVI 패턴이란? (0) | 2023.05.04 |
---|---|
[Android] 의존성 주입(Dependency Injection) (0) | 2023.04.27 |
[Android] 모듈을 기반으로하는 클린 아키텍처를 셋팅 (0) | 2023.02.22 |
[Android] Intent 란? (0) | 2023.02.03 |
[Android] Context 란? (0) | 2023.02.03 |