단방향 데이터 흐름의 이해

2021. 11. 21. 19:00바삭바삭 IT/안드로이드

Compose의 중요한 키워드인 State를 이해하려면 먼저 기존의 View System의 흐름을 알아야 합니다.

기존의 View System은 아래와 같은 흐름을 갖고있었죠.

사용자가 버튼을 클릭 -> click event가 발생 -> event handler가 상태를 업데이트 -> 상태와 관련된 ui가 새로 업데이트됨

좀더 구체적인 예제로 알아볼까요?

구조화되지 않은 상태

사용자가 이름을 입력하면 바로 화면에 "Hello 이름"이 출력되게 하려고 합니다.

구현하는 한가지 방법은 TextView에 이벤트 콜백을 바로 추가하는 것이죠. viewBinding을 사용한다면 아래코드처럼 될것입니다.

class HelloCodelabActivity : AppCompatActivity() {

   private lateinit var binding: ActivityHelloCodelabBinding
   var name = ""

   override fun onCreate(savedInstanceState: Bundle?) {
  
       binding.textInput.doAfterTextChanged {text ->
           name = text.toString()
           updateHello()
       }
   }

   private fun updateHello() {
       binding.helloText.text = "Hello, $name"
   }
}

하지만 문제점이 많습니다.

1. 테스트의 어려움

2. 화면에 이벤트가 많아지면 관리가 힘듬

3. 코드의 복잡함

등등.. 단점이 많이 존재합니다.

 

기존의 구조화되지 않은 data flow를 개선하기 위해 AAC에서 제공되는 것이 ViewModel과 LiveData입니다.

 

단방향 데이터 흐름

viewModel는 ui에서 state를 추출시켜 줍니다. 그리고 viewModel에 ui업데이트를 하는 이벤트를 정의해 놓습니다.

위 예제를 viewModel을 사용하면 아래처럼 쓸 수 있습니다.

class HelloCodelabViewModel: ViewModel() {

   //state를 갖고있는 LiveData선언
   //UI에서 이를 관찰합니다.
   private val _name = MutableLiveData("")
   val name: LiveData<String> = _name

   //UI에서 호출하는 이벤트 입니다.
   fun onNameChanged(newName: String) {
       _name.value = newName
   }
}

class HelloCodeLabActivityWithViewModel : AppCompatActivity() {
   private val helloViewModel by viewModels<HelloCodelabViewModel>()

   override fun onCreate(savedInstanceState: Bundle?) {

       binding.textInput.doAfterTextChanged {
           helloViewModel.onNameChanged(it.toString()) 
       }

       helloViewModel.name.observe(this) { name ->
           binding.helloText.text = "Hello, $name"
       }
   }
}

 

위에 있는 두 코드의 차이는 무엇일까요?

viewModel을 사용하여 우리는 state를 Activity에서 분리시킬 수 있습니다. LiveData는 관찰가능한 state를 담는 홀더(그릇)으로 누구나 state의 변화를 감지할 수 있게 해줍니다. UI는 state가 변하는 것을 observe라는 메소드로 감지할 수 있습니다.

Observable
Observable은 말그대로 관찰가능한 객체로 예를들어, LiveData, Flow, StateFlow, Observable 등이 있습니다.

이렇게 구조화된 코드를 보면, "이벤트가 viewModel로 위로 흐른다"는 느낌이 들 것입니다. 그리고 state가 업데이트 되면 "state가 activity로 아래로 흐른다"라고 얘기 합니다. 아래 그림이 바로 이 얘기를 설명하고 있는거죠.

 

그리고 이 그림이 바로 "단방향 데이터 흐름"을 설명하고 있는 그림입니다. 이렇게 구조화된 코드로 얻을 수 있는 이점은 아래 3가지 입니다.

1. state를 ui에서 분리시키므로 테스트가 편함

2. state가 한곳에서만 업데이트 되므로 버그가 줄어듬

3. UI일관성 - observable로 모든 state가 ui에 즉각 반영됨

 

 


위 글은 Jetpack Compose codelab Using state in Jetpack Compose의 3. Understanding Unidirectional Data Flow 를 번역한 글 입니다.

 

https://developer.android.com/codelabs/jetpack-compose-state?authuser=4&continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fcompose%3Fhl%3Den%26authuser%3D4%23codelab-https%3A%2F%2Fdeveloper.android.com%2Fcodelabs%2Fjetpack-compose-state&hl=en#2 

 

Using state in Jetpack Compose  |  Android Developers

In this codelab you’ll learn about how to build rich, interactive, compose applications by managing state.

developer.android.com

 

반응형