Compose에서 SideEffect는 Composable 함수 내에서 UI와 별개로 추가적인 작업이 필요한 경우에 사용하는 함수로,
데이터 업데이트, 네트워크 통신 등 Composable 함수 외적인 작업들을 예측 가능한 방식으로 제어하기 위해 사용한다.
- SideEffect
- LaunchedEffect
- DisposableEffect
만일 SideEffect가 아닌 Composable 함수 내에 그냥 작성을 하게 된다면 Recomposable 될 때마다 다시 실행하지 않아도 되는 코드들이 모두 실행되어 불필요한 자원이 소모될 것이다.
따라서 특정 상황에서만 작업이 필요한 경우, 한 번만 작업하면 되는 경우 또는 UI와 별개의 작업이 필요한 경우 등 다양한 작업을 UI와 분리하여 성능과 가독성을 높이고 유지보수를 더욱 용이하게 할 수 있다.
1. SideEffect
- SideEffect가 선언되어 있는 Composable 함수가 Recomposition 될 때마다 실행된다.
- 비동기로 동작하지 않는다.
- Recomposition 이후에 실행된다. (화면 구성 이후 마지막에 실행됨)
@Composable
fun ChildCompose(
num: () -> Int,
onClick: () -> Unit
) {
SideEffect {
Log.e("SideEffect", "DO!")
}
Log.e("ChildCompose", "Recomposition Start")
Text(text = "First - ${num()}")
Button(onClick = { onClick() }) {
Text(text = "First Text Change")
}
Log.e("ChildCompose", "Recomposition End")
}
2. LaunchedEffect
fun LaunchedEffect(
key1: Any?,
block: suspend CoroutineScope.() -> Unit
)
- Composition 때만 동작하거나(Recomposition 시 동작하지 않음), 특정 값의 변경이 이루어질 때만 동작한다.
- LaunchedEffect(Unit) : 단 한 번만 실행
- LaunchedEffect(key): Key 값이 변경될 때마다 실행
- CoroutineScope로 이루어져 비동기 작업이 가능하다.
- Key 설정 시 Key의 값이 변경되면 코루틴은 취소되고 다시 실행된다.
- Key는 여러 개 설정할 수 있다.
- Composition에서 벗어나면 코루틴은 취소된다.
@Composable
fun ChildCompose(
timerState: () -> Boolean,
onClick: () -> Unit
) {
if(timerState()){
Timer()
}
Button(onClick = { onClick() }) {
Text(text = "On/Off")
}
}
@Composable
fun Timer(){
var time by remember{ mutableIntStateOf(0) }
LaunchedEffect(Unit) {
while(true){
delay(1000L)
time++
Log.e("Timer", time.toString())
}
}
Text("Time : $time")
}
5초 이후에 버튼을 클릭하여 TimerState를 false로 바꾸면 코루틴이 취소되어 더이상 로그가 찍히지 않는다.
3. DisposableEffect
DisposableEffect는 다른 Effect와는 다르게 내부에 onDispose 함수를 호출 할 수 있다.
onDispose 함수는 Composition이 종료될 때 호출되기 때문에 Composition 종료 시 추가적인 작업이 필요한 경우에 적합하다.
(Activity Lifecycle의 onDestroy와 같은 기능이라고 생각하면 좋을 것 같습니다.)
- CoroutineScope로 이루어져 있지 않다.
- onDispose 함수를 통해 Composition 종료 시의 작업을 처리할 수 있다.
- LaunchedEffect와 같이 Key를 설정할 수 있다.
@Composable
fun Timer(){
var time by remember{ mutableIntStateOf(0) }
DisposableEffect(Unit) {
Log.e("DisposableEffect", "Start")
onDispose {
Log.e("DisposableEffect", "End")
}
}
LaunchedEffect(Unit) {
while(true){
delay(1000L)
time++
Log.e("Timer", time.toString())
}
}
Text("Time : $time")
}
'안드로이드 > Compose' 카테고리의 다른 글
[Compose] Composable 함수의 데이터 관리 (0) | 2025.06.28 |
---|---|
Recomposition(2) - 사용 예시 (0) | 2025.06.25 |
Recomposition (0) | 2025.01.21 |
Compose 동작 원리와 ComponentActivity를 상속하는 이유 (0) | 2025.01.21 |