https://velog.io/@evergreen_tree/Android-MVI-%ED%8C%A8%ED%84%B4 에서 이어집니다.
MVI는 순수 함수로 이루어진 Pure Cycle과, 부수효과가 포함되어있는 SideEffct Cycle로 표현할 수 있습니다.
이번 포스팅에서는, https://orbit-mvi.org/ MVI 프레임워크 중 하나인, orbit을 사용해 MVI의 Pure cycle에 대해 이해하겠습니다.
순수 함수와 부수 효과에 대해 들어보신 적이 있나요❓
함수형 프로그래밍 : 부수 효과를 없애고 순수 함수를 만들어 모듈화 수준을 높이는 프로그래밍 패러다임
- 부수 효과 : 외부의 상태를 변경하는 것, 함수로 들어온 인자의 상태를 직접 변경하는 것
- 순수 함수 : 부수효과가 없는 함수 즉, 어떤 함수에 동일한 인자를 주었을 때 항상 같은 값을 리턴하는 함수
순수 함수는 어떤 함수에 동일한 인자를 주었을 때 항상 같은 값을 리턴하는 함수입니다.
Pure cycle은 순수 함수와 동일한 맥락입니다
Pure cycle은 intent(event) == state
,을 만족하는 사이클입니다. 즉 어떠한 의도로 인해 발생하는 결과는 항상 “상태” 입니다.
버튼을 누르면 아래 숫자가 증가하는 프로그램을 Compose와 MVI 형식으로 아주 간단하게 만들어 보았습니다.
intent()
를 통해, add(number: Int)
이벤트를 발생 시켜서 기존 count 값에 number을 더해 새로운 상태를 생성하는 예제를 살펴보겠습니다.
implementation("org.orbit-mvi:orbit-viewmodel:4.3.2")
testImplementation("org.orbit-mvi:orbit-test:4.3.2")
→ 먼저 orbit 의존성을 추가합니다. 왜 Framework를 이용해야 하는지는 이전 글(https://velog.io/@evergreen_tree/Android-MVI-%ED%8C%A8%ED%84%B4)에 나와있습니다.
data class CalculatorState (
val total: Int = 0
)
→ View에 렌더링 할 값인 total 을 가지는 Model(State)을 생성합니다.
class CalculatorViewModel: ViewModel(), ContainerHost<CalculatorState, CalculatorSideEffect> {
override val container = container<CalculatorState,CalculatorSideEffect>(CalculatorState())
fun add(number :Int) = intent{
reduce{
state.copy(total = state.total + number)
}
}
}
ViewModel 에서 State와, SideEffect를 가지고 container를 재정의합니다.
container에 선언에는 State와 SideEffect를 명시해 줘야 하는데, 일단은 Pure cycle에 대해서만 설명할 것이므로 임의로 넣어놨습니다.
add라는 메소드를 intent에 담고 연산된 결과를 reduce를 통해 새로운 state를 만들어 냅니다.
reduce는 순수 함수로, 그저 새로운 state를 만들어 냅니다.
@Composable
fun TestPage(
viewModel: CalculatorViewModel,
) {
val state by viewModel.container.stateFlow.collectAsState()
Column{
Button(onClick ={viewModel.add(1)}){
Text("1이 증가하는 버튼")
}
Text("${state.total}")
}
→ 버튼의 이벤트로 viewModel.add()
를 전달하게 되면 ViewModel에서 Intent로 감싸져 새로운 상태를 생성하게 됩니다.
val state by viewModel.container.stateFlow.collectAsState()
view는 상태를 관찰하고 있기 때문에, Recomposition이 발생하여 새로운 상태를 렌더링 하게 됩니다.
이처럼 pure cycle은 상태 관리에서 가장 중요한 역할을 하고, 개발자의 실수를 줄여줍니다. 예상 가능한 값을 반환하기 때문에 테스트 코드를 작성하기에 용이합니다
👉다음 포스팅에서는 SideEffect Cycle 에 대해서 알아보겠습니다.
https://sungbin.land/아직도-mvvm-이젠-mvi-시대-319990c7d60
https://medium.com/@kimdohun0104/mvi-패턴에-대한-고찰-이유와-방법-그리고-한계-767cc9973c98
https://dev.to/kaleidot725/implementaing-jetpack-compose-orbit-mvi-3gea
ㅎㅎ 1빠!