Android Architecture Pattern

don9wan·2021년 9월 22일
0

Android

목록 보기
1/18
post-thumbnail
post-custom-banner

아키텍처 패턴, 그게 뭔데

필자는 최근 아무 생각 없이 코드 짜서 유지보수성 포기하기 대회에서 최우수상을 수상하는 영예를 안았다.

취업 준비를 위해 포트폴리오를 준비하고 있었는데, 나도 모르게 앱 크래시가 발생하기 시작했다. git 버전 관리도 제대로 모르고 해왔던 터라 문제 해결이 쉽지 않았다. 포트폴리오는 반포기 상태에 이르렀고, 기본기 공부를 시작하게 되었다. 그러던 중, Android Architecture(Design) Pattern에 대해 알게 되었다.

Architecture(Design) Pattern?
아키텍처 패턴? 구조 패턴 정도로 해석이 되는데, ECB 구조 패턴을 배우던 강의시간에 들었던 용어인 것으로 기억난다.

  • 아키텍처 패턴은 자주 발생하는 문제의 표준적인 해답이다.

반대로 해석하면, 아키텍처 패턴을 적용하지 않고 앱 개발을 하면 문제가 발생했다는 것이다. 꽤나 일리 있는 말이다. 정형화된 구조나 기준 없이 앱 개발을 진행하다 보면, 우리의 코드는

가 돼있을 것이다. 자, 아키텍처 패턴에 대한 키워드를 듣고도 무시하고 코드를 짤텐가? 선택은 우리의 몫이다. Yes라고 하면 필자처럼 될 확률이 높다. 지금까지의 앱 개발자들에게 "어느정도 증명된" 안드로이드 설계구조 방식이라고 생각하면 될 것 같다.

이 해답은 하나가 아니라 여러 개가 존재한다. 그리고 각 아키텍처 패턴마다 장단점도 존재하기에 이를 잘 알고 있어야 당신의 프로젝트에 적절한 아키텍처 패턴을 적용할 수 있다. 널리 알려진 아키텍처 패턴은 MVC, MVP, MVVM이 있다. 한 번 알아보자!

들어가기에 앞서

MV/C/P/VM
앞의 MV가 겹치는데, 이는 우연이 아니다. M은 Model을 의미하고, V는 View를 의미한다. 다만 각 아키텍처 패턴에서 Model과 View의 역할이 조금씩 달라질 수 있다. 기본적으로

  • Model : 데이터, 상태, 비즈니스 로직이다. 프로젝트 내에서 쓰이는 데이터를 저장하고 또는 가공, 처리하는 역할을 한다. View 와 (Controller, Presenter, View Model) 에 의존적이지 않으므로 재사용할 수 있다.
  • View : UI를 의미한다고 생각하면 된다.
  • C, P, VM는 모두 다른 용어이다.

구조적으로 Model, View, 각 아키텍처 패턴의 C, P, VM이 서로 어떻게 상호작용하는지를 중점으로 글을 읽으면 된다.

MVC

간략한 역할 설명

  • Model : 데이터
  • View : 순수 xml
  • Controller : 액티비티

안드로이드 아키텍처를 접해본 적이 없는 이들이라면, MVC와 가장 유사한 형태로 개발을 해왔을 것이다.

MVC
Activity.kt 파일에 앱 동작 코드를 다 써버렸다!

  • Controller
    • 위의 말 그대로이다. 데이터 갱신이나, 뷰 업데이트와 같은 동작들을 액티비티 혼자 감당한다. 코드도 액티비티 파일에 몰려있다. 그래서 문제점이 발생한다.
    • 앱 개발이 계속될 수록 액티비티 파일에 코드량이 비대해진다. 이는 가독성과 유지보수성을 저해하는 큰 이유 중 하나이다.
  • 장점
    • 모델과 뷰가 완벽하게 분리된다.
    • 모델을 쉽게 테스트할 수 있다.
  • 단점
    • 앞서 설명한 것과 같이, 컨트롤러에 코드량이 집중되면서 유지보수에 어려움이 생길 수 있다.
    • MVC 는 View 와 Model 의 결합도가 높다. 대부분의 코드가 View 에서 Model을 직접 호출하여 사용하게 되기 때문이다. 그래서 테스트 코드를 작성하는 경우 UI 위주의 테스트코드를 작성해야 하는데, UI 는 개발중 변화가 자주 있는 곳이기 때문에 일이 매우 복잡해진다.

MVP

간략한 역할 설명

  • Model : 데이터
  • View : xml + 액티비티 + 뷰 인터페이스
  • Presenter : Model과 View를 이어주는 인터페이스

MVC에서 View와 Model의 결합도가 높다는 단점을 보완하기 위해 MVP가 등장했다.

MVP
MVC에서 View와 Model의 의존성을 제거한 디자인 패턴이다.

