많은 포스팅에서 MVI가 상태를 쉽게 관리해주기 때문에 상태가 중요한 Compose에서 적절한 패턴이라고 소개하고 있다
이 부분에서 의문이 들었다.
MVVM 패턴에서는 상태를 쉽게 관리해주지 않나?
MVVM 패턴에서는 단방향 흐름을 제공하지 못하나?
많은 고민을 하다가 내린 결론은 MVVM으로도 충분히 상태를 관리할 수 있다는 것이다.
다만, MVI는 MVVM을 더 엄격하게 구조화한 패턴이라고 생각된다.
즉, 상태를 쉽게 관리할 수 있다라는 말은 MVI패턴을 적용하면 상태를 더 엄격하게 관리할 수 있기 때문에, 예기치 못한 상태변경을 방지할 수 있고, 그렇기 때문에 상태관리가 더 쉬워진다라고 이해했다
MVVM처럼 MVI도 관심사를 나누고 해당 관심사의 앞글자를 따서 만든 패턴이다

가장 큰 특징은 단방향 흐름 구조로 유지한다는 점이라고 할 수 있다
이 UDF 구조를 엄격하게 유지하기 위해 Intent라는 개념이 추가되었고, Intent는 사용자의 의도이다(UI 화면에서 어떤 행위를 할건지에 대한..)
UI 내에서 사용자의 의도를 Model로 전달하고, Model은 이를 캐치하여 상태를 변경하며, 이를 View에 적용시킨다
선언형 UI 패턴과 자연스럽게 연결됨
상태(State) 추적이 쉬워 유지보수와 디버깅이 편리함
테스트가 용이해지고, 앱의 안정성이 증가함
@Test
fun testCounterViewModel() = runTest {
val viewModel = CounterViewModel()
viewModel.increase()
assertEquals(1, viewModel.count.first()) // ✅ 상태가 정확하게 변경되었는지 확인
}
abstract class BaseViewModel<Event: UiEvent, State : UiState, Effect : UiEffect> : ViewModel() {
private val initialState : State by lazy {createInitialState()}
abstract fun createInitialState() : State
private val _uiState : MutableStateFlow<State> = MutableStateFlow(initialState)
val currentState: State get() = _uiState.value
val uiState = _uiState.asStateFlow()
private val _event : MutableSharedFlow<Event> = MutableSharedFlow()
val event = _event.asSharedFlow()
private val _effect : Channel<Effect> = Channel()
val effect = _effect.receiveAsFlow()
init {
viewModelScope.launch {
event.collect{
handleEvent(it)
}
}
}
abstract fun handleEvent(event : Event)
fun setEvent(event:Event){
val newEvent = event
viewModelScope.launch {
_event.emit(newEvent)
}
}
protected fun setState(state: State){
_uiState.value = state
}
protected fun setEffect(effect : Effect){
viewModelScope.launch {
_effect.send(effect)
}
}
}