애플리케이션을 데이터를 처리하는 모델 (Model), 사용자에게 보여지는 UI인 뷰 (View), 뷰에 바인딩 되어 모델과 뷰 사이를 이어주는 뷰 모델 (View Model)로 분리하는 방식
모델과 뷰 뿐만 아니라 뷰와 뷰 모델간의 의존성까지 최소화한 형태로, UI가 실제 코드와 거의 완벽하게 분리되어 있다.
Model
도메인 중심
핵심 데이터와 규칙을 가진다.
Entity / data class, Domain logic, Repository interface 등이 포함된다
UI는 절대 알지 못하며, 어디든 사용해도 동일해야한다.
CounterModel.kt
data class CounterModel(var count : Int) class CounterRepository { private var _counter = CounterModel(0) fun getCounter() = _counter fun incrementCounter() { _counter.count++ } fun decrementCounter() { _counter.count-- } }
ViewModel
Model을 View가 이해할 수 있는 형태로 가공한다.
화면 상태 관리, 사용자 이벤트 처리, 비즈니스 로직 호출 등
View에 대한 참조가 없으며 상태 중심이다.
CounterViewModel.kt
class CounterViewModel() : ViewModel() { private val _repository: CounterRepository = CounterRepository() private val _count = mutableStateOf(_repository.getCounter().count) val count: MutableState<Int> = _count fun increment() { _repository.incrementCounter() _count.value = _repository.getCounter().count } fun decrement() { _repository.decrementCounter() _count.value = _repository.getCounter().count } }