View 와 Model이 Presenter를 통해서만 동작할 수 있도록 하자!

  • View
    • 액티비티/프래그먼트가 이제 View의 일부로 간주된다. 따라서 뷰와 액티비티가 서로에게 연관되는 현상을 극복할 필요가 없다. View의 일부인 액티비티가 뷰 인터페이스를 구현해서 “프리젠터가 코드를 만들 인터페이스를 갖도록 하는 것”이다.
    • 프리젠터(인터페이스)를 독립적으로 만들어주고, 실제 View에서 해당 프리젠터의 인터페이스를 구현하여 사용한다. 이렇게 하면 프리젠터(인터페이스)를 기반으로 한, 실제 뷰가 아닌 가상 뷰(가상 객체)를 구현해서 간단한 유닛 테스트를 실행할 수 있게 된다.
  • Presenter
    • 본질적으로 MVC의 Controller와 같지만, Presenter는 뷰에 연결되는 것이 아니라 단순한 인터페이스이다.
    • 이를통해 (유닛) 테스트 용이성이 생긴다. 또한 모듈화/유연성 문제도 해결할 수 있다.
    • 다만 한가지 제약사항이 있는데 그 어떤 안드로이드 API 도 참조해선 안된다. 이를 지키지 않는다고 큰 문제가 있지는 않지만 가급적 해당사항을 준수해야 한다.
  • 장점
    • 안드로이드 고유의 뷰와 API에 연결되지 않으므로 뷰 인터페이스를 구현했다면 어떤 뷰와도 작업할 수 있어서 프리젠터 로직을 쉽게 테스트할 수 있다.
  • 단점
    • 프리젠터에 코드량이 집중되면서 유지보수에 어려움이 생길 수 있다.

MVVM

간략한 역할 설명

  • Model : 데이터
  • View : xml + 액티비티
  • ViewModel : Model과 View를 이어주는 인터페이스

MVC에서 View와 Model의 결합도가 높다는 단점을 보완하기 위해 MVP가 등장했다.
MVP에서도 Presenter의 코드량이 비대해질 수 있다는 단점이 있기에 MVVM이 등장했다.

MVVM
안드로이드 데이터 바인딩을 사용하는 디자인 패턴이다.

View는 ViewModel이 들고 있는 데이터를 관찰하여 UI 업데이트한다.
Model은 ViewModel의 요청에 따른 데이터를 가져온다.

  • 사용 전
    • build gradle(:app)에 데이터 바인딩을 위한 코드를 집어넣어 주어야 한다. 이를 통해 뷰는 뷰모델에 의해 모델과 유연한 바인딩이 가능하게 된다.
  • View
    • 액티비티/프래그먼트가 View의 일부로 간주된다.(MVP와 동일)
    • 데이터 바인딩을 위해 XML을 적절히 변경해 주어야 한다.
    • 뷰모델에 의해 보여지는 옵저버블 변수와 액션에 유연하게 바인딩된다.
  • ViewModel
    • 뷰모델은 모델을 래핑하고 뷰에 필요한 옵저버블 데이터를 준비한다.
    • 뷰가 모델에 이벤트를 전달할 수 있도록 훅(hook)을 준비합니다. 그러면서도 뷰모델이 뷰에 종속되지는 않는다.
  • 장점
    • 뷰에 대한 의존성이 전혀 없으므로 유닛 테스트가 더 쉬워진다. MVP에서처럼 테스트를 위해 가상의 뷰를 만들 필요도 없다. 테스트 때 모델이 변경되는 시점에 옵저버블 변수가 제대로 설정됐는지 확인하면 된다.
    • 데이터 변화를 추적하면서 테스트할 수 있다.
    • 또한 ViewModel 과 View 의 종속성이 1 : n 관계이므로 그만큼 코드의 양을 줄일 수 있다고 볼 수 있다.
  • 단점
    • 프로젝트를 수정하거나 새로운 기능을 추가할 때 추가되는 프리젠테이션 로직을 처리하기 위해 XML, ViewModel, BindingAdapter의 코드량이 비대해지면서 유지보수성이 저하될 수 있다.

MVVM 원몰타임

  • View
    • ViewModel 홀드 클래스의 데이터로 UI 갱신
    1. Activity / Fragment 가 View 역할을 함
    2. 사용자의 Action 을 받음 (텍스트 입력, 버튼 터치 등)
    3. ViewModel 의 데이터를 관찰하여 UI 갱신
  • ViewModel
    • 데이터를 가지고 있는다.
    1. View 가 요청한 데이터를 Model 로 요청함
    2. Model 로부터 요청한 데이터를 받음
    3. 화면 변화 시에도 변하지 않는 (사라지지 않는) 데이터를 가지고 있다.
  • Model
    • ViewModel(View)이 필요로 하는 데이터를 반환해준다.
    1. ViewModel 이 요청한 데이터를 반환함
    2. Room, Realm 과 같은 DB 사용이나 Retrofit 을 통한 백엔드 API 호출 (네트워킹) 이 보편적
  • View는 ViewModel 데이터 관찰 및 UI 업데이트

    • 결국 View 가 필요로 하는 데이터는 ViewModel 이 쥐고 있고,
