코틀린 코루틴을 활용한 비동기 프로그래밍 개선
코틀린 코루틴을 활용한 비동기 프로그래밍 개선
코틀린 코루틴은 안드로이드 비동기 프로그래밍을 위한 구조적이고 경량화된 솔루션을 제공합니다. 스레드를 블로킹하지 않으면서도 코드의 가독성을 유지할 수 있도록 설계되어 있으며, 네트워크 요청과 같은 백그라운드 작업을 메인 스레드를 멈추지 않고 수행할 수 있습니다. 이를 통해 앱의 성능과 반응성을 크게 높여 줍니다. 이번 면접 질문을 통하여 아래 내용들을 학습하실 수 있습니다.
- 코루틴이 콜백 기반 비동기 패턴을 순차적 코드로 대체하는 원리를 설명할 수 있습니다.
viewModelScope를 사용하여 코루틴의 생명주기를 ViewModel에 연결하는 방법을 이해할 수 있습니다.withContext를 활용하여 디스패처(dispatcher)를 전환하고 메인 스레드 안전성을 확보하는 방법을 학습하실 수 있습니다.- 구조화된 동시성(structured concurrency) 기반의 예외 처리 방식을 익힐 수 있습니다.
- 안드로이드 아키텍처 레이어별 코루틴 사용 모범 사례를 파악하실 수 있습니다.
안드로이드 아키텍처에서의 코루틴 활용
최신 안드로이드 앱에서 코루틴은 주로 ViewModel 계층에서 viewModelScope와 함께 사용됩니다. viewModelScope는 ViewModel이 해제(clear)될 때 해당 스코프에서 실행 중인 모든 코루틴을 자동으로 취소해 주므로, 메모리 누수나 불필요한 백그라운드 작업이 남아 있는 문제를 원천적으로 방지할 수 있습니다.
class LoginViewModel(
private val repository: LoginRepository
) : ViewModel() {
fun login(email: String, password: String) {
viewModelScope.launch {
val result = repository.makeLoginRequest(
email, password
)
// UI 상태를 result로 업데이트
}
}
}
viewModelScope는 ViewModel의 생명주기에 연결되어 있습니다. 사용자가 화면을 이탈하여 ViewModel이 해제되면, 이 스코프 안에서 실행 중이던 모든 코루틴이 자동으로 취소됩니다. 이러한 구조화된 동시성 보장 덕분에 생명주기 관련 버그를 근본적으로 제거할 수 있습니다. 면접에서 이 개념을 설명하실 때는, 단순히 "자동으로 취소된다"라고만 답변하기보다는 Job 계층 구조와 부모-자식 관계를 함께 언급하시면 더 깊이 있는 답변이 됩니다.
withContext를 활용한 메인 스레드 안전성 확보
메인 스레드가 블로킹되지 않도록 하려면, suspend 함수 내부에서 블로킹 작업에 적합한 디스패처로 전환해야 합니다. withContext(Dispatchers.IO)를 사용하면 블로킹 I/O 작업에 최적화된 스레드 풀로 실행을 이동할 수 있습니다.
suspend fun makeLoginRequest(
email: String, password: String
): Result<LoginResponse> {
return withContext(Dispatchers.IO) {
// 블로킹 네트워크 호출을 IO 스레드에서 수행
apiService.login(email, password)
}
}
이 패턴을 메인 안전성(main safety)이라고 부릅니다. ViewModel에서 호출하는 쪽은 리포지토리 내부에서 어떤 디스패처를 사용하는지 알 필요가 없습니다. suspend 함수가 내부적으로 스레드 전환을 처리하기 때문에, Dispatchers.Main에서 안전하게 호출할 수 있습니다. 이 관례를 따르면 호출 코드가 깔끔해지고, suspend 함수를 어떤 컨텍스트에서든 재사용할 수 있게 됩니다. 실무에서 이 패턴은 아키텍처 레이어 간 관심사 분리(separation of concerns)를 지키는 데 핵심적인 역할을 합니다.