본문 바로가기
안드로이드 자바

[JAVA][Android] MVP 패턴 익혀보기

by teamnova 2021. 10. 10.
728x90

이전에 배운 MVC 패턴에 이어서 

 

이번에 배울 패턴은 MVP 패턴입니다.

 

어딘가 비슷하면서도 다른것 같은데 함께 알아볼까요?


MVP 패턴이란?

 

MVP 패턴이란 Model, View, Presenter의 첫 글자를 따서 이름이 지어졌습니다. MVP의 핵심 설계는 MVC와는 다르게

 

UI(View)와 비즈니스 로직(Model)을 분리하고, 서로 간에 상호작용을 다른 객체(Presenter)에 그 역할을 줌으로써 서로의

 

영향(의존성)을 최소화하는 것에 있습니다.

 

 

 

 

 

  • Model
    • 프로그램 내부적으로 쓰이는 데이터를 저장하고, 처리하는 역할을 함.(비즈니스 로직)
    • View 또는 Presenter 등 다른 어떤 요소에도 의존적이지 않은 독립적인 영역임.
  • View
    • UI를 담당하며 안드로이드에서는 Activity, Fragment가 대표적인 예.
    • Model에서 처리된 데이터를 Presenter를 통해 받아서 유저에게 보여줌.
    • 유저 액션(Action) 및 액티비티 라이프사이클 상태 변경을 주시하며 Presenter에 보내는 역할임.
    • Presenter를 이용해 데이터를 주고받기 때문에 Presenter에 매우 의존적임.
  • Presenter
    • Model과 View사이의 매개체.
    • 모델과 뷰를 매개체라는 점에서 Controller와 유사하지만, View에 직접 연결되는 대신 인터페이스를 통해 상호작용 한다는 점이 다름.
    • 인터페이스를 통해 상호작용 하므로 MVC가 가진 테스트 문제와 함께 모듈화/유연성 문제 역시 해결할 수 있음.
    • 뷰에게 표시할 내용(Data)만 전달하며 어떻게 보여줄지는 View가 담당.

 

 

장점

MVC 와는 다르게 코드가 매우 깔끔 해지며 MVP를 이용해서 이와 같이 Model과 View 간의 결합도를 낮추면, 새로운

 

기능 추가 및 변경을 해야 할 때 관련된 해당 부분만 코드 수정하면 되기 때문에 확장성이 좋아짐과 동시에 유닛 테스트

 

시 테스트 코드를 작성하기 편리해지기 때문에 더 쉽게 안전한 코딩이 가능해집니다.그리고 UI, Data 각각 파트를 나누

 

기 때문에 해야 할 일이 명확해지고 그 결과로 쉽고 빠르게 코딩이 가능합니다.

 

단점

가장 큰 단점은 애플리케이션이 복잡해질수록 View와 Presenter 사이의 의존성이 강해지는 단점이 있습니다.


그리고 MVC의 Controller처럼 Presenter도 어느 정도 시간이 지남에 따라 추가 비즈니스 로직이 집중되는 경향이 있습

 

니다.개발자는 시간이 지난 어느 순간 거대해지며 동시에 다루기도 어렵고, 문제가 발생하기 쉽고, 서로 간의 분리를 하

 

기도 어려운 Presenter를 발견하게 됩니다.물론 초기에 설계/기획을 잘함과 동시에 유능한 개발자라면 시간의 흐름에 따

 

른 앱의 다양한 변화에 맞춰서 이 문제를 해결해나갈 수 있겠지만 실제로는 그것도 쉽지만은 않습니다.

 


저희가 진행할 예제의 구조입니다.

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".View.MainActivity">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <EditText
                android:id="@+id/number1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ems="10"
                android:inputType="textPersonName" />

            <EditText
                android:id="@+id/number2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ems="10"
                android:inputType="textPersonName" />
        </LinearLayout>

        <Button
            android:id="@+id/sum"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button" />

        <TextView
            android:id="@+id/result"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="TextView" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

 

[ Presenter ]

Contractor.java

//Contract Interface
//View와 Presenter를 연결하기 위한 Interface
package com.example.mvp.Presenter;

public interface Contract {
    interface View{
        void showResult(int answer);      //값을 보여줄 View 메소드 선언
    }
    interface Presenter{
        void addNum(int num1, int num2);  //결과 값 구하기 위한 메소드 선언
    }
}

 

MainPresenter.java

//MainPresenter class
//Model과 View를 연결하여 동작을 처리해
package com.example.mvp.Presenter;

import com.example.mvp.Model.MainModel;

//Presenter줌
public class MainPresenter implements Contract.Presenter {
    Contract.View view;
    MainModel mainModel;
    public MainPresenter(Contract.View view){
        this.view = view;                   //Activty View정보 가져와 통신
        mainModel = new MainModel(this);    //Model 객체 생성
    }
    
    //Presenter를 상속하고 addNum 구현
    @Override
    public void addNum(int num1, int num2) {
        view.showResult(num1 + num2);
    }
}

 

[ View ]

MainActivity.java

//MainActivity class
package com.example.mvp.View;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.example.mvp.Presenter.Contract;
import com.example.mvp.Presenter.MainPresenter;
import com.example.mvp.R;

//View
public class MainActivity extends AppCompatActivity implements Contract.View {
    private EditText number1;		//입력할 EditText
    private EditText number2;		//입력할 EditText
    private Button sumButton;
    private Contract.Presenter presenter;	//presenter와 통신하기 위해 객체 생성
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        presenter = new MainPresenter(this);
        init();
    }

    private void init(){
        sumButton = (Button)findViewById(R.id.sum);
        number1 = (EditText)findViewById(R.id.number1);
        number2 = (EditText)findViewById(R.id.number2);
        
        //버튼 클릭
        sumButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            	//결과 값 계산
                presenter.addNum(Integer.parseInt(number1.getText().toString()),
                        Integer.parseInt(number2.getText().toString()));
            }
        });
    }
    @Override
    public void showResult(int answer) {
        ((TextView)findViewById(R.id.result)).setText(Integer.toString(answer));
    }
}

 

[ Model ]

 

MainModel.java

//MainModel class
//데이터 관리를 해줄 클래스
package com.example.mvp.Model;

import com.example.mvp.Presenter.Contract;

//Model
public class MainModel {
    Contract.Presenter presenter;
    public MainModel(Contract.Presenter presenter){
        this.presenter = presenter;
    }
   
}

 

https://stickode.com/mainlogin.html

 

STICKODE

 

stickode.com

 

 

다음번에는 간단한 MVP의 단점을 보완한 디자인 패턴에 대해 알아보도록 하겠습니다.