Compose 상태 관리(2)

햄햄·2022년 5월 31일
0

Compose

목록 보기
4/7
post-thumbnail

Stateful, Stateless

remember를 사용하여 객체를 저장하는 composable은 내부 상태를 생성하여 composable을 Stateful로 만듭니다. 이는 호출자가 상태를 제어할 필요가 없고 상태를 직접 관리하지 않아도 상태를 사용할 수 있는 경우에 유용합니다. 그러나 내부 상태를 갖는 composable은 재사용 가능성이 적고 테스트하기가 더 어려운 경향이 있습니다.

Stateless composable은 상태를 갖지 않는 composable입니다. Stateless를 달성하는 한 가지 쉬운 방법은 State hoisting을 사용하는 것입니다.

State hoisting

Compose에서 State hoisting(직역하면 상태 끌어올리기)는 composable을 Stateless로 만들기 위해 상태를 composable의 호출자로 옮기는 패턴입니다.
State hoisting를 위한 일반적인 패턴은 상태 변수를 다음 두개의 매개변수로 바꾸는 것 입니다.

  • value: T: 표시할 현재 값
  • onValueChange: (T) -> Unit: T가 제안된 새 값인 경우 값을 변경하도록 요청하는 이벤트
@Composable
fun HelloScreen() {
    var name by rememberSaveable { mutableStateOf("") }

    HelloContent(name = name, onNameChange = { name = it })
}

@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello, $name",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.h5
        )
        OutlinedTextField(
            value = name,
            onValueChange = onNameChange,
            label = { Text("Name") }
        )
    }
}

위 예에서는 HelloContent에서 nameonValueChange를 추출한 다음, 이러한 항목을 HelloContent를 호출하는 HelloScreen composable로 옮깁니다.

위와 같이 수정하게 되면 HelloContent에서 상태를 끌어올리면 더 쉽게 composable을 추론하고 여러 상황에서 재사용하며 테스트할 수 있습니다. 또한, HelloScreen을 수정하거나 교체할 경우 HelloContent의 구현 방식을 변경할 필요가 없습니다.
위 그림과 같이 상태가 내려가고(HelloScreen -> HelloContent) 이벤트가 올라가는(HelloContent -> HelloScreen) 패턴을 단방향 데이터 플로우(unidirectional data flow)라고 하고, 이를 따르면 UI에 상태를 표시하는 composable과 상태를 저장하고 변경하는 앱 부분을 서로 분리할 수 있습니다.

상태를 끌어올리는 다른 방법은?

위 예와 같이 간단한 상태 끌어올리기는 composable에서 관리가 가능합니다. 그러나 저장해야하는 상태의 양이 많거나 로직이 발생하는 경우 이러한 책임을 State holder에 위임하는 것이 좋습니다.
정리하자면,

  • composable : 간단한 UI 요소 상태 관리
  • State holder : 복잡한 UI 요소 상태 관리, UI 요소 상태와 UI 로직 소유
  • ViewModel : 비즈니스 로직이나 UI 상태에 대한 액세스 권한을 제공하는 특수한 유형의 State holder

0개의 댓글