PHpullh

KOTLIN · 디자인패턴

MVI 패턴

Model-View-Intent 패턴으로 단방향 데이터 흐름을 구현합니다. 상태 관리가 예측 가능하고 디버깅이 쉽습니다.

디자인패턴고급mviunidirectionalreducerstate-management

핵심 설명

Model-View-Intent 패턴으로 단방향 데이터 흐름을 구현합니다. 상태 관리가 예측 가능하고 디버깅이 쉽습니다.

Kotlin code

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

// State
data class CounterState(val count: Int = 0, val loading: Boolean = false)

// Intent (사용자 액션)
sealed class CounterIntent {
    data object Increment : CounterIntent()
    data object Decrement : CounterIntent()
    data object Reset : CounterIntent()
}

// Store (Reducer)
class CounterStore {
    private val _state = MutableStateFlow(CounterState())
    val state: StateFlow<CounterState> = _state.asStateFlow()

    private val _intents = MutableSharedFlow<CounterIntent>()

    suspend fun processIntents() {
        _intents.collect { intent ->
            val current = _state.value
            _state.value = reduce(current, intent)
        }
    }

    private fun reduce(state: CounterState, intent: CounterIntent): CounterState =
        when (intent) {
            CounterIntent.Increment -> state.copy(count = state.count + 1)
            CounterIntent.Decrement -> state.copy(count = state.count - 1)
            CounterIntent.Reset -> CounterState()
        }

    suspend fun dispatch(intent: CounterIntent) {
        _intents.emit(intent)
    }
}

fun main() = runBlocking {
    val store = CounterStore()
    launch { store.processIntents() }
    val job = launch { store.state.collect { println("상태: $it") } }

    store.dispatch(CounterIntent.Increment)
    store.dispatch(CounterIntent.Increment)
    store.dispatch(CounterIntent.Decrement)
    delay(50)
    store.dispatch(CounterIntent.Reset)
    delay(50)
    job.cancel()
}

학습 팁

MVI의 reducer는 순수 함수이므로 단위 테스트가 매우 쉽습니다. 이전 상태 + Intent → 새 상태를 검증하면 됩니다.

주의할 점

reducer 내에서 부수 효과(API 호출 등)를 수행하지 마세요. 부수 효과는 미들웨어나 별도 계층에서 처리해야 합니다.

자주 묻는 질문

MVI 패턴란 무엇인가요?

Model-View-Intent 패턴으로 단방향 데이터 흐름을 구현합니다. 상태 관리가 예측 가능하고 디버깅이 쉽습니다.

MVI 패턴 학습 시 주의할 점은 무엇인가요?

reducer 내에서 부수 효과(API 호출 등)를 수행하지 마세요. 부수 효과는 미들웨어나 별도 계층에서 처리해야 합니다.