Jetpack Compose로 마이그레이션을 진행하면서, 기존 LiveData 기반의 ViewModel 코드를
StateFlow + Flow 중심 구조로 함께 개선했습니다.
특히 즐겨찾기 화면에서는 그동안 LiveData 기반으로 onResume() 시점마다 수동으로 데이터를 다시 불러와야 했는데요,
이번에는 StateFlow와 Room + Flow 조합을 통해 자동으로 갱신되는 UI 흐름으로 전환하게 되었습니다.
이를 통해 어떤 점이 개선되었고, 실제로 어떤 구조의 차이가 있었는지 정리해보고자 합니다.
기존 방식: 수동 갱신이 필요했던 구조
기존에는 ViewModel 내부에서 다음과 같이 데이터를 불러오는 방식을 사용하고 있었습니다.
private fun loadFavoritePhotos() {
viewModelScope.launch {
_photos.value = getFavoritePhotoListUseCase.execute()
}
}
- 위 방식은 데이터를 한 번만 가져오고 끝나는 구조입니다.
- Room에서 즐겨찾기를 추가하거나 삭제해도 UI는 자동으로 갱신되지 않기 때문에,
Fragment의 onResume() 시점마다 loadFavoritePhotos()를 매번 호출해야 했습니다. - 즉, 정적인 데이터 스냅샷을 UI에 반영하는 방식이었습니다.
개선 방식: Flow를 통해 자동으로 데이터 감지
Room에서 제공하는 DAO 함수를 다음과 같이 Flow로 변경하였습니다.
@Query("SELECT * FROM favorite_photos ORDER BY inputAt DESC")
fun getAllPhotos(): Flow<List<Photo>>
ViewModel에서는 collect를 통해 데이터의 변경을 감지하여 처리합니다.
init {
viewModelScope.launch {
getFavoritePhotoListUseCase.execute().collect { photoList ->
_photos.value = photoList
}
}
}
- 이제는 Room 데이터가 변경될 때마다 collect 블록이 자동으로 실행되며
UI 상태도 즉시 갱신됩니다. - onResume() 없이도 최신 상태를 유지할 수 있어 코드도 간결해졌습니다.
변경 전후 비교
항목 | 기존 방식 (LiveData + 수동 호출) | 개선 방식 (Flow + collect) |
데이터 흐름 | 정적 데이터 (1회 요청) | 실시간 스트림 |
UI 갱신 방식 | onResume()에서 수동 호출 | 자동 감지로 즉시 반영 |
코드 유지보수 | 생명주기에 의존 | 선언적이고 간결 |
사용자 경험 | 변경 사항이 늦게 반영될 수 있음 | 실시간 반영으로 일관된 경험 제공 |
정리하며
개발 초기에는 단순히 StateFlow로만 변경하면 UI가 자동으로 반영될 거라고 생각했지만,
실제로는 Room DAO 레벨에서 Flow를 반환하는 것이 핵심이라는 걸 깨달았습니다.
그 결과, Fragment의 생명주기에 의존하지 않고
Room 데이터 변경 → ViewModel 감지 → UI 반영이라는 흐름이 자연스럽게 연결되었고,
onResume() 없이도 항상 최신 상태의 UI를 유지할 수 있게 되었습니다.
이 과정을 통해,
더 깔끔하고 유지보수가 쉬운 구조로 발전시켜 나가고 있다는 느낌을 받을 수 있었습니다.
Jetpack Compose의 선언형 UI 패러다임과도 잘 어울리는 흐름이었고,
앞으로도 이런 데이터 흐름 설계 방식이 기본이 되어야겠다는 생각이 들었습니다.
'Projects > FineByMe' 카테고리의 다른 글
[Android/Kotlin] Jetpack Compose + Paging3로 무한 스크롤 구현하기 (1) | 2025.05.15 |
---|---|
[Android/Kotlin] Jetpack Compose에서 Flow.debounce()로 검색 요청 최적화하기 (0) | 2025.05.07 |
[Android/Kotlin] BaseViewModel을 걷어내고 원본 비율을 살린 Masonry 레이아웃 개선기 (0) | 2025.04.14 |
[Android/Kotlin] StaggeredGridLayout 사용시 발생한 화면 재구성문제 수정 (2) | 2024.07.29 |
[Android/Kotlin]FineByMe 프로젝트 리팩토링: RecyclerView.Adapter에서 ListAdapter로의 전환 (1) | 2024.07.10 |