⚠️ 이 글은 MVC 패턴에 대한 이해도가 있다면 더욱 읽기 수월합니다
Android 앱 개발을 하다보면, Activity 클래스에 모든 앱 동작 코드를 다 집어넣는 경우가 많았다.
물론 동작에 있어 큰 문제는 없지만 체계적인 구조가 전혀 없어 추후에 유지 보수가 어렵다.
실제로 몇몇 프로젝트를 진행함에 있어 이러한 방식으로 앱을 개발하다 보면,
기능을 바꾸거나 추가할 때 어떤 부분을 수정해야 할지 머리가 아득해졌던 경험이 있다.
문득 여태 짠 지저분한 코드들을 보면서 이러한 생각이 자연스레 들었다.
'아무래도 MVVM 디자인 패턴 공부를 하고, 적용을 해봐야겠다'
Activity 에 모든 동작을 때려넣다보면 점점 스파게티가 완성된다..
그래도 다행이라면 다행인게, MVVM 패턴에 따른 앱 개발이 대세인만큼 구글에서도 이를 도와주는 듯 Android Jetpack 의 구성요소로써 AAC(Android Architecture Component) 라는 것을 제공하고 있다.
(물론 AAC 가 있다고 MVVM 을 쉽게 정복할 수 있으리라는 자신감은 접어두는 것이 좋은 것 같다.)
따라서 필자가 여러 자료를 찾아보면서 익힌 MVVM 패턴과 AAC 에 대해서 소개하고자 한다.
기존 성행했던 단순한 형태의 MVC 패턴에 따라 Activity 에 모든 코드를 다 집어넣으면 이런 단점들이 발생했다.
단점들을 봤을 때, MVC 패턴은 규모가 커질수록 공통적으로 유지보수가 어려워진다는 단점이 존재한다.
왜냐하면 MVC 패턴의 동작이 아래와 같기 때문이다.
- Controller 가 사용자 동작을 받아들임 (텍스트 입력, 버튼 터치 등)
- Controller 가 사용자의 동작에 따른 Model 업데이트를 요청함
- Controller 가 Model 을 나타낼 View 를 선택함
- View 는 Model 을 참조하여 UI 를 업데이트함
자연스레 View 와 Model 간의 의존성이 높아질 수 밖에 없다.
또한 Controller (Activity) 가 Model 과 View 사이에서 바쁘게 움직이고 있다.
혼자서 여기저기 요청을 보내야 하고 가운데에 껴서 고생하는 Controller 는 당연히 동작이 무거워진다.
따라서 코드 유지보수를 하다가 까딱했다간 UI 프레임 스킵 현상 및 메모리 릭 (Memory Leak)의 위험에 빠질지도 모른다.
한마디로 MVC 패턴은 구현하기 쉬운 장점이 있는 반면, 기능 추가 및 변경에 있어 유지보수가 어렵다.
Controller 는 '나 혼자 떠맡아야 한다는 사실'을 알게 되었다.
이러한 MVC 패턴의 단점을 보완하고자 (Controller 를 살려주고자) 등장한 디자인 패턴이 바로 MVVM 이다.
MVVM 은 기존 MVC 에서 Controller 에게 막중한 역할을 부여하기보다, 이 동작 자체를 분리하여
동작의 흐름을 더욱 체계적으로 만들어주고 유지보수를 편리하게 할 수 있도록 해주는 디자인 패턴이다.
MVVM 은 Model, View, ViewModel 로 이루어져 아래와 같은 동작을 한다.
View
- Activity / Fragment 가 View 역할을 함
- 사용자의 Action 을 받음 (텍스트 입력, 버튼 터치 등)
- ViewModel 의 데이터를 관찰하여 UI 갱신
ViewModel
- View 가 요청한 데이터를 Model 로 요청함
- Model 로부터 요청한 데이터를 받음
Model
- ViewModel 이 요청한 데이터를 반환함
- Room, Realm 과 같은 DB 사용이나 Retrofit 을 통한 백엔드 API 호출 (네트워킹) 이 보편적
결국 View 가 필요로 하는 데이터는 ViewModel 이 쥐고 있고,
View 는 그것을 필요로 하기 때문에 ViewModel 이 쥐고 있는 데이터를 관찰 (Observing) 한다.
때문에 MVC 패턴과 다르게, View 가 DB 에 직접 접근하는 것이 아닌 UI 업데이트에만 집중한다.
또한 관찰하고 있는 만큼 데이터 변화에 더욱 능동적으로 움직이게 된다.
따라서 MVVM 패턴은 다음과 같은 장점을 가진다.
이러한 장점을 가지고 있는 MVVM 패턴은 잘만 사용한다면 훌륭한 앱을 만들 수 있다.
그렇지만 그만큼 구조가 복잡하다는 단점이 크게 다가온다. 진입장벽이 상당하다.
그래도 MVVM 패턴을 간편하게 적용해볼 수 있게끔 구글에서 AAC 라는 것을 제공한다.
지금까지 알아봤던 MVVM 의 구성 요소를 Android Jetpack 의 구성요소 AAC 와 함께 구현한다고 해보자.
하나씩 아래 그림에 나와있는 구성 요소를 살펴보자.
앞서 설명한대로, 화면 변화 시에도 변하지 않는 (사라지지 않는) 데이터를 가지고 있다.
View 가 ViewModel 을 관찰할 때, 그 관찰 대상이 되는 데이터 홀더 클래스이다. Live Data 는 Activity 및 Fragment 의 Life Cycle 을 인지하지 못하므로, 화면이 활성화 되어 있을 때만 동작하여 메모리 릭을 줄여준다.
ViewModel 과 데이터를 주고받기 위해, 데이터 API 를 포함하는 클래스다. 사용자 동작에 따라 필요한 데이터나 외부 백엔드 서버 등에서 데이터를 가져오게 된다. Repository 의 존재 덕분에 ViewModel 이 데이터를 관리할 필요가 없게 된다.
Room 은 SQLite 를 사용함에 있어 별도의 Query문 작성없이 간편하게 Insert, Delete 등의 동작을 할 수 있게끔 도와주는 ORM 라이브러리이다. (공식 문서에 따르면 Realm 같은 친구를 사용해도 상관이 없다고 한다. 필자는 체감상 Realm 이 더 간결하고 깔끔하다는 생각이다.)
처음엔 "불행인건지.. 차라리 다행인건지.." 싶을 수 있다.
AAC 에서 이러한 구성 요소들을 기본적으로 제공해주기 때문에, 손쉽(지 않)게 MVVM 패턴을 익히고 사용할 수 있다.
물론, MVVM 도 이점을 살리지 못하고 잘 활용하지 못하면 괜히 구조만 복잡한 프로젝트가 될 것이다.
따라서 기능 각각을 어떻게 분류하여 어떤 컴포넌트에 포함해야 제일 효율적일지 생각하는 것이 과제가 될 것이다.
또한, 자기가 개발하고자 하는 앱에 가장 알맞는 디자인 패턴이 무엇인지 생각해볼 필요도 있다.
간단한 아이디어에서 착안된, 간단한 동작을 하는 앱이라면 굳이 MVVM 을 사용할 필요가 없으니까 말이다.
이렇듯, MVVM 패턴이 좋은 건 알겠는데 어떻게 접목해야 할지도 잘 모르겠고 따져야할 것이 많은 것이 사실이다.
AAC 가 있다고 한들, 막상 사용하려니 이론은 이해가 되는데 구현을 어떻게 해야할 지 감이 안 잡힐 수 있다.
예제를 보고 따라해보면서 구현 방식을 이해하고 익숙해지는 과정이 필요할 것 같다.
필자도 MVVM 패턴을 유심히 익혀보며 앞으로 프로젝트에 적용하여 유지보수가 용이한 개발을 해볼 예정이다.
(사실 이미 해보고 있는데, 상당히 프로젝트 구조가 깔끔해졌다는 느낌이 절로 든다. 신세계다.)
만약 아직 MVVM 패턴을 사용하여 앱 개발을 해본적이 없다면, 꼭 한 번 시도해보는 것을 추천한다.
기회가 되면 AAC 를 활용한 MVVM 패턴의 앱 만들어보기 예제 포스팅을 올려보겠다.
아래에 본문 이해에 도움이 될 수 있는 영상을 첨부한다.
안녕하세요 해로님, 좋은 글 정말 잘 봤습니다. 덕분에 MVVM 패턴에 좀 더 익숙해진 것 같아요. 그런데 글을 읽고 몇 가지 궁금한 점이 생겼는데, 질문 드려도 될까요?
이 부분이 무슨 말씀인지 이해가 잘 안 가는데,, View가 모델을 직접 참조하면 왜 memory leak이 발생하는 건가요?
LiveData가 LifeCycle을 인지해서 화면이 활성화되어 있을 때만 동작한다고 이해하고 있었는데, 제가 잘못 알고 있었던 걸까요?
감사합니다.
와~ 정리가 너무 잘되어있네요 ^^