Android/Theory

Android MVP Pattern

Ju_Hyang 2019. 7. 15. 17:36

원본 : 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의 자원이 많아질 수 있습니다. 패턴으로 코드의 가독성 및 보수유지에 도움을 줄 수 있으나, 프로젝트에 따른 코드 자원의 증가를 어떻게 관리할 것인지 연구가 필요해 보입니다.