Sam Story

안드로이드 MVVM 패턴 본문

Android

안드로이드 MVVM 패턴

Sam H 2024. 4. 30. 19:15

지난번 포스팅에 이어 오늘은 MVVM 패턴에 대해 포스팅 해보려 한다.

 

디자인 패턴에 관한 내용은 지난번 포스팅에서 다루었었는데

 

디자인 패턴 MVP , MVC 패턴에 대한 이해가 부족하다면 글 최하단의 포스팅을 참고하도록 하자.

 

 

1. MVVM 디자인 패턴이란?

MVVM 패턴은 Model + View + ViewModel 세가지 구성요소의 앞글자를 따온 패턴이다.

 

세가지 구성요소에 대해 간단하게 알아보자.

 

 

1. Model

 

- 데이터와 비즈니스 로직을 주로 관리한다

 

- ViewModel에게 명령을 전달 받고 데이터의 상태를 변경시킨다.

 

- 데이터의 상태가 변경되면 다시 ViewModel에게 알린다.

 

 

2. View

 

- View , Layout 등 화면을 처리하는 곳 (안드로이드의 경우 Activity , Fragment 에 해당)

 

- 사용자 입력을 받고 ViewModel에게 알린다.

 

- ViewModel 에게서 업데이트될 데이터를 직접 전달받지 않고 데이터를 관찰하여 데이터가 갱신될 때마다 업데이트 된다

 

 

3. ViewModel

 

- View와 Model 사이에서 데이터를 전달하는 역할을 한다.

 

- View에 데이터를 전달할 때는 직접적으로 전달하지 않는다.

 

 

간단하게 위 요소들이 어떤 흐름으로 동작하는지 그림을 통해 알아보자.

MVVM 패턴의 흐름

 

간단하게 나타내자면 위 그림처럼 나타낼 수 있다.

 

 

 

2. MVVM 패턴의 특징

- MVP 패턴을 기반으로 생겨났다.

 

- ViewModel은 MVP 패턴의 Presenter와 동일한 역할을 한다

 

- View와 Model 사이의 의존성이 없다.

 

- View와 ViewModel간의 의존성을 줄였다.

 

● LiveData & DataBinding 사용 view에서 ViewModel의 데이터를 관찰하고 

데이터가 갱신될 때마다 업데이트 하는 방식 적용

 

 

 

3. 예제

오늘 준비한 예제도 지난번 MVC , MVP 에서 사용한 예제와 같은 예제이지만

MVVM 패턴으로 코드를 작성하였다.

 

Model

package com.example.designpattern_mvvm_example

import kotlin.random.Random

class Model {

    lateinit var name: String

    // 0 ~ 5 까지의 랜덤한 숫자에 지정된 이름을 뽑는 로직
    fun randomName(): String {

        when(Random.nextInt(6)){

            0 -> name = "Human"
            1 -> name = "Harry"
            2 -> name = "Stella"
            3 -> name = "Hyun"
            4 -> name = "Lion"
            5 -> name = "Jin"

        }

        return name

    }

}

 

Model 클래스의 경우 지난번 다른 패턴들과 동일한걸 알 수 있다.

 

 

ViewModel

package com.example.designpattern_mvvm_example

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class ViewModel {

    // 모델 초기화
    private val model = Model()
    private val _name: MutableLiveData<String> = MutableLiveData()

    // TextView 의 초기값 세팅
    init {

        _name.value = "오늘의 당첨자는?"

    }

    // _name 의 값을 return 해주는 메서드
    fun resultName(): LiveData<String> {

        return _name

    }

    // 모델의 메서드 호출 해서 _name.value 초기화
    fun setName() {

        _name.value = model.randomName()

    }

}

 

ViewModel 의 경우 Presenter의 역할을 해준다고 생각하면된다.

init는 textView의 초기값 설정을 위해 정의해 주었다.

 

 

 

메인 액티비티 레이아웃

<?xml version="1.0" encoding="utf-8"?>

