0. 정의

Jetpack Compose의 Effect Handler


1. Scope.launch를 사용해선 안 되는 이유

/**
 * Bad. 아래처럼 사용할 시, recomposition마다 새 coroutine이 시작됨.
 */
@Composable
fun MyBookComposable() {
    val scope = rememberCoroutineScope()
    var bookings by remember {
        mutableStateOf<List<Booking>>(emptyList())
    }
    
    **scope.launch** { 
        bookings = loadBookings()
    }
    
    LazyColumn {
        items(bookings) {
            // ... 
        }
    }
}

상기 코드는 Composable 함수 내에서, non Composable 함수인 scope를 호출하고 있음.

Composable 함수가 재구성 될 때마다, 새로운 코루틴이 시작된다.

이에 따라, Booking 목록을 로드하는 긴 네트워크 요청이 매번 재시작된다.

/**
 * Good. Jetpack Compose의 Effect Handler를 활용하는 방식으로 코드를 작성해야 한다.
 */
@Composable
fun BookingList() {
    var bookings by remember {
        mutableStateOf<List<Booking>>(emptyList())
    }
    
    **LaunchedEffect(true) {**
        bookings = loadBookings()
    }
    
    LazyColumn {
        items(bookings) {
            //...
        }
    }
}

LaunchedEffect는 주어진 key에 의존하여 그 key가 변경될 때만 내부의 로직을 실행한다.

상기 코드의 경우, key가 true(고정된 값)로 설정되어 있다.

따라서, 함수가 재구성 되었을 때 loadBookings() 함수를 불필요하게 재호출하지 않는다.

위를 잘 활용하자.