on
안드로이드 대표적인 패턴 정리
지난 겨울학기, 본인은 학교 수업을 통해 <클린 코드(Clean code, 로버트 마틴 저)>를 접했다. 개발 시 테스트와 코드를 깔끔하게 짜는 것에 대한 중요성은 느끼고 있었지만, 아무래도 본인의 코드는 그것과 영 거리가 멀었다. 테스트 코드는 당연히 없었고 심지어 클래스 분리도 거의 하지 않았(!!)다. 지금이야 ‘한 클래스, 한 메소드는 하나의 기능만 가져야 한다.’는 생각과 Step down rule 등의 원칙을 준수하며 코드를 작성하지만 여전히 부족한 점이 많다.
코드를 예쁘게 짜기 위해 지켜야 할 여러가지가 있지만, 그 중 오늘 다루려 하는 주제는 안드로이드의 세 가지 패턴인 MVC, MVP, MVVM 이다. 스타트업에 안드로이드 개발자 포지션으로 면접을 보러 가면 백에 백은 이에 대한 질문을 했다. 이렇게나 필수적인 지식인만큼 간단한 정리와 적용을 해볼 필요성이 있다고 생각한다.하지만 어렵지 않다고는 안했다... 어려움...
안드로이드에서 왜 아키텍처 패턴을 사용해야 하는가?
앞서 말했듯 코드를 예쁘게 짜기 위함과 동시에 유닛 테스트를 위해서이다. 전자의 경우는 훌륭한 안드로이드 개발자분들께서 이미 입증하셨으니 후자의 이야기를 해보자. 안드로이드를 개발해봤다면 초반엔 통(!)으로 코드를 짜본 경험이 있을 것이고, 그 당시에 테스트 코드를 작성해봤거나 작성하려고 노력했다면… 안드로이드에서 유닛 테스트 코드를 짜는게 쉽지 않다는 걸 알고 있을 것이다.
코드 사이의 종속성이 높기 때문이다. 가령 액티비티에 있는 메소드를 테스트 하려면 테스트 코드에 해당 클래스를 끌어와야 한다. 하지만 그러기도 어려울 뿐더러, 그런 메소드는 대부분 리턴 값이 없기 때문에 테스트를 하는 게 거의 불가능하다. 유닛 테스트를 하긴 힘겨운데 그렇다고 테스트를 아예 버릴 수는 없다. 그렇다면 어떻게 해야할까? 답은 ‘분리’가 되겠다.
본론에 들어가기에 앞서 글을 쓰는 데에 도움을 받은 글 목록의 주소를 첨부한다.
1. MVC(Model View Controller)
안드로이드 아키텍처 패턴의 최초라고 할 수 있는 MVC는 웹의 패턴을 차용한 것으로, 앱을 인터페이스를 분리하기 위한 패턴이다.
-
- Model
- 모델은 데이터를 관리하는 부분이다. 주로 데이터베이스 관리와 비즈니스 로직을 담당한다. 뷰나 컨트롤러에 종속되지 않기 때문에 독립적이다.
-
- View
- 컨트롤러를 통해 모델에서 오는 데이터를 화면에 출력하는 역할을 한다. 그 외에 다른 역할은 하지 않으며, 사용자로부터 받은 입력을 처리하는 등의 일은 컨트롤러가 담당한다. 본인이 이해한 대로 쉽게 말하자면 XML의 집합이라고 할 수 있다.
-
- Controller
- 컨트롤러는 모델과 뷰를 매개하는 역할을 담당한다. 사용자가 뷰를 통해 발생시킨 이벤트를 모델과 적절하게 상호작용하고, 모델의 데이터가 갱신됨에 따라 뷰를 업데이트 한다. 간단하게 액티비티를 생각하면 된다.
-
- 장점
- 모델이 뷰와 컨트롤러에서 어떤 부분도 참조하지 않기 때문에 독립적이다. 따라서 모델의 테스트가 쉽고 직관적이게 되며, 코드 재사용에 용이하다.
-
- 단점
- 모델은 독립적일지 몰라도 컨트롤러는 뷰에 민감하다. 뷰를 변경하면 컨트롤러의 코드 또한 변경해야 하는데, 텍스트 뷰를 하나 추가한다면 그것을 액티비티에 추가해야 하는 것을 간단한 예로 들 수 있겠다. 그리고 코드가 복잡해질 수록 모델과 뷰를 연결하는 컨트롤러의 양이 많아진다는 문제도 발생한다. 직관적으로 생각해봐도 아무런 참조를 하지 않는 모델이나, 모델의 데이터를 출력/컨트롤러로부터 화면을 갱신 받는 뷰에 비해 코드가 비대해질 수 밖에 없다.
2. MVP(Model View Presenter)
MVP는 컨트롤러의 문제점을 덜기 위해, 뷰에 안드로이드 액티비티가 결합된 패턴이다.
-
- Model
- MVC와 동일하다.
-
- View
- MVC가 XML 파일만 가졌던 것과 달리 안드로이드 액티비티와 프래그먼트가 뷰에 소속된다. 그러므로 뷰와 컨트롤러 간의 높은 결합성은 사라진다. 하지만 이전과 달리 뷰를 추상화 해 인터페이스를 만들 필요가 있는데, 프레젠터에게 유저의 동작을 전달해야 하기 때문이다. 더불어 가상 뷰의 구현으로 유닛 테스트 진행도 원활해진다.
-
- Presenter
- 모델과 뷰를 매개한다는 점에서 컨트롤러와 유사하지만, 뷰에 직접 연결되는 대신 인터페이스를 통해 통신한다는 점이 다르다. 여전히 뷰와 프레젠터는 긴밀한 관계를 가지므로 서로의 참조자를 가지게 된다.
-
- 장점
- MVC의 단점을 해결해 코드의 분리가 명확해진다. 또한 뷰의 추상화로 인해 프레젠터를 테스트하기 수월해진다.
-
- 단점
- 뷰의 추상화로 인해 인터페이스가 너무 많아진다는 점과, MVC와 마찬가지로 뷰와 모델의 매개 역할을 하기 때문에 코드가 복잡해짐에 따라 무거워질 수 있다는 문제점이 발생한다.
참고로 MVP는 다음 글에서 그 예를 다루고 있다. 안드로이드 MVP 패턴 정리
3. MVVM(Model View ViewModel)
뷰를 추상화한다는 점에서는 MVP와 유사하지만, 안드로이드의 데이터 바인딩을 사용해 인터페이스가 불필요한 패턴이다.
-
- Model
- MVC와 동일하다.
-
- View
- ViewModel의 메소드가 뷰에 바인딩된다. 가령 XML의 텍스트에 viewModel.value[“1”]과 같은 식으로 직접적인 데이터 전달이 가능하다. 물론 이를 위해서 뷰는 ViewModel에 접근할 수 있는 참조자가 필요하다.
-
- ViewModel
- 뷰의 추상화로, 뷰의 상태를 노출시키기 위한 모델이다. 뷰모델은 데이터바인딩을 사용하기 때문에 MVP의 프레젠터와 다르게 View의 인터페이스를 가지지 않아도 된다. 그렇기 때문에 뷰에 종속되지 않는다는 특징을 갖는다.
-
- 장점
- 뷰 인터페이스를 만들지 않아도 된다. 같은 맥락으로, 뷰에 참조자를 두지 않아서 뷰모델이 뷰에 종속되지 않기 때문에 테스트를 작성하기 수월하며, 모델 또한 마찬가지이다.
-
- 단점
- 뷰에 직접적으로 데이터를 바인딩하기 때문에 XML이 복잡해질 수 있다.
이 주제는 다루려면 한 없이 길게 다룰 수 있는 주제이지만, 이번 글에서는 안드로이드 아키텍쳐 패턴에 대해 간략히 알아봤다. 솔직히 말해 안드로이드 패턴을 처음 접했을 때는 이게 무슨 말인지 전혀 감이 잡히지 않았다. 하지만 직접 코드에 패턴 중 하나인 MVP를 적용해보고, 또 글을 정리하니 조금씩 좋은 코드에 다가서게 되는 듯하다. 앞으로 더 노력해서 MVP와 MVVM 패턴을 능숙하게 다룰 수 있는 안드로이드 개발자가 되고 싶다.