<layout>

    <data>

        <variable
            name="viewModel"
            type="com.example.designpattern_mvvm_example.ViewModel" />

    </data>

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textView"
            android:text="@{viewModel.resultName()}"
            android:gravity="center"
            android:textSize="30sp"
            android:textColor="@color/black"
            android:textStyle="bold"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            />

        <Button
            android:id="@+id/button"
            android:onClick="@{() -> viewModel.setName()}"
            android:layout_margin="40dp"
            android:textSize="20sp"
            android:text="추첨"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

    </LinearLayout>

</layout>

 

레이아웃 xml 파일에서 보면 알겠지만 데이터바인딩을 사용해 각 View들의 값을 설정해 주었다.

 

 

 

메인 액티비티

package com.example.designpattern_mvvm_example

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.example.designpattern_mvvm_example.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding
    lateinit var viewModel: ViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 데이터바인딩 사용
        binding = DataBindingUtil.setContentView(this,R.layout.activity_main)

        // 뷰모델 초기화
        viewModel = ViewModel()

        // lifecycleOwner 지정
        binding.lifecycleOwner = this
        binding.viewModel = viewModel

    }

}

 

다른 디자인 패턴들에 비해 코드가 현저히 줄어든걸 알 수있다.

 

 

 

실행 결과

좌 - 버튼 누르기 전 , 우 - 버튼 누른 후

 

위와 같이 잘 작동하는걸 볼 수있다.

 

 

 

4. MVVM 패턴의 장점과 단점

 

장점

 

- Observer 방식 데이터 통일성 보장

 

- View와 Model 사이의 의존성이 없다.

 

- 각 모듈별로 분리하여 개발할 수 있다.

 

- 모듈화 개발에 적합한 만큼 테스트가 수월하다.

 

단점

 

- 기본적으로 알아야할 개념이 많기 때문에 러닝커브가 높다.

● DataBinding , LiveData 등 AAC에 대한 어느정도의 이해가 필요함

 

- 프로젝트를 구성하는데 다른 패턴에비해 시간이 걸린다.

● 각각의 요소에 맞게 구조를 짜는게 다른패턴들에 비해 복잡함

 

 

 

이렇게 오늘은 MVVM 패턴에 대해 알아보았다.

 

확실히 러닝커브가 있는편이였고 이해하는데 있어서

선행되야 할 지식이나 기술들이 있다고 생각한다.

 

어느정도 이해를 하고나서 보면 굉장히 각각의 역할과

의존성 분리가 참 잘되어 있는 패턴이라고 생각한다.

 

 

MVC 패턴 포스팅

 

 

안드로이드 MVC 패턴

오늘은 안드로이드 디자인 패턴중에 하나인 MVC 패턴에 대해 포스팅 해보려 한다.  디자인 패턴에 관한 내용은 하단 링크에 정리해놓은 포스팅이 있으니기본적인 내용은 생략하도록 하겠다 디

samtistory.tistory.com

 

 

MVP 패턴 포스팅

 

안드로이드 MVP 패턴

오늘은 지난번 포스팅에 이어 안드로이드 디자인 패턴중에 하나인MVP 패턴에 대해 포스팅 해보려 한다. 그 전에 포스팅한 MVC 패턴에 대해 궁금하다면 글 최하단의 포스팅을 참고하도록 하자.  

samtistory.tistory.com

 

 

오늘의 예제 깃허브 주소

 

GitHub - nam-su/MVVMPatternExample

Contribute to nam-su/MVVMPatternExample development by creating an account on GitHub.

github.com

 

'Android' 카테고리의 다른 글

커스텀 다이얼로그 (custom Dialog)  (0) 2024.08.18
핸들러 (Handler)  (0) 2024.05.13
안드로이드 MVP 패턴  (0) 2024.04.29
안드로이드 MVC 패턴  (0) 2024.04.27
안드로이드 ConstraintLayout  (2) 2024.04.25