Jetpack Compose에서 rememberCoroutineScope()를 사용할 때 흔히 발생하는 오용(Misusing)
// BAD
@Composable
fun LoginScreen(...) {
val scope = rememberCoroutineScope() // 현재 Composition을 인식하는 scope
Button(onClick = {
scope.launch {
val result = viewModel.login() // Suspending function (UI 무관 비즈니스 로직)
if (result == Result.SUCCESS) {
navController.navigate("home")
}
}
}) { /* ... */ }
}
문제점: rememberCoroutineScope()가 제공하는 스코프는 현재 Composition의 생명주기를 따름.
결과: 화면 회전과 같은 구성 변경이 발생하면, 현재 Composition이 파괴되 및 재생성 됨.
⇒ 이전에 실행되던 scope.launch 내부의 코루틴이 취소되는 문제 발생.
요약: UI와 관련 없는 suspend 함수(예: 데이터베이스, 네트워크 호출)은? ⇒ Composable 스코프에서 직접 실행하면, 구성 변경 시 작업이 취소될 위험이 있음.
비즈니스 로직은 ViewModel에서 처리
// GOOD
@Composable
fun LoginScreen(
viewModel: LoginViewModel,
navController: NavController
) {
// 1. 상태 변화 감지 및 UI 동작 (네비게이션)
LaunchedEffect(key1 = viewModel.isLoggedIn) {
if (viewModel.isLoggedIn) {
navController.navigate("home") { /* ... */ }
}
}
// 2. 버튼 클릭 시 ViewModel의 함수 호출
Button(onClick = { viewModel.login() }) {
Text(text = "Login")
}
}