LiveData와 Flow가 뭔지 정리해보고 어떻게 사용하는 지에 대해 알아본다. 추가로, 두 가지가 유사하면서도 다른 점들이 있기에 주요한 차이점과 적절한 사용법도 알아보자.
LiveData & Flow
- LiveData는 안드로이드 앱 개발에서 일반적인 작업인 데이터 전송의 한 방법이다.
- Kotlin Flow도 데이터를 전송하는 것이며 비동기로 전송할 수 있는 기능이 있다.
두 가지 방법 모두 기존의 전통적인 문제를 극복하기 위해 설계되었으며, 장점과 더불어 한계점도 있다.
LiveData
관찰 가능한 데이터 홀더 클래스, 다른 안드로이드 컴포넌트들(activity, fragment, service)에 의해 관찰될 수 있는 데이터들의 집합이라고 생각하면 된다.
관찰 가능한 다른 일반 클래스들과 다른 점은 LiveData는 LifeCycle을 인식한다는 점이다. 이로 인해, 데이터를 관찰하던 컴포넌트가 destroy되거나 비활성화되면 LiveData는 observer에게 데이터를 publish하는 것을 중단한다. 이 부분은 기존에 있던 안드로이드 개발자들의 많은 문제들을 해결해준다.
요즘에는 대부분 MVVM 아키텍처를 사용하며 여기에서 LiveData를 이용하여 ViewModel에서 View로 데이터를 통신하거나 전송한다. 이는 ViewModel과 View가 Life Cycle를 인식하며 통신할 수 있도록 해주고 메모리 누수를 줄일 수 있도록 해준다.
장점들을 정리하면 다음과 같다.
- 메모리 누수 없음
- 중지된 컴포넌트로 인한 Crash 없음
- Life Cycle을 직접 핸들링하지 않아도 됨
- Resource 공유
공식 문서에 따른 장점
- UI와 데이터 상태의 일치 보장
LiveData는 Observer 패턴을 따른다. LiveData는 기본 데이터가 변형될 때 Observer 객체에 알리고, Observer는 UI를 업데이트 할 수 있다. 이렇게 하면 앱 데이터가 변경될 때마다 Observer가 UI를 업데이트 하므로 개발자가 직접 업데이트 할 필요가 없다. - 메모리 누수 없음
Observer는 Lifecycle 객체에 결합되어 있으며 연결된 수명 주기가 끝나면 자동으로 삭제된다. - 중지된 활동으로 인한 비정상 종료 없음
활동이 백 스택에 있을 때를 비롯하여 Observer의 수명 주기가 비활성 상태에 있으면 Observer는 어떤 LiveData 이벤트도 받지 않는다. - 수명 주기를 더 이상 수동으로 처리하지 않음
UI 구성요소는 관련 데이터를 관찰하기만 할 뿐 관찰을 중지하거나 다시 시작하지 않는다. LiveData는 관찰하는 동안 관련 LifeCycle 상태의 변경을 인식하므로 이 모든 것을 자동으로 관리한다. - 최신 데이터 유지
수명 주기가 비활성화되면 다시 활성화될 때 최신 데이터를 수신한다. 예를 들어 background에 있었던 활동은 foreground로 돌아온 직후 최신 데이터를 받는다. - 적절한 구성 변경
기기 회전과 같은 configuration 변경으로 인해 Activity 또는 Fragment가 다시 생성되면 사용 가능한 최신 데이터를 즉시 받게 된다. - 리소스 공유
앱에서 시스템 서비스를 공유할 수 있도록 싱글톤 패턴을 사용하는 LiveData 객체를 확장하여 시스템 서비스를 래핑할 수 있다. LiveData 객체가 시스템 서비스에 한 번 연결되면 리소스가 필요한 모든 Observer가 LiveData 객체를 볼 수 있다. 자세한 내용은 LiveData 확장을 참고하면 된다.
LiveData 사용법
title과 icon을 String, Drawable 타입의 LiveData로 선언했다. postValue()나 setValue()를 통해 MutableLiveData의 값을 업데이트 할 수 있고, Observer는 LiveData 타입을 통해 접근할 수 있도록 해주는 것이 좋다.
title(String)과 icon(Drawable)에 대해서 Observer를 생성하고, title TextView와 icon ImageView를 업데이트 하도록 했다. 그리고 이를 ViewModel에 있는 LiveData에 할당하여 observe하고 activity context를 넘겨준다. LiveData는 이 Context가 active 상태인 경우에만 observer에게 업데이트를 전달한다.
LiveData와 DataBinding 함께 사용
LiveData와 DataBinding을 함께 사용하는 경우에는 더 간결하게 표현해서 사용할 수 있다.
먼저, 레이아웃 파일에서 root를 <layout> 하나로 변경해주고 data class로 binding Class의 경로와 이름을 지정(선택)하고 여기에 변수를 지정해서 사용할 수 있다. type에서 원하는 기본 타입을 설정할 수 있고 그렇지 않으면 위의 경우와 같이 ViewModel과 같은 class 타입도 통째로 지정해줄 수 있다. title과 icon을 각각 string, drawable로 지정할 수 있지만 여기서는 ViewModel만 한번에 지정했다. 그러면 레이아웃 요소에서 LiveData를 변수처럼 사용할 수 있다. TextView의 android:text="@{vm.title}"나 ImageView의 android:src="@{vm.icon}"와 같이 사용하면 앞서 Observer를 생성하고 observe를 한 것과 동일하게 동작한다.
Activity의 코드가 훨씬 간결해졌다.
Kotlin Flow
Flow는 값을 순차적으로 내보낼 수 있는 타입이다. Flow는 Coroutines를 기반으로 빌드되며 여러 값을 제공할 수 있고, 비동기식으로 계산할 수 있는 데이터 스트림의 개념이다. 이 그림에서 Producer는 스트림에 추가되는 데이터를 생산한다. 코루틴을 이용하여 비동기 방식으로 데이터를 생산할 수도 있다. Intermediary는 stream에 내보내는 각각의 값이나 스트림 자체를 수정할 수 있고 이는 선택사항이다. Consumer는 스트림의 값을 사용하는 대상이다. Android에서 일반적으로 Consumer는 View이고 Producer는 데이터 소스 또는 저장소이다. Intermediary는 상위 레이어의 요구사항에 맞게 조정하기 위해 데이터 스트림을 수정하는 중개자의 역할을 수행한다.
비동기 프로그램의 문제를 해결하기 위해 Rx가 나왔고, 이후에 나온 Coroutines는 더 정교한 방법을 제시하며 문제들을 해결했다. 이후에 Coroutines는 Flow API를 고안하여 순차적으로 실행되는 데이터 스트림을 비동기적으로 처리할 수 있도록 했다.
Flow 사용법
Coroutines의 collect를 통해 ViewModel의 title가 변경될 때마다 TextView가 업데이트 되도록 했다.
LiveData와 Flow 차이
LiveData는 LifeCycle 관련 문제를 처리하기 위해 추가적인 것들을 복잡하게 사용할 필요 없이 데이터를 관찰하는 데 사용된다. 구글 공식 문서에 따르면 LiveData Transformation과 MediatorLiveData를 사용하여 LiveData 객체 작업을 할 수 있지만, LiveData는 비동기 데이터 스트림을 처리하도록 설계되지 않았기 때문에 이렇게 사용할 경우 단점이 있다. 결합 기능이 제한적이고 변환을 통해 만들어진 객체를 포함한 모든 LiveData가 Main Thread에서 관찰된다. LiveData를 쓰고 싶은데 앱의 다른 레이어에서 스트림 변환이 필요한 경우에는 Kotlin Flow에서 작업하고 asLiveData()를 통해 사용하도록 권장하고 있다.
Flow는 연속적인 데이터 통합을 위해 사용되며 Async 프로그래밍도 단순화된 상태로 사용할 수 있다.
결론
복잡한 비동기 작업이 포함될 수 있는 데이터 흐름을 처리하거나 간단하지 않은 transformation이 필요한 경우에는 Kotlin Flow를 사용하여 처리하는 것이 좋다. 그렇지 않고 상태 변경과 같이 단순한 작업이 필요한 경우에는 LiveData를 사용하면 된다. asLiveData()를 통해 UI의 Observer는 LiveData를 사용하고 앱의 하위 레이어와 같은 곳에서는 Flow를 통해 작업을 처리해도 좋다.
References
https://developer.android.com/topic/libraries/architecture/livedata
https://developer.android.com/kotlin/flow
https://developer.android.com/codelabs/advanced-kotlin-coroutines
'Android > Android Development' 카테고리의 다른 글
Android ViewModel에서 Context를 올바르게 사용하는 방법 (592) | 2022.08.08 |
---|---|
DataStore of Android Jetpack (828) | 2021.10.24 |
Android LiveData setValue vs postValue (2) | 2021.10.21 |
Android Custom Lint Checks (1427) | 2021.08.22 |
Google I/O '21 (1785) | 2021.06.20 |
댓글