[Compose] SideEffect란?

이승우·2023년 5월 31일
1
post-custom-banner

SideEffect란 무엇인가?

SideEffect(부수 효과)란 Composable 범위 밖에서 발생하는 앱 상태에 대한 변경이다.

SideEffect를 이해하기 위해서는 아래의 2가지를 이해해야 한다.

  1. Composable은 각각의 Lifecycle을 가지고 있다.
  2. Composable은 단방향으로만 State를 전달한다.

우리는 Composable을 사용할 때, 여러 Composable들을 겹쳐서 사용한다. 그러면 시스템은 각 Composable에 대한 Lifecycle을 만들고 Composable 별로 재구성이 필요할 때만 재구성시킨다. 또한, Composable은 기본적으로 바깥쪽 Composable이 안쪽 Composable로 State를 내려준다. 이로 인해 단방향 의존성이 생긴다.

하지만, 만약 안쪽에 있는 Composable에서 바깥쪽에 있는 Composable의 상태에 대한 변경을 준다면? 혹은 Composable에서 Composable이 아닌 앱 상태에 대한 변화를 준다면? 양방향 의존성으로 인해 예측할 수 없는 Effect(효과)가 생길 것이다. 이를 SideEffect라 부른다.

SideEffect란 Composable에서 자신이 아닌 외부의 State(상태)에 영향을 만드는 것을 뜻한다.

SideEffect의 예시

예를 들어, 메모 리스트를 표현하는 Screen(MemoListScreen)과 메모를 작성하는 Screen(MemoWriteScreen) 2가지 Screen으로 이루어진 앱을 만든다고 해보자. MemoWriteScreen에서 저장하면 MemoListScreen으로 navigation이 이동되어야 한다. 하지만, 저장하기 버튼 Composable은 navigation에 대한 참조가 없다. 따라서 Button Composable은 이러한 이벤트가 발생되면 navigation에 대한 변화를 만들어야 한다. 이러한 변화를 SideEffect(부수효과)라고 한다.

LaunchedEffect(key1 = viewModel._homeSideEffect) {
        viewModel._homeSideEffect.collect { sideEffect ->
            when (sideEffect) {
                is HomeSideEffect.NavigateProductDetailWeb -> {
                    Intent(Intent.ACTION_VIEW, Uri.parse(sideEffect.url))
                        .apply { context.startActivity(this) }
                }
                is HomeSideEffect.NavigateProductHomeWeb -> {
                    Intent(Intent.ACTION_VIEW, Uri.parse(sideEffect.url))
                        .apply { context.startActivity(this) }
                }
            }
        }
    }

SideEffect 처리하기

Compose는 이러한 SideEffect를 처리하기 위한 다양한 Effect API를 제공한다. 우리는 Compose에서 SideEffect를 처리하기 위해 다음 동작을 실행할 수 있는 Effect API를 사용할 수 있다.

  • LaunchedEffect : Composable Lifecycle Scope에서 suspend fun 실행하기 위해 사용
  • DisposableEffect : Composable이 Dispose될 때 정리되어야 할 SideEffect를 정의하기 위해 사용
  • SideEffect : Compose의 State를 Compose에서 관리하지 않는 객체와 공유하기 위해 사용

추가적으로 Compose는 위 3가지와 함께 사용할 수 있는 여러 CoroutineScope과 State 관련 함수를 제공한다.

  • rememeberCoroutineScope : Composable의 CoroutineScope을 참조하여 외부에서 실행할 수 있도록 한다.
  • rememberUpdatedState : LaunchedEffect는 컴포저블의 state가 변경되면 재실행되는데 재실행되지 않아도 되는 state를 정의하기 위해 사용
  • produceState : Compose State가 아닌 것을 Compose의 State로 변환
  • derivedStateOf : State를 다른 State로 변환하기 위해 사용한다. Composable은 변환된 State에만 영향을 받는다.
  • snapshotFlow : Composable의 State를 Flow로 변환한다.

Ref

profile
Android Developer
post-custom-banner

0개의 댓글