LiveData 란?
관찰 가능(observing)한 데이터 홀더 객체로,
Activity, Fragment, Service 등의 앱 구성요소의 수명 주기(LifecycleOwner)를 인식한다.
그리고 수명 주기 인식을 통해 "활동 수명 주기 상태"에 있는 앱 구성요소 관찰자(observer)만 업데이트가 가능하다.
LiveData의 이점
- 관찰자(Observer) 패턴
- LiveData는 데이터가 변경될 때 Observer 객체에게 알리며,
이러한 관찰자 패턴으로 데이터가 변경될 때마다 UI를 자동으로 업데이트시킬 수 있다.
- LiveData는 데이터가 변경될 때 Observer 객체에게 알리며,
- 생애 주기 인식
- LiveData의 Observer는 Lifecycle 객체와 결합되어 있어 연결된 생명주기가 종료되면 자동으로 삭제된다.
- 관찰자 수명주기가 비활성화 상태(backstack 등)에 있을 경우, 관찰자는 어떤 LiveData 이벤트도 받지 않기 때문에 비정상 종료, 즉 해당 리소스(UI와 밀접한 리소스)가 유효하지 않는 경우 접근해서 생기는 오류를 방지할 수 있다.
- 최신 데이터 유지
- 생명주기가 활성화되면 최신 데이터를 수신한다.
예를 들어, 백그라운드에서 포어그라운드로 돌아온 직후 최신 데이터를 받을 수 있다. - 기기 회전과 같은 구성 변경으로 인한 Activity 및 Fragment가 다시 생성되면 사용 가능한 최신 데이터를 즉시 받게 된다.
- 생명주기가 활성화되면 최신 데이터를 수신한다.
// at ViewModel
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
// at Activity
model.currentName.observe(this) {
nameTextView.text = newName
}
LiveData 객체에 저장된 값을 업데이트하면 연결된 LifecycleOwner가 활성 상태에 있는 한 등록된 모든 관찰자가 트리거 된다.
전에 학습한 Flow의 Collect는 내부적으로 무한 루프를 돌아 값을 계속 관찰하는 것에 비해 LiveData는 콜백 방식의 트리거인 셈이다.
https://androidhelper.tistory.com/33
[Kotlin] Coroutine Flow란, 그리고 Flow, StateFlow, SharedFlow..
Coroutine Flow란?Flow는 Kotlin Coroutne 기반의 비동기 데이터 스트림 처리 도구이다. 데이터 스트림은 시간 흐름에 따라 연속적으로 발생하는 데이터를 순차적으로 처리하는 개념인데, Java의 Stream과 비
androidhelper.tistory.com
전에 포스팅한 Flow에 대한 내용
StateFlow에 대해서는 이전 글에서 다뤄본 적이 있다.
LiveData도 그렇고 StateFlow도 그렇고, 앱의 "상태"에 대한 표현 하는데 무척 적합해 보인다.
그리고 요즘 클린 아키텍처에 대한 패턴이 관심을 받고 여러 이유로 인해 LiveData에서 StateFlow로 마이그레이션을 진행하는 경우도 종종 발생하는데, 둘의 차이가 무엇이고 무엇 때문에 StateFlow로 마이그레이션을 진행하는 것일까?
개발자들이 StateFlow를 선택하는 이유 중 하나씩 뽑아보자면 다음과 같다.
우선, 생명 주기 인식
아까, LiveData의 이점에서도 나온 부분이다.
LiveData는 Android 의존성을 가져 생명 주기 인식하여 개발자가 신경 쓰지 않아도 메모리 누수의 위험성이 적다.
하지만, 이 장점 때문에 LiveData는 필연적으로 Android 의존성을 가지고 있을 수밖에 없다.
이 부분에서 많은 개발자들은 LiveData의 확장 사용하는데 고민을 하게 될 것이다.
Android는 권장하는 계층화된 표준 아키텍처가 존재한다.
요즘 클린 아키텍처에 대한 관심이 높아지면서 도메인 레이어는 (앱) 생태 의존성이 제거되며 어느 레이어에도 의존성을 가지지 않는 레이어 등의 암묵적인 규칙이 존재하나, 우선 여기서는 기본 Android 앱 아키텍처에 대해서만 가볍게 짚고 가자.
보다시피 안드로이드 아키텍처 가이드에서는 UI, Domain, Data 등의 계층화된 레이어로 관심사 분리를 중요시 여기고 있다.
UI는 UI, Data는 Data로 말이다. 여기에서 Android 생명주기의 의존성은 UI와 아주 밀접한 연관이 있다. 아니 그냥 UI 측 관심사다.
그렇기 때문에 LiveData는 UI Layer에서만 사용이 권장되는 한정적인 자원이라고 느끼게 된 것이다.
또한, Android 의존성이 생길 경우 일반 Unit 테스트를 하기 어려워진다.
그다음은 Flow는 훌륭한 데이터 스트림 처리 도구이다.
이거는 LiveData의 단점이라기보다는 Flow의 성능에 의해 밀려났다고 생각해 볼 수 있다.
Flow의 StateFlow는 SharedFlow의 특수한 형태로, 다양한 연산자는 물론이고 기본적으로 데이터 스트림 처리 도구이다.
그렇기 때문에 그저 "상태" 홀더 객체로 만들어진 LiveData 보다 더 유연한 처리가 가능한데,
가령, 중간 연산자가 그렇다.
또한, 하나의 StateFlow으로 추가적인 Flow 구성이 자유롭다.
private val _searchQuery = MutableStateFlow<String>("")
val searchQuery: StateFlow<String>
get() = _searchQuery
@OptIn(ExperimentalCoroutinesApi::class)
val searchPagingData = _searchQuery
.filter { it.isNotBlank() }
.flatMapLatest {
// 검색어가 있으면 해당 검색어로 PagingData 반환
getSearchCachingPagingUseCase(it)
}
.cachedIn(viewModelScope)
이런 폭발적이며 쉬운 사용성으로 인해 Flow가 사용되고, LiveData에서 점차 StateFlow를 사용하는 추세로 넘어갔다고 나는 생각한다.
이것은 LiveData의 특징이고 오히려 이 부분 때문에 다른 라이브러리가 아닌 LiveData를 사용하는 이유가 될 수도 있을 것이다.
무조건 LiveData는 구시대의 라이브러리이고 레거시 코드이다. 라기보다는 그에 맞게 적절하게 쓰는 것이 더 올바른 태도라고 생각된다.
LiveData의 생명 주기는 메모리 누수에 대한 관리를 라이브러리가 책임지면서 오히려 개발자 친화적인 라이브러리였다고 볼 수 있다.
그렇기 때문에 요즘 Flow가 대세라고 그냥 Flow로 휙 갈아타기보다는 정말 Flow가 필요해서 도입하는 걸까?라는 생각도 해보면 Flow를 사용하더라도 더 많은 기능들을 활용할 수 있는 시야가 트이지 않을까 한다.
어쩌면 어떤 앱에서는 LiveData 만으로 기능을 충족할 수 있을 수도 있을 것이다.
그렇다면 오히려 Android 의존성을 통해 메모리 누스 등의 생명주기가 자동으로 관리되는 LiveData가 더 우수한 성능을 이끌어내지 않을까 싶다.
참고 자료
https://developer.android.com/topic/libraries/architecture/livedata?hl=ko
LiveData 개요 | Android Developers
LiveData를 사용하여 수명 주기를 인식하는 방식으로 데이터를 처리합니다.
developer.android.com
https://developer.android.com/topic/architecture?hl=ko
앱 아키텍처 가이드 | App architecture | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 앱 아키텍처 가이드 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 가이드에는 고품질의 강력한
developer.android.com
'Android > 학습' 카테고리의 다른 글
[Git] GitFlow(깃플로우), 기존 Git 명령어 관점에서 (3) | 2025.08.23 |
---|---|
[Git] Git Merge 종류 (with. force push로 commit이 사라졌을 경우) (8) | 2025.08.09 |
[Kotlin] Coroutine Flow란, 그리고 Flow, StateFlow, SharedFlow.. (9) | 2025.07.06 |
[CS] 동기 vs 비동기, 블로킹 vs 논블로킹, 그리고.. (1) | 2025.06.14 |
[Android] RecyclerView의 동작 과정 (5) | 2025.05.16 |