Android MVP Pattern
원본 : https://faith-developer.tistory.com/71
MVP 는 Model - View - Presenter 로 구성됩니다. MVP가 나오게 된 이유는 View와 Model을 완전히 분리해서 사용하기 위해서 입니다. MVP는 Model의 역할인 비즈니스 로직을 독립적으로 테스트할 수 있습니다. MVP패턴의 각 구성에 대해서 자세히 알아보겠습니다.
-
MVP 패턴 구성 요소
-
MVP 모델은 Model - View - Presenter로 구성됩니다.
-
뷰 (View)
-
실제 view 에 대한 직접적인 접근을 담당합니다. 안드로이드에서는 액티비티 / 프래그먼트는 뷰의 일부로 정의합니다.
-
View에서 발생하는 이벤트는 직접 핸들링 할 수 있으나 Presenter 에 위임하도록 합니다. 위임하는 방법은 액티비티가 뷰 인터페이스를 구현해서 Presenter에서 코드를 만들 인터페이스를 갖도록 하면 됩니다. 이렇게 하면 특정 뷰와 결합되지 않고 가상 뷰를 구현해서 간단한 유닛테스트를 실행할 수 있습니다.
-
프리젠터 (Presenter)
-
본질적으로는 MVC의 컨트롤러와 같지만, 뷰에 연결되는 것이 아니라 인터페이스로 연결된다는 점이 다릅니다. 이에 따라 MVC가 가진 가능성 테스트 문제와 함께 모듈화 / 유연성 문제 역시 해결합니다. 프리젠터 (Presenter)의 역할을 한줄로 표현한다면 뷰 (View)와 모델 (Model)사이에서 자료 전달 역할을 합니다.
-
모델 (Model)
-
앱 데이터 및 상태에 대한 비즈니스 로직을 수행합니다.
-
* 비즈니스 로직 (Business Login)은 컴퓨터 프로그램의 규칙에 따라 데이터를 생성, 표시, 저장, 변경하는 부분을 말합니다. 데이터베이스, 표시장치 등 프로그램의 다른 부분과 대조되는 개념으로 쓰입니다.
-
코드로 보는 MVP (Model - View - Presenter)
-
간단한 두 수를 더하는 앱을 통하여 MVP 패턴이 어떻게 적용되는지 알아보겠습니다. 앱에서 MVP 패턴의 각 역할은 다음과 같습니다
-
뷰 (View)
-
액티비티 (Activity) 화면 구성 및 인터페이스 제공
-
프리젠터 (Presenter)
-
두 수의 계산 및 데이터를 저장합니다.
-
모델에 데이터를 전송하여 저장하는데 도움을 줍니다.
-
모델 (Model)
-
데이터를 저장합니다.
-
뷰 (View)
-
Presenter에서 호출 할 수 있도록 View의 Interface를 갖고 있으며, Presenter를 생성하여 Interface로 View와 Presenter 통신을 합니다. 또한 위젯 조작을 구성하고 있습니다.
public class MainActivity extents Activity implements MainConstants.View {
MainConstants.Presenter mainPresenter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainPresenter = new MainPresenter();
initListener();
}
private void initListener(){
String inputA = ((EditText)findViewById(R.id.editInputA)).getString().toString();
String inputB = ((EditText)findViewById(R.id.editInputB)).getString().toString();
// '=' 버튼 클릭 시 덧셈 결과 받기
findViewById(R.id.btnResult).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mainPresenter.addNums(inputA, inputB);
}
});
}
@Override
public void showResult(int result){
((TextView)findViewById(R.id.txtResult)).setText(Integer.toString(result));
}
}
-
프리젠터 (Presenter)
-
View의 통신을 위해서 Interface를 갖고 있으며, Model을 직접적으로 연결합니다. Presenter에서 UI 작업은 View의 Interface을 통해서 표시 합니다. 데이터 저장, 삽입 등 비즈니스 로직이 필요 시 Model을 호출하여 작업합니다.
public interface MainConstants {
interface View{
// View 에 계산한 결과를 표시
void showResult(int result);
}
interface Presenter{
// View에서 입력한 두 수에 대한 덧셈
void addNums(int input1, int input2);
// 데이터 저장
void saveData(int data);
}
}
public class MainPresenter implements MainConstants.Presenter {
MainConstants.View mainView;
MainModel mainModel;
public MainPresenter(MainConstants.View view){
// View 연결
mainView = view;
// Model 연결
mainModel = new MainModel(this);
}
@Override
public void addNums(int input1, int input2) {
mainView.showResult(input1 + input2);
}
@Override
public void saveData(int data) {
mainModel.saveData(data);
}
}
-
모델
-
비즈니스 로직만 구성됩니다. Presenter에 저장된 데이터를 호출하여 전송 및 데이터를 저장하는 기능을 하게 됩니다.
public class MainModel {
MainConstants.Presenter presenter;
public MainModel(MainConstants.Presenter presenter){
this.presenter = presenter;
}
// Presenter 에서 데이터 저장 시 호출됩니다
// 자세한 저장 로직은 생략했습니다
public void saveData(int data){
//Todo..SaveData
}
}
-
정리
-
앱 프로젝트 진행하다보면 소스 정리에 대해 고민을 하게 되는데, MVP 패턴을 사용한다면 인터페이스와 로직을 분리해서 관리 할 수 있다는 장점이 있습니다. 또한 유닛테스트로 활용 시 테스트 화면만 그려서 테스트 할 수 있다는 장점이 있었습니다. 단점으로는 하나의 화면 생성 시 Model, View, Presenter, Interface를 생성해야하는 불편함이 있습니다. 또한 프로젝트가 커질 수록 Presenter의 자원이 많아질 수 있습니다. 패턴으로 코드의 가독성 및 보수유지에 도움을 줄 수 있으나, 프로젝트에 따른 코드 자원의 증가를 어떻게 관리할 것인지 연구가 필요해 보입니다.