View 는 그것을 필요로 하기 때문에 ViewModel 이 쥐고 있는 데이터를 관찰 (Observing) 한다.
    • 때문에 MVC 패턴과 다르게, View 가 DB 에 직접 접근하는 것이 아닌 UI 업데이트에만 집중한다.
또한 관찰하고 있는 만큼 데이터 변화에 더욱 능동적으로 움직이게 된다.
    • View 가 ViewModel 의 Data 를 관찰하고 있으므로 UI 업데이트가 간편
    • ViewModel 이 데이터를 홀드하고 있으므로 Memory Leak 발생 가능성 배제
      • View 가 직접 Model 에 접근하지 않아 Activity / Fragment 라이프 사이클에 의존하지 않기 때문
    • 기능별 모듈화가 잘 되어 유지 보수에 용이 (e.g. ViewModel 재사용 및 DB 교체 등의 작업이 편리함)
  • AAC

    • MVVM 패턴을 간편하게 적용해볼 수 있게끔 구글에서 AAC 라는 것을 제공한다.
    • AAC는 ViewModel을 쉽게 사용할 수 있도록 해준다.
  • ViewModel은 데이터를 가지고 있음

    • 앞서 설명한대로, 화면 변화 시에도 변하지 않는 (사라지지 않는) 데이터를 가지고 있다.
  • Live Data
    • View 가 ViewModel 을 관찰할 때, 그 관찰 대상이 되는 데이터 홀더 클래스이다.
    • Live Data 는 Activity 및 Fragment 의 Life Cycle 을 인지하지 못하므로, “화면이 활성화 되어 있을 때만 동작하여” 메모리 릭을 줄여준다.
  • Repository
    • ViewModel과 데이터를 주고받기 위해, 데이터 API 를 포함하는 클래스다.
    • 사용자 동작에 따라 필요한 데이터나 외부 백엔드 서버 등에서 데이터를 가져와서 ViewModel로 반환해준다.
    • Repository의 존재 덕분에 ViewModel이 데이터를 관리할 필요가 없게 된다.
  • RoomDatabase
    • Room 은 SQLite 를 사용함에 있어 별도의 Query문 작성없이 간편하게 Insert, Delete 등의 동작을 할 수 있게끔 도와주는 ORM 라이브러리이다.
      • 공식 문서에 따르면 Realm 같은 라이브러리를 사용해도 상관이 없다고 한다.

결론

  • 데이터와 관련된 변수들은 ViewModel에서 LiveData로 관리하고 Observe(관찰)를 통해 xml로 전달 받아 뷰를 업데이트 하고 유저 액션(클릭 이벤트)가 발생 했을땐 ViewModel에서 작성한 함수를 호출하는 방식으로 코드를 구분하고 관리한다.

MVC에 비해 MVP와 MVVM은 앱을 보다 모듈화하고 구성 요소를 단일 용도로 분해한다는 점에서 발전된 모습이지만, 이 구조 때문에 앱이 더 복잡해질 수 있다. 한 두 개의 화면으로만 구성된 간단한 앱이라면 MVC만으로도 충분하다. 한편 데이터 바인딩을 사용하는 MVVM은 보다 반응이 빠른 프로그래밍 모델을 따르고 적은 코드를 사용한다는 점에서 매력적이다.

그렇다면 어떤 패턴이 여러분에게 적합할까? MVP와 MVVM 중 하나를 고른다면 개인 취향에 따른 많은 결정 사항이 있겠지만, 장단점을 파악하기 위해서는 실용적인 관점에서 보는 것이 좋다.

MVVM도 이점을 살리지 못하고 잘 활용하지 못하면 괜히 구조만 복잡한 프로젝트가 될 것이다. 따라서 기능 각각을 어떻게 분류하여 어떤 컴포넌트에 포함해야 제일 효율적일지 생각하는 것이 과제가 될 것이다.

MVVM은 제대로 쓰면 좋지만 엉성하게 쓸꺼면 쓰지말라. 라고 얘기하네요.

AAC 가 있다고 한들, 막상 사용하려니 이론은 이해가 되는데 구현을 어떻게 해야할 지 감이 안 잡힐 수 있다. 예제를 보고 따라해보면서 구현 방식을 이해하고 익숙해지는 과정이 중요하다.

profile
한 눈에 보기 : https://velog.io/@dongwan999/LIST
post-custom-banner

0개의 댓글