Compose State Hoisting

HEETAE HEO·2023년 2월 17일
0
post-thumbnail

State Hoisting

State Hoisting은 UI 컴포넌트가 상태를 가지지 않고 대신 상태를 렌더링 하는 컴포넌트로부터 전달받는 패턴을 말합니다. 이 패턴을 사용하면 코드의 가독성, 유지보수성, 테스트 용이성이 향상됩니다.

상태 호스팅의 핵심 개념은 UI 컴포넌트는 상태를 가지지 않는다는 것입니다.
이렇게 하면 UI 컴포넌트의 코드는 간결해지고 명확해지는 효과가 있습니다. 또한 상태를 외부에서 관리하면서 UI 컴포넌트는 외부에서 전달해주는 상태에 따라 구현만 되면 되는 것입니다.

간단한 버튼 클릭으로 설명드리겠습니다.

@Composable
fun MainScreen() {
    var count by remember { mutableStateOf(0) }
    Button(onClick = { count++ }) {
        Text("Count: $count")
    }
}

위의 Composable 함수를 보면 count라는 변수를 생성하고 버튼을 클릭할 때마다 숫자가 1씩 증가하게 되어 있습니다. 이렇게 되면 단점이 무엇이냐 하면 바로 값 즉 상태가 변경될 때마다 리컴포지션 즉 재구성이 발생하게 되는 것입니다. 버튼 내부의 Text뿐만 아니라 Button까지 말입니다. 위의 코드에서는 버튼과 Text 단 2개이지만 굉장히 많은 UI와 한 두개의 변수가 아닌 여러 개의 변수가 위의 코드처럼 선언된다면 어떻게 될까요?

하나의 값 변경으로 인해 전체 UI 재구성되는 -> 리소스가 굉장히 낭비가 되는 일이 발생하게 된다는 것입니다.

그렇기에 상태 호스팅을 이용하여 Text만 리컴포지션되게 만들어주는 것 입니다.

@Composable
fun MainScreen(count: Int, onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("Count: $count")
    }

Counter와 onClick을 매개변수로 받아 UI컴포넌트가 아닌 상태를 관리해주는 컴포넌트에서 관리하게 되는 것입니다.

코드의 재사용성도 올라가고 앱의 성능도 올라가게되는 것입니다.

Compose 사용 주의점

  1. 상태는 항상 불변성(immutability)을 유지해야 합니다. 즉 상태를 변경할 때마다 새로운 상태 객체를 생성해야 합니다. 이를 통해 불필요한 리컴포지션을 피할 수 있습니다.
  2. remember 함수를 사용하여 상태를 호스팅할 때 초기화 코드는 Composable 함수의 바깥쪽에 위치해야 합니다. 초기화 코드가 Composable 함수 내부에 위치하면 매번 함수가 실행될 때마다 상태가 재설정 됩니다.
  3. remember 함수는 Composable 함수 내부에서만 호출할 수 있습니다. 다른 함수에서 호출할 경우 예외가 발생합니다.
  4. 상태가 변경될 때마다 Composable 함수가 다시 실행되므로, Composable 함수 내부에서 무거운 작업을 수행하지 않는 것이 좋습니다.

위의 주의점에서 2번이 쉽게 이해가 되지 않습니다. 그렇기에 2번을 코드로 설명드리겠습니다.

@Composable
fun MainScreen() {
    val count = remember { mutableStateOf(0) }
    ...
}

위의 코드에서 remember 함수를 호출하여 count 상태를 호스팅하고 있고 초기값으로 0을 사용하고 있습니다.

하지만 만약 remember함수가 Counter 함수 내부에 위치하다면 어떻게 구현이 될까요?

@Composable
fun Counter() {
    val count = mutableStateOf(0)
    remember {
        count.value = 0
    }
    ...
}

위의 처럼 구현을 하게 된다면 함수가 실행될 때마다 count.value = 0이 실행 된다는 것입니다.

상태 호스팅의 단점

  1. 상태 호스팅을 사용하면 코드가 복잡해질 수 있습니다. 상태가 여러 개이고, 그 상태들 간에 의존성이 있는 경우 코드가 더욱 복잡해집니다.

  2. 상태 호스팅을 사용하면, 객체 생성 비용이 추가됩니다. 이는 메모리 사용량이 늘어나고, 성능 저하의 원인이 될 수 있습니다.

  3. 상태가 변경될 때마다 Composable 함수가 다시 실행되므로, UI가 자주 갱신됩니다. 이는 사용자 경험을 해칠 수 있습니다. 따라서, 상태가 자주 변경될 필요가 없는 경우에는 상태 호스팅을 사용하지 않는 것이 좋습니다.

마치며

오늘은 Compose에서의 상태 호스팅에 대해서 설명드렸습니다.
긴글을 읽어주셔서 감사합니다.

profile
Android 개발 잘하고 싶어요!!!

0개의 댓글