https://www.youtube.com/watch?v=b2z1jvD4VMQ
오늘 유튜브에서 PhilippLackner님의 영상을 보게되었습니다. 해당 영상에서는 MVVM과 MVI 그 차이점에 관하여 말하고 있었습니다.
저는이전에 MVC MVP MVVM MVI의 차이에관하여 글을 작성한적이 있습니다.
https://velog.io/@kshk0897/Android-MVC-MVP-MVVM-MVI%EC%9D%98-%EC%B0%A8%EC%9D%B4
이글에서는 MVI는 MVVM에서 상태를 사용자가지정한 Intent의 형태로 ViewModel에서 관리하여 해당Intent변경을 감지하여 상태에따른 동작을 하는것이라고 말한적이 있습니다.
영상에서는
MVVM과 MVI가 프레젠테이션 패턴이며 이러한 패턴은 프레젠테이션 레이어를 다른 부분으로 분리하기 위한것일뿐이며 전체 앱을 다른 부분으로 분리하기 위한것이 아닙니다. 왜냐하면 사람들이 mvvm또는 클리아키텍처를 사용해야 하는지에관하여 자주 듣기 때문입니다. 이는 하나의 프로젝트에서 둘 다 사용할수 있는 매우 다른것입니다. 클린아키텍처는 전체 앱을 다른 부분으로 다른 레이어로 분리하는 반면 mvvm은 클린아키텍처 프로젝트의 한 부분인 프레젠테이션 레이어만 다른 부분으로 분리하기 때문입니다.
이런말이 나옵니다. 즉, 클린 아키텍처는 전체 애플리케이션의 아키텍처를 설계하는 개념이며, MVVM은 그 중 하나의 요소인 프레젠테이션 레이어를 다른 부분으로 분리하는 데 사용되는 구체적인 디자인 패턴입니다. 이부분은 중요합니다. MVVM을 구축했다고 클린아키텍처인거은 아닙니다.
MVI와 MVVM의 차이에 관해서는 ViewModel에서 상태를 하나로만 관리를 할수있다는 점입니다. MVVM같은경우 여러 상태를 관리하기위해서 여러개의 프로퍼티로 관리를 하게되니 그만큼 관리해야될 프로퍼티도 많아지고 해당 프로퍼티를 모두 감지해야되니 이부분이 하나의 State로 관리하게된다면 감지하는곳 조건문으로 해당 state에 맞는 동작을 수행할수 있게되니 MVI가 기존의 MVVM에 비해 가독성과 코드의 양을 줄여줍니다. 입력같은 경우에는 사용자가 지정한 Intent를 주게되면 해당 인텐트에 맞는 동작을 하게됩니다. 이렇게 Intent를 넘겨주는것은 하나의 메서드나 프로퍼티로만 있어야 할것입니다.
sealed class MviIntent {
object LoadImage : MviIntent()
}
sealed class MviState {
object Idle : MviState()
object Loading : MviState()
data class LoadedImage(val image: Image, val count: Int) : MviState()
}
// in ViewModel
val channel = Channel<MviIntent>()
private val _state = MutableStateFlow<MviState>(MviState.Idle)
val state : StateFlow<MviState> get() = _state
init {
handleIntent()
}
private fun handleIntent() {
viewModelScope.launch {
channel.consumeAsFlow().collectLatest {
when(it) {
MviIntent.LoadImage -> {
loadImage()
}
}
}
}
}
위 코드는 이전글에서 사용했던 코드입니다. 해당 코드에서 로 퍼블릭인 Channel로만 Intent를 받고 StateFlow를 이용하여 현재상태를 최신화하고 감지하여 상태에 맞는 로직을 동작하도록 구현할수있습니다.