Jetpack Compose에서 상태 호이스팅(state hoisting) ~ 상태관리패턴

JaeEun Lee·2024년 10월 27일

SwiftUI & Jetpack compose

목록 보기
4/10

개요

Jetpack Compose에서 상태 호이스팅(state hoisting)은 컴포넌트의 상태를 관리할 때 권장되는 패턴입니다. 이 패턴은 컴포넌트 간의 데이터 관리를 단순화하고 상태의 일관성을 유지하기 위한 효과적인 방법입니다.

상태 호이스팅이란?

상태 호이스팅은 자식 컴포넌트의 상태를 부모 컴포넌트로 끌어올려 자식 컴포넌트는 상태를 관리하지 않고 그리기만 하도록 하는 방법입니다. 이를 통해 상태를 한 곳에서 관리하여 다른 컴포넌트들이 쉽게 해당 상태에 접근하고 업데이트할 수 있습니다.

어떨때 사용할까?

가독성을 위해 composable View를 분리하여 만드는것(Atomic Design)이 일반적인데 그렇게 하다보면 하위 뷰에서 ViewModel를 상태에 접근하는 경우가 생기는데 이러한 코드는 상태의 변화를 알기 어렵게 합니다. 또 상태를 하위뷰까지 전달하려면 파라메타가 많아지거나 코드관리가 복잡해지는 경우도 종종 발생하게 됩니다. 이 패턴은 그러한 문제를 해결해 줄 수 있습니다.

상태 호이스팅의 베스트 프랙티스

  • 상태의 이동: 상태는 가장 하위의 공통 부모 컴포넌트에 위치시킵니다. 상태 값과 상태를 변경할 수 있는 함수는 자식 컴포넌트에 전달합니다.

  • 단일 책임 원칙: 각 컴포넌트는 하나의 역할에만 집중합니다. 상태를 소유한 컴포넌트는 상태 관리에 자식 컴포넌트는 그리기에만 집중하도록 합니다. 이로 인해 코드의 가독성과 유지보수성이 향상됩니다.

예제 시나리오

Repository에서 데이터를 가져오는 fetchData() 함수가 있다고 가정합니다.
ViewModel이 상태와 이벤트를 관리하여 Composable 함수에 전달합니다.
Composable 함수는 ViewModel에서 받은 상태를 사용하여 데이터를 표시합니다.

import androidx.compose.runtime.*
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.delay

// Repository 정의
class MyRepository {
    fun fetchData(): String {
        // 예시로 네트워크 호출 또는 데이터베이스 작업 대신 지연 후 데이터 반환
        return "Fetched Data"
    }
}

// ViewModel 정의
class MyViewModel(private val repository: MyRepository) : ViewModel() {

    // 상태를 State로 관리
    private val _data = mutableStateOf("Loading...")
    val data: State<String> = _data

    // 데이터 불러오기
    fun loadData() {
        viewModelScope.launch {
            // 네트워크 지연을 가정
            delay(1000)
            _data.value = repository.fetchData()
        }
    }
}

// Composable 함수 정의
@Composable
fun MyScreen(viewModel: MyViewModel) {
    val data by viewModel.data

    // UI 구성
    Column {
        Text(text = "Data: $data")
        Button(onClick = { viewModel.loadData() }) {
            Text("Load Data")
        }
    }
}

// 부모 Composable에서 ViewModel과 Repository를 주입하여 상태 호이스팅 적용
@Composable
fun ParentComponent() {
    // ViewModel을 초기화하고 Repository를 주입합니다.
    val repository = MyRepository()
    val viewModel = remember { MyViewModel(repository) }

    // MyScreen에 ViewModel을 전달하여 상태 호이스팅 적용
    MyScreen(viewModel = viewModel)
}

참고링크

https://medium.com/@android-world/jetpack-compose-meets-atomic-design-ee24878b919

https://developer.android.com/develop/ui/compose/state-hoisting?hl=ko

profile
공업철학프로그래머

0개의 댓글