반응형
코틀린 사용 구조
[1].[2]([3]) {
[4]
}
| [1] | 생명주기 범위 (CoroutineScope) | 코루틴이 살아있는 범위를 지정 (Optional) |
| [2] | 코루틴 실행 함수 | launch, async, withContext 등 실행 방식 결정 |
| [3] | Dispatcher | 어떤 스레드(큐)에서 실행할지 |
| [4] | suspend 함수 실행 | 실제 일시중단 작업 수행 |
[1] 생명주기 범위 (CoroutineScope)
다른 scope는 내부적으로 CoroutineScope + Dispatcher를 포함하고 있기 때문에, 다시 ()로 Dispatcher를 지정해줄 필요가 없음
값 설명 사용 위치 종료 시점
| (생략 불가) | scope 생략 시 컴파일 에러 발생 | 반드시 명시 필요 | |
| CoroutineScope(...) | 직접 생성한 사용자 지정 scope | 일반 클래스 등 | 직접 cancel해야함 |
| viewModelScope | ViewModel의 생명주기와 연결 | ViewModel 내부 | viewModel 끝날때 |
| lifecycleScope | LifecycleOwner (Activity/Fragment)의 생명주기와 연결 | UI 컴포넌트 | LifecycleOwner에 따라서 |
| GlobalScope | 앱 전체에서 살아있는 범위 (자동 취소 없음) | ❗ 사용 지양 | 앱이 죽을때 까지 실행 |
[2] 코루틴 실행 함수 (빌더)
함수 반환 타입 설명 사용 목적
| launch | Job | 결과 없이 실행 | UI 업데이트, 단순 실행 |
| async | Deferred<T> | 결과를 비동기로 반환 | 계산, 네트워크 등 결과 필요할 때 |
| withContext | T | 컨텍스트 변경 후 결과 반환 /Dispatcher 변경용 | 스레드 변경하며 suspend 함수 실행 |
| runBlocking | T | 코루틴을 블로킹(동기) 방식으로 실행 / 실무 X | main() 함수, 테스트용 |
// launch, async 사용법
CoroutineScope(Dispatchers.Main).launch {
// runBlocking = 코루틴 "시작점"에서 전체 묶기 (블로킹)
fun main() = runBlocking {
// 코루틴 실행
}
// withContext = "코루틴 내부"에서 Dispatcher 바꾸기 (비블로킹)
viewModelScope.launch {
val result = withContext(Dispatchers.IO) {
longTask()
}
}
항목 withContext async-await
| 용도 | 컨텍스트(Dispatcher) 전환 + 결과 처리 | 병렬 비동기 실행 + 결과 처리 |
| 실행 시점 | 즉시 실행 | 지연 실행 (lazy) |
| 병렬 처리 | ❌ 불가 (순차 실행) | ✅ 가능 (여러 개 동시에 실행 가능) |
| 반환값 | T (그냥 값) | Deferred<T> → await() 해야 결과 받음 |
| 코드 목적 | 스레드 전환하면서 작업 하나만 할 때 | 여러 비동기 작업을 동시에 처리할 때 |
✅ withContext – 순차 실행
val data = withContext(Dispatchers.IO) {
fetchFromNetwork()
}
val result = withContext(Dispatchers.Default) {
processData(data)
}
✅ async-await – 병렬 실행
val networkDeferred = async(Dispatchers.IO) { fetchFromNetwork() }
val fileDeferred = async(Dispatchers.IO) { readFromFile() }
val result = combine(networkDeferred.await(), fileDeferred.await())
[3] Dispatcher 종류 (실행 스레드)
Dispatcher 스레드 종류 설명
| 생략 가능 | Scope에 설정된 Dispatcher를 따라감 | 예: viewModelScope는 기본 Main |
| Dispatchers.Main | 메인(UI) 스레드 | UI 업데이트, LiveData 변경 등 |
| Dispatchers.IO | 백그라운드 I/O 스레드 | 파일, DB, 네트워크 작업 |
| Dispatchers.Default | 백그라운드 CPU 스레드 | 무거운 연산, 데이터 처리 |
| Dispatchers.Unconfined | 제한 없음 (컨텍스트에 따라 다름) | 테스트, 특수 용도에만 사용 |
[4] 일시중단 함수 (suspend함수)
함수 예시 설명
| delay(timeMillis) | 지정 시간 동안 중단 (스레드 점유 X) |
| repository.fetchData() | 네트워크 요청 등 실제 suspend 작업 |
| withContext(Dispatcher) | suspend 함수 내부에서 컨텍스트 전환 |
| apiService.getUser() | Retrofit에서 suspend로 정의된 API 호출 |
예시 코드
viewModelScope.launch(Dispatchers.Main) {
val data = withContext(Dispatchers.IO) {
repository.fetchData()
}
_state.value = data
}
위치 값 설명
| [1] | viewModelScope | ViewModel의 생명주기와 연결 |
| [2] | launch | 결과 없이 코루틴 실행 |
| [3] | Dispatchers.Main | UI 스레드에서 시작 |
| [4] | withContext(Dispatchers.IO) { repository.fetchData() } | I/O 스레드에서 suspend 함수 실행 |
반응형