Language \ Framework/Kotlin(Android)

[Android] ViewModel 간단 정리

구로모논 2025. 11. 27. 22:58

1. ViewModel의 역할

ViewModel은 화면의 상태(State)를 관리하는 역할을 합니다.
UI에 필요한 비즈니스 로직을 ViewModel에서 처리함으로써,
UI 코드와 비즈니스 로직을 명확하게 분리할 수 있습니다.

또한 ViewModel은 화면 구성 변경(예: 가로/세로 회전) 이 발생하더라도
데이터를 유지할 수 있기 때문에 안정적인 화면 상태 관리를 가능하게 합니다.

 

2. remember / rememberSaveable

remember와 rememberSaveable을 사용해도 상태 관리는 가능합니다.
두 API 모두 상태를 기억한다는 공통점이 있지만, 동작 방식에는 차이가 있습니다.

항목구성 변경(회전 등) 시 값 유지직렬화 필요비고
항목 구성 변경 시 값 유지 상태 직렬화 필요 비고
remember ❌ 초기화됨 필요 없음 단순 메모리 보존
rememberSaveable ⭑ 유지됨 ⭑ 필요함 Bundle 등에 저장되어 복원
  • rememberSaveable은 직렬화 가능한 타입만 저장할 수 있습니다.
    예: Int, String, 직렬화 가능한 List 등은 가능
    반면, 크기가 큰 객체 또는 직렬화 불가능한 객체(Service 등) 는 저장할 수 없습니다.

참고로 remember와 rememberSaveable은 Compose 환경에서만 사용 가능한 기능입니다.

 

3. ViewModel을 사용하는 이유

 

ViewModel을 사용하는 이유는 다양하지만, 대표적인 장점을 정리하면 다음과 같습니다.

* 유지보수성 및 재사용성 향상

여러 Composable에서 동일한 데이터나 로직이 필요할 경우,
각 화면에서 따로 구현할 필요 없이 ViewModel을 공유하여 재사용할 수 있습니다.
그 결과 생산성과 유지보수성이 모두 높아집니다.

* UI와 비즈니스 로직 분리

UI 코드 내부에 비즈니스 로직이 혼재되면 코드 가독성이 떨어지고 유지보수가 어려워집니다.
ViewModel을 활용하면 UI는 UI 역할에 집중하고,
비즈니스 로직은 ViewModel에서 관리할 수 있어 역할 분리가 명확해집니다.

* 안정적인 데이터 관리

화면 회전 및 구성 변경으로 View가 재생성되더라도
ViewModel은 메모리에 유지되기 때문에,
사용자가 보고 있던 UI 데이터가 보존됩니다.

 

4. 사용법

  • build.gradle.kts
 
// 의존성 추가
dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.x.x") // 최신 버전 확인
}

 

 

  • TestScreen.kt
@Composable
fun TestScreen(
    vm: TestViewModel = viewModel()
) {
    // TestUiState
    val ui by vm.state.collectAsState()
    Column {
        Text(ui.count.toString())
        Button(
            onClick = { vm.countUp() }
        ) {
            Text("Count up!")
        }    
    }
}

 

 

  • TestViewModel.kt
class TestViewModel(): ViewModel() {
	
    data class TestUiState(var count: Int = 0)
    
    private val _state = MutableStateFlow(TestUiState())
    val state: StateFlow<TestUiState> = _state.asStateFlow()
    fun countUp() {
        _state.update {
            it.copy(
                count = it.count + 1
            )
        }
    }
}

 

 

아주 간단한 코드 예시만 작성하긴 했는데, 실제로는 UI상의 로직을 여기다 구현하기 때문에, 더 복잡하게 구현 되어 있을 수 있습니다.