본문 바로가기

[TIL][내일배움캠프]

[내일배움캠프][TIL] 24.02.02 (금) - MVVM

1. MVVM

 

어제를 끝으로 앱개발 심화 개인과제의 필수 과제들은 전부 구현하였다.

하지만, 아직 선택 과제 부분이 남아있고, 그 선택 과제 부분에서 가장 중요한 개념이 바로 MVVM이다.

 

그렇다면, MVVM은 과연 무엇인가?

 

 

MVVM (Model - View - ViewModel)

 

MVVM은 Model, View, ViewModel이 서로 유기적으로 연결되어 있는 형태를 말한다.

  • Model:
    • 데이터와 비즈니스 로직을 처리
    • 데이터베이스, 네트워크 서비스, 기타 비즈니스 로직이 해당
  • View
    • 사용자 인터페이스(UI)
    • 사용자에게 정보를 표시하고 사용자의 입력을 받는 것
  • ViewModel
    • View와 Model 사이의 매개체 역할 (Data의 메신저)
    • View에 데이터를 전달하고, View로부터의 입력을 처리

 

○ MVVM의 장점

  • 모듈성 및 유지 보수성: View와 Model 사이의 의존성이 낮아져 코드의 재사용성과 유지 보수가 편해짐
  • 테스트 용이성: ViewModel은 UI로부터 분리되어 있어 비즈니스 로직의 테스트가 용이
  • 반응형 UI: ViewModel을 통해 View와 Model 간의 데이터 바인딩을 구현함으로써, UI가 데이터의 변경에 자동으로 반응

○ 생명주기

  • 액티비티나 프래그먼트가 구성 변경(예: 화면 회전) 또는 재생성되는 동안에도 데이터와 상태를 유지
  • 액티비티나 프래그먼트의 구성 변경으로 인한 데이터 손실을 방지
  • 데이터 관리 및 UI 상태 유지를 더욱 효율적으로 할 수 있음
  • **ViewModel**의 onCleared() 메서드가 소멸시점에 호출되어 리소스 정리 및 해제 작업을 수행

 

○ ViewModel 만들기

class HomeViewModel(repository: YoutubeRepository) : ViewModel() {

 

우선은 ViewModel 클래스를 만든다.

 

//Activity에서 사용될 때
class MyActivity : AppCompatActivity() {
    private val viewModel: HomeViewModel by viewModels()

//Fragment에서 Activity의 viewModel을 공유 받고 싶을때
class MyFragment : Fragment() {
    private val viewModel: HomeViewModel by activityViewModels()

//Fragment 자신만의 viewModel을 사용할 때
class HomeViewModel: Fragment() {
    private val viewModel: HomeViewModel by viewModels()

그리고 그것을 Activity와 Fragment에 각각 연결 시킨다.

 

※ 주의사항

Context나 View 단위를 ViewModel에 넘겨서는 안 됨.

 

 

LiveData

 

  • 데이터 변경을 관찰할 수 있는 데이터 홀더 클래스
  • LiveData는 생명주기를 인식
  • 액티비티, 프래그먼트 생명주기 상태에 따라 자동으로 업데이트 됨
  • Observer 패턴을 사용하기 때문에, 데이터의 변화를 실시간으로 전달 가능
  • 장점
    • UI와 데이터 상태 동기화: LiveData를 사용하면 UI 컴포넌끼리 데이터 상태를 쉽게 동기화할 수 있음
    • 생명주기 인식: LiveData는 관찰자에게만 활성 상태일 때 데이터 변경을 알림
    • 메모리 누수 방지: LiveData는 관찰자의 생명 주기를 인식하므로, 관찰자가 활성 상태가 아닐 때는 이벤트를 보내지 않음
  • MutableLiveData vs LiveData
    • **Mut**ableLiveData 는 GET / SET 이 모두 가능하며, LiveData 는 GET 만 가능
  • setValue vs postValue
    • setValue() : MainThread가 보장될 경우 활용 (MainThread 에서의 값 업데이트)
    • postValue() : MainThread 가 아닌 IO 스케줄러 활용 시 활용 (MainThread 로 값 전달)

 

○ LiveData 사용법

private val _trendingVideos = MutableLiveData<List<Item>>()
val trendingVideos: LiveData<List<ListItem.VideoItem>> = _trendingVideos.switchMap {
    MutableLiveData(it.toVideoItem())
}

fun fetchTrendingVideos(region: String = "US") {
        viewModelScope.launch {
            runCatching {
                val videos = repository.getTrendingVideos(region)//3초
                _trendingVideos.value = videos
            }.onFailure {
                Log.e(TAG, "fetchTrendingVideos() failed! : ${it.message}")
                handleException(it)
            }
        }
}
viewModel.trendingVideos.observe(viewLifecycleOwner) {
    adapter.submitList(it)
}

 

LiveData를 설정한 뒤에는 observe를 넣어야 한다.

 

 

하지만, 이렇게만 봐서는 도무지 MVVM을 완벽하게 이해할 수 없다.

그렇기 때문에 다음 시간에는 선택 과제를 통해서 MVVM을 어떻게 사용해야하는지 한 번 알아보겠다.