MVC 패턴은 모델(Model), 뷰(View), 컨트롤러(Controller)로 이루어진 디자인 패턴입니다.
모델은 애플리케이션의 데이터인 데이터베이스, 상수, 변수 등을 뜻합니다.
모델은 아래와 같은 규칙들을 가지고 있습니다.
1. 사용자가 편집하길 원하는 데이터를 가지고 있어야한다.
2. 뷰나 컨트롤러에 대해서 어떠한 정보도 알 수 없어야한다.
3. 변화가 있을 때, 변화에 대한 처리방법을 구현해야한다.
Model - 백그라운드에서 동작하는 비지니스 로직 처리
뷰는 TextView, EditText, Checkbox 등 사용자 인터페이스 요소를 나타냅니다. 즉, 모델을 기반으로 사용자가 볼 수 있는 화면을 뜻합니다.
뷰는 아래와 같은 규칙들을 가지고 있습니다.
1. 모델이 가지고 있는 정보를 따로 저장해서는 안된다.
2. 모델이나 컨트롤러와 같이 다른 구성요소들을 알면 안된다.
3. 변화가 있을 때, 변화에 대한 처리방법을 구현 해야한다.
정보를 화면으로 보여주는 역할
컨트롤러는 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리 역할을 하며 이벤트 등 메인 로직을 담당합니다. 또한, 모델과 뷰의 생명주기도 관리하며, 모델이나 뷰의 변경 통지를 받으면 이를 해석하여 각각의 구성 요소에 해당 내용에 대해 알려줍니다.
컨트롤러는 아래와 같은 규칙들을 가지고 있습니다.
1. 뷰와 모델에 대한 정보를 갖고 있다.
2. 뷰나 모델의 변경을 모니터링 해야한다.
사용자의 입력 처리와 흐름 제어 담당
, 화면과 Model과 View를 연결시켜 주는 역할
😊이제까지 모델(Model), 뷰(View), 컨트롤러(Controller)의 특성에 대해서 알아보았습니다.
KeyPoint : 재사용성
, 확장성
View
는 Controller
에 연결되어 화면을 구성하는 단위 요소이므로 다수의 View를 가질 수 있습니다.
Model
은 Controller
를 통해 View
와 연결되지만, Controller
에 의해서 하나의 View
에 연결될 수 있는 Model
로 여러 개가 될 수 있어 View와 Model이 서로 의존성을 띄게 됩니다.
즉, 애플리케이션이 복잡해질수록 모델과 뷰 관계가 복잡해지는 단점이 있습니다.
KeyPoint : 관계의 복잡성 증가
MVP 패턴은 MVC 패턴으로부터 파생되었으며 MVC에서 C에 해당하는 컨트롤러가 프레젠터(Presenter)로 교체된 패턴입니다.
Presenter는 MVC의 Controller와 매우 유사하지만, 다른 점이 있다면 View에 남아 있는 모든 비지니스 로직을 전부 Presenter로 통합하는데 차이점이 있습니다.
MVC 패턴 View
: Controller
= N : 1
MVP 패턴 View
: Controller
= 1 : 1
뷰와 프레젠터는 1:1 관계이기 때문에 MVC 패턴보다 더 강한 결합을 지닌 디자인 패턴입니다.
MVVM 패턴은 MVC에 C에 해당하는 컨트롤러가 뷰모델(ViewModel)로 바뀐 패턴입니다.
이 패턴의 목표는 비지니스 로직과 프레젠테이션 로직을 UI로부터 분리하는 것입니다.
두 로직을 UI로부터 분리하게 되면, 테스트, 유지보수, 재사용성이 쉬워집니다.
하나의 소프트웨어를 최대한 기능적으로 작은 단위로 분할해 테스트가 쉽고 큰 프로젝트를 상대적으로 관리하기 쉬운 도구입니다.
모든 입력은 View로 전달되며, ViewModel은 입력에 해당하는 로직을 처리하여 View에 데이터를 전달합니다.
ViewModel
은 View
를 따로 참조하지 않기 때문에 독립적이며 ViewModel
: View
=1 : N 관계입니다.
ViewModel
의 역할 : UI 관련 데이터를 저장하고 관리해주는 역할을 합니다.
안드로이드에서 화면이 회전할 때 Activity는 onDestroy()가 불려 View가 메모리에서 떨어졌다가 다시 onCreate()가 불리면서 다시 할당됩니다. 그래서 View를 통해 보여줄 데이터를 유지할 수 가 없습니다. 아래의 그림에서 생명주기를 확인해보면,
activity가 rotated가 되어도 viewModel이 onCleared()가 불리지 않아 소멸하지 않는 것을 확인할 수 있습니다. 그러므로 ViewModel를 통해 UI 관련 데이터를 안전하게 가지고 있을 수 있습니다.
activity_main
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.market.mvvmpatternexample.MainViewModel" />
<variable
name="mainViewModel"
type="MainViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{Integer.toString(mainViewModel.count)}"
android:textSize="50sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:backgroundTint="#03A9F4"
android:onClick="@{() -> mainViewModel.onClickButton()}"
android:text="클릭!"
android:textSize="13sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/count" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MainViewModel
package com.market.mvvmpatternexample
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class MainViewModel : ViewModel() {
private var _count = MutableLiveData<Int>()
val count: LiveData<Int> get() = _count
init {
_count.value = 0
}
fun onClickButton() {
Log.d("ViewModel", "$count")
_count.value = count.value?.plus(1)
}
}
MainActivity
package com.market.mvvmpatternexample
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.market.mvvmpatternexample.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val mainViewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.lifecycleOwner = this
binding.mainViewModel = mainViewModel
}
}
UI요소와 데이터를 프로그램적 방식으로 연결하지 않고, 선언적 형식으로 결합할 수 있게 도와주는 라이브러리를 말합니다. 즉, UI와 로직을 분리하기 위한 라이브러리
(컴퓨터 프로그래밍)
제공자와 소비자로부터 데이터 소스를 함께 묶어 동기화하는 일반적인 기법. XML 데이터 바인딩과 UI 데이터 바인딩에서와 같이 서로 다른 언어를 사용하는 두 개의 데이터/정보 소스로 이루어집니다. UI 데이터 바인딩에서는 언어와 다른 로직 함수의 데이터 및 정보 객체가 서로 결합됩니다.