본문 바로가기
Projects/FineByMe

[Android/Kotlin] Room + Flow 조합으로 즐겨찾기 화면 자동 갱신하기

by quessr 2025. 4. 24.

 

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 패러다임과도 잘 어울리는 흐름이었고,
앞으로도 이런 데이터 흐름 설계 방식이 기본이 되어야겠다는 생각이 들었습니다.

 

반응형