[Android] ViewModel 공유 vs. 직접 전달

yeonjeen·2025년 6월 8일
0

Android

목록 보기
10/10

프로젝트를 진행하며 데이터를 주고 받아야 하는 상황에서 두 가지 고민을 한 경험이 있다.

  • ViewModel을 공유할 것인가?

  • 명시적으로 상태를 전달할 것인가?

이 두 가지 사이에서 고민을 했었고 어떤 상황에 어떤 방법이 조금 더 적절한지 그 기준을 정리해보자!🌟


1️⃣ ViewModel 공유란?

  • 하나의 Activity 범위에서 ViewModel을 여러 Fragment에서 함께 사용하는 방식
    ➡️ activityViewModels()를 통해 구현

✅ 예시 코드

@AndroidEntryPoint
class MyActivityFragment : Fragment() {

    private val myPageViewModel: MyPageViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        myPageViewModel.userProfile.observe(viewLifecycleOwner) { userProfile ->
            // UI 업데이트
            binding.nickname.text = userProfile.nickname
            binding.avatar.load(userProfile.avatarUrl)
        }
    }
}

📌 장점

  • 동일 액티비티 내 여러 프래그먼트가 동일 상태를 관찰할 수 있다.
  • UI 상태가 자동으로 동기화되므로 추가 전달 로직 없이 간결하다.

⚠️ 주의점

  • 의존성이 커질 수 있음
    → ViewModel이 여러 프래그먼트의 요구를 모두 책임지게 되기 때문.

  • 생명주기 충돌
    → View가 아직 생성되지 않았을 때 observe할 경우 예외 발생 가능성 있음.

2️⃣ 상태 전달이란?

  • 상태 전달은 특정 데이터를 명시적으로 전달하는 방식
  • Navigation Component or public method 등을 통해 수동으로 데이터 전달

✅ 예시 코드

class MyActivityFragment : Fragment() {

    private var userProfile: UserProfileModel? = null

    fun setUserProfile(userProfile: UserProfileModel) {
        this.userProfile = userProfile
        // 강제로 어댑터 갱신
        adapter.setUserProfile(userProfile)
        adapter.submitList(adapter.currentList)
    }
}
// MyPageFragment에서 설정
myActivityFragment.setUserProfile(userProfile)

📌 장점

  • 데이터 흐름이 명확하다. “어디서 → 어디로 → 왜 전달했는지” 추적 가능
  • 프래그먼트 간 독립성이 유지된다

⚠️ 주의점

  • 실시간 반영 어려움
    → ViewModel처럼 observe하는 방식이 아니기 때문에 값이 바뀌어도 UI에 자동 반영되지 않음

  • Fragment가 재생성되면 값이 초기화될 수 있음

3️⃣ 실제 사례: MyPageFragment ↔ MyActivityFragment

🎯 목적

  • MyActivityFragment는 ViewPager의 탭 중 하나이며 유저의 게시물을 보여줌

  • 게시물에는 유저의 nickname과 avatar를 보여줘함

  • 하지만 서버에서는 개별 게시물마다 이 정보를 X

MyPageFragment에서 가져온 유저 정보를 MyActivityFragment로 공유 or 전달

⛔️ 초반 구현 방식: 상태 전달

// MyPageFragment에서
myActivityFragment.setUserProfile(userProfile)
// MyActivityFragment
fun setUserProfile(userProfile: UserProfileModel) {
    this.userProfile = userProfile
    adapter.setUserProfile(userProfile)
    adapter.submitList(adapter.currentList)
}
  • setUserProfile()은 외부에서 호출되며 어댑터에 프로필 정보를 적용

🔥 문제

  • Fragment가 이미 생성되어 있을 때는 잘 반영되지만 ViewPager에서 캐시된 상태거나 생명주기 타이밍이 엇갈릴 경우 반영되지 않는 문제 발생

✅ 개선 방식: ViewModel 공유

// MyActivityFragment
private val myPageViewModel: MyPageViewModel by activityViewModels()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    myPageViewModel.userProfile.observe(viewLifecycleOwner) { userProfile ->
        adapter.setUserProfile(userProfile)
        adapter.submitList(adapter.currentList)
    }
}
// MyPageViewModel
private val _userProfile = MutableLiveData<UserProfileModel>()
val userProfile: LiveData<UserProfileModel> = _userProfile

fun updateUserProfile(profile: UserProfileModel) {
    _userProfile.value = profile
}
  • MyPageFragment에서 profile을 받아오면 ViewModel에 저장

  • MyActivityFragment는 observe만 하고 있어도 알아서 반영됨

4️⃣ 선택 기준 요약

상황ViewModel 공유상태 전달
동일 액티비티 내 탭(Fragment) 간 데이터 공유✔️ 적합❌ 반복 로직 발생
UI가 실시간으로 업데이트되어야 함✔️ observe 가능❌ 수동 갱신 필요
데이터가 초기 진입 시 한 번만 필요함❌ 과도함✔️ 명시적 전달이 간단
프래그먼트가 recreate 될 수 있음✔️ 안전하게 재반영됨❌ 값 유지 어려움
의존성 최소화가 중요함❌ 공유 범위 넓음✔️ 분리 가능

ViewModel 공유는 자동 반영, UI 일관성 유지에 탁월한 방식이지만
범위가 넓어질수록 관리가 어렵습니다.
반면 상태 전달은 간결하고 명확하지만 반응형 UI에는 맞지 않습니다.

👉 내가 관리해야 하는 상태가 “지속적이고 반응형”인지 아니면 “초기 진입 시 한 번”인지에 따라 기준을 세워 판단해야 합니다!

0개의 댓글