Jetpack ViewModel에 대해 알아보자 1

milkbottle·2024년 4월 28일
0

Jetpack ViewModel

전장에서는 안드로이드에서 획기적으로 만든 선언형 UI 프로그래밍 방식인 Jetpack Compose UI에 대해 알아보았다.

이번에는 Jetpack ViewModel에 대해 알아보자.

Jetpack이라는 단어가 중복되는 것을 보니, 기존 안드로이드에서 부족했던 부분을 개선하고 새로운 걸 만드는 큰 프로젝트같은 느낌이 든다.

그 Jetpack 프로젝트의 안에서 ViewModel을 만들고, Compose UI를 만든 것이다.

디자인 패턴에 대해 들어 본 적이 있을 것이다.

MVVM, MVC, MVP... 등 등 말이다.

그중 ViewModel은 MVVM 패턴을 사용한다.

MVVM 패턴? MVC 패턴?

아이디, 패스워드를 입력하고 로그인버튼을 누르면 서버에 전송해서, 200OK 라면 메인 페이지로 넘어가는 화면을 만든다고 해보자.

그렇다면 기존의 Android 코드에서는 어떻게 만들어야할까?

MVC

xml 뷰 형식의 UI라면, activity_login.xmlLinearLayout, EditText, Button 이런 것을 넣어서 구현할 것이다.

그리고 LoginActivity.kt이런 곳에서 idEditText, pwEditText, loginBtn이런 식의 뷰 참조 객체들을 생성하고 바인딩 할 것이다.

대충 코딩하기 귀찮으니 수도코드 같은 느낌으로 작성해보겠다.

	class MainActivity {
    	// 뷰 객체들
    	EditText idEditText;
        EditText pwEditText;
        Button loginBtn;
        
        // Model
        String idState;
        String pwState;
        
        onCreate(Bundle ~) {
        	super.onCreate(~~);
            
            // 뷰 객체 바인딩
            idEditText = (EditText) findViewById(R.id.~~);
            pwEditText ~~
            loginBtn ~~
             
             
            // Controller
            idEditText.값넣으면(
            	저장해(
                	idState = value;
                )
            ) 
            
            // Controller
            pwEditText.값넣으면(
            	저장해(
                	pwState = value;
                )
            ) 
            
            // 이벤트 처리
            loginBtn.클릭했어?(new ~~() {
                  클릭햇을때(
                        // idState, pwState로 로그인 시키는 함수
                        boolean isLogined = login(idState, pwState);
                        if(isLogined) {
                        	gogoMainPage();
                        } else {
                        	Log.d("응 틀렷어");
                        }
                  )
            	}
            )
            
        }
    }

그리고 editText에 값을 입력하면 이를 저장할 수 있는 idState이런 String 형식의 변수를 만들어 이벤트가 발생하면 갱신시킬 것이다.

여기서 Model을 id, password값을 저장하는 곳을 뜻한다.

View는 사람의 눈에 보이는 디자인으로 xml 파일을 뜻한다.

LoginActivity.kt 파일에서 뷰 참조 객체와 바인딩하고 이벤트가 일어나면 Model의 값을 변경 시키는 것을 Controller라고 한다.

기존의 Android UI는 MVC 패턴을 가지고 있다.

MVC의 문제점

하지만 기존의 방식은 치명적인 문제가 있다.

Activity.kt 파일이 관할하는 역할이 너무 커진다.

뷰 객체를 바인딩하고, 모델자체를 멤버변수로 가지고 있으며, 모델을 변경하는 연산도 수행한다.

자기가 뭐 만능인줄아나? 그리고 또 다른 문제가 있다.

바로 화면 회전시 값이 초기화 되는 것이다.

라이프사이클 때문이다.

Android에서는 화면이 회전하면 onPause -> onStop -> onDestroy로 액티비티나 프래그먼트를 지운다.

그리고 onCreate -> onStart ->onResume을 통해 다시 화면을 갱신한다.

그래서 이 과정속에서 기존의 id, password 같은 모델(액티비티의 멤버변수)의 값이 사라지는 것이다.

뭐 savedInstanceState 를 잘 가지고 놀면 살릴 수 있지만, 여기서는 생략한다.

그래서 ViewModel은 이를 해결하기위해 항상 라이프사이클에 관계없이 데이터를 보존할 수 있도록 한다.

액티비티나 프래그먼트 같은 화면에 처음 들어가고나서부터 완전 빠져나올때까지 계속 값이 살아있도록 한다.

MVVM

ViewModel은 기존의 Activity.kt 코드의 역할을 줄이면서 라이프사이클에게 최대한 영향을 받지않도록 만들어졌다.

아까는 Model, Controller이 Activity에 덕지덕지 붙었는데 ViewModel에선 이를 약간이나마 분리할 수 있다.

예시로 코틀린으로 작성된 ViewModel 코드를 살펴보자.

class MainViewModel: ViewModel {
	val id = mutableStateof("")
    val password = mutableStateof("")
    
    fun onIdChanged(inputId: String) {
    	id.value = inputId;
    }
    
    fun onPwChnaged(inputPw: String) {
    	pw.value = inputPw;
    }
}

아까 봤던 Model과 Controller과 비슷한 함수가 안에 들어가있다.

View는 ViewModel안에 있는 정보(id, password)를 구독한다.

위의 사진에서 DataBinding하는 것과 같다.

그리고 View에서 이벤트가 일어나면, onIdChanged, onPwChanged를 호출해서 ViewModel 내부에 존재하는 정보를 갱신한다.

그런데 사실 위코드는 제대로된 MVVM 패턴은 아니다.

왜냐하면 Model에 ViewModel 안에 종속되어 있기 때문이다.

그래서 Repository라는 것을 두어야 한다.

이 내용은 다음 장에서 설명하도록 하겠다.

0개의 댓글