2015년 03월 10일 | Steve.Jung

AndroidAnnotations 와 MVP

앞선 포스팅에서 우리는 MVC, MVP, MVVM 에 대해서 알아보았습니다.

그 중 MVP 는 최근에 View 와의 상호작용은 물론 모델과 뷰 분리도 효과적으로 구현할 수 있어 iOS 와 Android 모두에 적합한 모델이라는 평가를 받고 있습니다.

그럼 MVP 가 어떤 구조이고 실제로 코드상으로 어떻게 구현되었기에 모바일에 적합한 패턴인지 보도록 하겠습니다.

MVP 란?

앞선 포스팅에서 말했듯이 MVP 는 Model-Presenter-View 관계를 나타내는 패턴입니다.

View 는 어떠한 Presenter 와 연결될 지를 결정하여 스스로 제어될 곳을 결정합니다. View 로부터 제어권을 할당받은 Presenter 는 Model 을 통해서 필요한 로직을 수행한 후 View 에게 다시 보여질 화면을 구현하도록 요청합니다.

그래서 관계도를 보면 아래와 같습니다.

mvp-uml

  • MVP 조건
  • View : Presenter = 1:1 이어야 합니다.
  • View 와 Presenter 는 서로 참조하고 있습니다.
  • View 와 모델은 서로의 존재를 모릅니다.

View 의 주 역할은 2가지입니다.

  1. 실제 View 에 직접 접근하여 화면을 갱신합니다.
  2. View 에서 발생하는 이벤트를 Presenter 로 전달합니다.

그래서 Presenter 에는 View 에서 전달받은 이벤트 위주로 설계되기에 on…으로 시작 하는 메소드가 주로 있고 View 는 화면을 갱신해주는 기능이 주로 있어 update… set… 과 같은 메소드가 주를 이루고 있습니다.

코드

그러면 AndroidAnnotations 로 구현한 MVP 코드를 살펴보도록 하겠습니다.

public interface Presenter {
	void setView(View view);
	void onInfoRequest();
}
public interface View {
	void setResultText(String result);
}
@EBean
public class PresenterImpl implements Presenter {
	
	private View view;
	
	@Bean
	private Model model;
	
	@Override
	public void setView(View view) {
		this.view = view;
	}
	
	@Background
	@Override
	public void onInfoRequest() {
		String result = model.requestInfo(); // Network
		view.setResultText(result);
	}
}
@EActivity(R.layout.act_main)
public class MainActivity extends Activity implements View {

	@Bean(PresenterImpl.class)
	Presenter presenter;
	
	@ViewById(R.id.txt_main)
	TextView resultTextView;
	
	@AfterInject
	void initObject() {
		presenter.setView(this);
	}
	
	@Click(R.id.btn_main)
	void onMainClick() {
		presenter.onInfoRequest();
	}
	
	@UiThread
	@Override
	public void setResultText(String result) {
		resultTextView.setText(result);
	}
}

MVC 와는 대조적으로 구현된 모습을 보실 수 있습니다.

MVC 에서는 Activity 가 Controller 역할을 수행했기 때문에 주로 @Background 어노테이션 위주로 구현하였습니다. 또한 Click 과 같은 이벤트를 직접적으로 처리하도록 하였습니다.

반면 MVP 에서는 Activity 가 View 역할을 수행하고 있습니다. 따라서 @UiThread 위주로 구현되어 있으며 Click 과 같은 이벤트는 직접 처리하지 않고 Presenter 로 전달하여 처리하도록 하고 있습니다. 그래서 Presenter 가 일종에 Controller 와 같은 역할을 수행하기 때문에 @Background 위주로 구현되어 있습니다.

결론

MVP 는 MVC 와는 대조적인 모습을 가지고 있습니다. Controller 의 기능을 Presenter 가 가지고 있지만 직접적으로 외부의 요청을 받아들이는 곳이 아닙니다. 이 과정에서 MVC 는 Controller 에서 모든 코드의 진행을 알 수 있는 반면 MVP 는 외부의 요청을 받는 곳에서 부터 코드를 쫓아가는 모습을 볼 수 있습니다.

하지만 이는 단점이 아니라 장점이 될 수 있습니다. 이러한 구현은 OOP 의 5대 원칙을 충실히 할 수 있습니다. 뿐만 아니라 자연스럽게 Activity ↔ Fragment 또는 Fragment 간의 통신에도 적용할 수 있습니다.

MVC, MVP 모두 좋은 구현 방법이며 관점에 따라서 맞춰서 사용하면 되는 것입니다. 단, 이러한 패턴을 사용할 때는 일관적인 모습으로 구현을 하여야 한다는 점을 잊어서는 안됩니다.