App Architecture MVVM

이창민·2022년 2월 3일
0

모바일 앱 사용자 환경

휴대 기기는 리소스가 제한된다 -> 하나의 기기에서 여러 앱을 실행하는 환경을 고려해 개발을 해야함
앱이 너무 많은 자원을 사용할 때 시스템은 이를 제한할 수 있음 -> 갑자기 앱이 종료되는 경험, 너무 큰 사이즈의 데이터를 변수에 저장하지 않고 UI를 유지할 수 있어야함

일반 아키텍처 원칙

Activity나 Fragment에 모든 코드를 작성하지 않아야함
즉 Adapter나 네트워크 통신 등 모든 코드를 Activity나 Fragment 하나의 클래스에 정의하지 않고 class를 분리하여 작성

권장 앱 아키텍처

UI layer

  1. ui elements - 화면에 데이터 렌더링하는 UI 요소(xml 파일 추가되는 view, jetpack compose)
  2. state holders - 데이터를 보유하고 UI에 노출해 로직 처리하는 상태 홀더(viewmodel)

data layer

각 데이터 소스(네트워크 통신을 통해 얻은 최신 데이터, 로컬 DB에 저장된 최근 데이터, json 파일 같은 것들)는 각 데이터 소스 클래스에서 관리하는 것이 좋은데 어떤 데이터 소스를 보여주는 것이 좋을 지 결정할 레포지토리 클래스 로 이뤄짐

domain layer

여러 viewmodel에서 재사용되는 간단한 비지니스 로직의 캡슐화를 담당
만약 여러 viewmodel에서 시간대를 사용해 화면에 적절한 메시지를 표시하는 경우 앱에는 GetTimeZoneUseCase 클래스가 존재할 수 있음
각각의 뷰모델에서 GetTimeZoneUseCase 클래스를 참조해 데이터를 변경해 UI elements가 이를 사용하게 됨

MVVM

mvvm 패턴은 권장 앱 아키텍처과 같이 비즈니스 로직과 프레젠테이션 로직을 UI로부터 분리하는 것이 목표이다. 비즈니스 로직과 프레젠테이션 로직을 UI로부터 분리하면 테스트, 유지 보수, 재사용이 쉬워진다.
MVVM 패턴은 아래 3가지 구성요소로 구성된다.

  • model
  • view
  • viewmodel

    뷰는 뷰모델을 알고 뷰모델은 모델을 안다.
    하지만, 뷰모델은 뷰를 모르고 모델은 뷰모델을 모른다.
    LiveData을 통해 변경을 알 수 있다.

위 구조를 통해 viewmodel과 model이 view로 부터 독립적인 형태를 만들어 UI로 부터 비즈니스 로직과 프레젠테이션 로직을 분리할 수 있다.

ViewModel


위 사진은 ViewModel의 수명주기와 activity의 수명주기를 비교한 사진이다.
왼쪽은 activity의 lifecycle, 오른쪽은 viewmodel의 lifecycle이다.
activity는 여러 단계인 반면 viewmodel은 하나의 onCleared callback밖에 없다.
activity의 상태가 계속 변화하는 반면 viewmodel은 계속 같은 상태를 유지함.
이런 이유로 viewmodel을 권장 앱 아키텍처의 state holders의 역할로 사용할 수 있음
ViewModel에서 데이터를 관리할 때 LiveData를 사용함.

일반적으로 뷰모델과 모델은 일대다 관계
뷰모델은 서로 다른 두 모델의 데이터를 활용한 데이터가 필요하다면 뷰에서 모델의 값을 조작하는 것이 아닌 뷰모델에서 두 모델의 데이터를 가공해 뷰는 UI만 다루도록 한다.

class MyViewModel : ViewModel() {
    private val users: MutableLiveData<List<User>> by lazy {
        MutableLiveData<List<User>>().also {
            loadUsers()
        }
    }

    fun getUsers(): LiveData<List<User>> {
        return users
    }

    private fun loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

class MyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.

        // Use the 'by viewModels()' Kotlin property delegate
        // from the activity-ktx artifact
        val model: MyViewModel by viewModels()
        model.getUsers().observe(this, Observer<List<User>>{ users ->
            // update UI
        })
    }
}

Activity나 Fragment에서는 위와 같이 by viewModels()을 사용해 myViewModel 객체를 생성한다.

LiveData


안드로이드 공식 홈페이지에는 위와 같이 사용하라고 나타난다.
1번 내용은 위 코드에서 MyViewModel의 user 변수에 해당한다.
2번 내용을 확인하면 활동(액티비티)이나 프래그먼트 같은 UI 컨트롤러에 Observer 객체를 만들라고 표기됨
3번 내용을 확인하면 위 코드의 액티비티에 확인해보면 model.getUsers().observe(LifecycleOwner객체, Observer객체) 이다.
activity와 fragment는 LifecycleOwner에 대한 참조를 얻을 수 있음
위 단계를 따른 후, LiveData가 변경 후에 Observer 객체의 구현체가 호출될 것이므로 view를 업데이트 할 수 있음

View

UI에 관련된 것을 다룸
스크린을 통해 보는 것들에 대한 구조, 레이아웃, 형태를 정의
애니메이션 같은 UI 로직을 포함하되 비즈니스 로직 포함x

Model

데이터와 데이터에 관련된 행위를 모두 합쳐 model이라 부름

참고자료

https://developer.android.com/jetpack/guide
https://developer.android.com/topic/libraries/architecture/viewmodel
https://developer.android.com/topic/libraries/architecture/livedata#work_livedata
https://velog.io/@k7120792/Model-View-ViewModel-Pattern#%EA%B5%AC%EC%84%B1-%EC%9A%94%EC%86%8C

profile
android 를 공부해보아요

0개의 댓글