SlideShare uma empresa Scribd logo
1 de 41
Baixar para ler offline
MVP 패턴 소개 (안드로이드)
신림프로그래머, 최범균, 2016-06-18
madvirus@madvirus.net
다룰 내용
• 막 만들면
• MVP 패턴
– 적용 결과
• MVP 패턴 적용 예
– 안드로이드
– 자바스크립트
• 정리
2
간단한 앱, 막 만들면…
3
드래그 탭
미림분식
별: 5
4
public class StoreActivity extends Activity …. {
private Handler handler = new Handler();
protected void onStart() {
loadingProgress.show();
LoadListThread lThread = new LoadListThread();
lThread.start();
}
private class LoadListThread extends Thread {
public void run() {
URL url = new URL(urlstr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
...
handler.post(new Runnable() {
public void run() {
loadingProgress.hide();
if (loadingResult) {
localDB.save(loadedData);
drawMarkerForStores(loadedData);
} else {
toasts..short("에러!");
}
}
});
}
}
기능 흐름 제어
데이터 보관 처리
UI 화면 제어
네트
워크
UI 처리 위한 쓰레드
화면 제어
쓰레드 제어
5
public class StoreActivity extends Activity …. {
private MapPoint center;
public void onMapViewDragEnded(
MapView mapView, MapPoint mapPoint) {
center = mapPoint;
loadingProgress.show();
LoadListThread lThread = new LoadListThread();
lThread.start();
}
private class LoadListThread extends Thread {
public void run() {
URL url = new URL(urlstr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
...
if (center != null) { params.put("center", toCoord(center)); }
...
handler.post(new Runnable() {
public void run() {
loadingProgress.hide();
…
}
});
}
}
사용자 이벤트 처리
UI 의존
데이터
화면 제어 + 쓰레드 제어
6
public class StoreActivity extends Activity …. {
private LocalDB localDB;
public void onMarkerTab(MapView mapView, Marker marker) {
StoreData storeData = localDB.select(marker.getMeta().getId());
if (storeData == null) {
alerts.showAlert("데이터가 없습니다.");
} else {
showBalloon(mapView, storeData);
}
}
private void showBallon(MapView mapView, StoreData storeData) {
BalloonInfoWindow infoWin = new BallonInfoWindow(this,storeData);
mapView.addFigure(infoWin);
…
}
데이터
조회
화면 흐름 제어
위젯
제어
막 만들다 보면
7
UI 조작
흐름 제어
로직
쓰레드
네트워크
DB
도메인
로직
단점
• 실행 흐름 파악이 어렵다.
– 흐름 제어 로직이 산재
• 부분적인 테스트가 어렵다.
– 위젯 조작 + UI 흐름 제어 + 데이터 관리 짬뽕
• 변경이 점점 어려워진다.
– 산재한 로직, 뒤섞인 코드  코드 변경 어려움
8
해결책
9
역할에 따라 알맞게 나누기
10
MVP
Model-View-Presenter
11
모델프리젠터뷰
• 비즈니스 로직과
어플리케이션
데이터
• 어플리케이션의
인터페이스
• 사용자에게는 뷰가 곧
어플리케이션
• 빈번하게 바뀌는 영역
• 모델과 뷰를 연결
• MVP에서 프리젠터는
기능/흐름을 제공
• 요구사항이 프리젠터의
기능에 대응
Model-View-Presenter
12
모델프리젠터뷰
• 비즈니스 로직과
어플리케이션
데이터
• 예, 인증
• 예, 특정 위치 기준
가계 정보
• 이벤트를 프리젠터에
전달
• 예, 로그인 버튼 클릭을
클릭하면 프리젠터에
인증 실행 요청
• 사용자에게 알맞은 화면
제공
• 예, 프리젠터를 통해
전달받은 데이터를
리스트와 같은 위젯을
이용해서 표현
• 로딩 중, 경고 대화창 등
안내
• 사용자 요청에 반응
• 예, 뷰를 통해 인증 요청을
받으면 모델을 사용해서
인증을 수행하고, 결과를
뷰에 전달
• 뷰의 흐름 제어
• 예, 인증 시작 전에 뷰를
통해 진행 중 대화창을
보여주고, 인증에 성공하면
뷰를 통해 메인 화면으로
이동
뷰
• 인터페이스
– 사용자에게 보여질
기능을 정의
– 프리젠터가 호출할 기능
• 예
– 데이터 출력 기능
– 진행 중 알림 기능
• 뷰 구현체
– 인터페이스에 정의한
기능의 구현 제공
– 사용자 이벤트를
프리젠터에 전달
• 예
– 데이터를 리스트로 표시
– 사용자가 항목을
클릭하면 프리젠터에
선택 요청 전달
13
뷰 구현
14
public interface StoreListView {
void showLoadingMessage();
void hideLoadingMessage();
void displayStores(stores);
void showFailMessage();
}
public class MapStoreListView implements StoreListView, … {
private StoreListPresenter presenter;
public void MapStoreListView(StoreListPresenter presenter) {
presenter.setView(this);
}
public void onMapViewDragEnded(
MapView mapView, MapPoint mapPoint) {
Coord center = toCoord(mapView.getCenter()))
presenter.onLocationChange(center);
}
public void showLoadingMessage() {
progress = ProgressDialog.show(this, "", "로딩중");
}
public void hideLoadingMessage() { progress.hide(); }
public void displayStores(List<Store> stores) {
…지도위에 마커 표시
}
프리젠터 정의
• 사용자의 UI 행위를 추상화한 메서드로
기능을 정의
– 뷰 구현에 의존하지 않음
15
onLocationChange: 상점을 조회할 위치 기준을 변경한다는 의미, O
뷰 구현 기술에 종속되지 않음
onMapDragged: 뷰의 지도를 드래그했다는 것을 의미, X
뷰 구현 기술에 종속됨
프리젠터 구현
• 모델과 뷰를 사용해서 사용자의 요청 처리
16
public class StoreListPresenter {
private StoreListView view;
private StoreListModel model;
public void onLocationChange(Coord location) {
view.showLoadingMessage();
try {
List<Store> stores = model.getStoresIn(location, 100);
view.hideLoadingMessage();
view.displayStores(stores);
} catch(Exception e) {
view.hideLoading();
view.showFailMessage();
}
}
UI 로직을
제어
모델로
비즈니스
로직 실행
전형적인 실행 흐름
17
MVP 적용 결과
• 뷰 구현 기술과 UI 로직(프리젠터)의 분리
– UI 로직 응집도 향상
18
MVP 적용 결과
• UI 구현 기술(뷰)과 UI 로직(프리젠터)의 분리
– UI 로직에 영향을 주지 않고 뷰 구현 변경 가능
19
public class MapStoreListView
implements StoreListView, … {
private StoreListPresenter presenter;
…
public void displayStores(List<Store> stores) {
listAdapter.clear();
listAdapter.addAll(stores);
}
public class MapStoreListView
implements StoreListView, … {
private StoreListPresenter presenter;
…
public void displayStores(List<Store> stores) {
map.clearAllMarks();
for(Store store : stores) {
map.addMarker(createMarker(store));
}
}
MVP 적용 결과
• UI 구현 기술(뷰), UI 로직(프리젠터), 도메인
로직(모델) 구현의 분리
– 뷰/모델 구현없이 UI 로직 테스트 가능
• 뷰를 구현하지 않아도 모의(mock) 객체로 UI 로직에
대한 테스트 가능
20
21
안드로이드와 MVP
기본 구조
22
Activity나 Fragment 역할
23
public class MapStoreListActivity implements StoreListView, … {
private StoreListPresenter presenter;
public void onCreate(Bundle savedInstanceState) {
StoreListModel model = new RestStoreListModel();
this.presenter = new StoreListPresenter(this, model);
this.presenter.init();
}
public void onMapViewDragEnded(MapView mapView, MapPoint mapPoint) {
Coord center = toCoord(mapView.getCenter()))
presenter.onLocationChange(center);
}
public void showLoadingMessage() {
progress = ProgressDialog.show(this, "", "로딩중");
}
public void hideLoadingMessage() {
progress.hide();
}
public void displayStores(List<Store> stores) {
…지도위에 마커 표시
}
뷰 구현
프리젠터/모델 객체를
생성하고 연결
안드로이드 앱에서 모델의 특징
• 외부 서버와 통신을 비동기로 처리
– 허니콤(3.0): Main(UI) 쓰레드에서 네트워크 금지
– AsyncTask나 Thread 사용
• 프리젠터에 비동기 결과 전달 방법 필요
– 주요 방법: 콜백(Callback), 옵저버(Observer) 등
24
모델과 콜백
25
public class RestStoreListModel
implements StoreListModel {
public void getStoresIn(Coord center,
int distance,
StoreListCallback callback) {
new Thread(new Runnable() {
public void run() {
try {
… network 처리, 데이터 변환
callback.onSuccess(results);
} catch(Exception ex) {
callback.onFail(ex);
}
}
}).start();
}
public interface StoreListCallback {
void onSuccess(List<Store> stores);
void onFail(Exception ex);
}
프리젠터는 콜백을 통해 결과 수신
26
public class StoreListPresenter {
public void onLocationChange(Coord coord) {
view.showProgressMessage();
model.getStoresIn(coord, 100,
new StoreListCallback() {
public void onSuccess(List<Store> stores) {
view.hideProgressMessage();
view.displayStores(stores);
}
public void onFail(Exception ex) {
view.hideProgressMessage();
view.showFailMessage(ex);
}
});
}
프리젠터와 라이프사이클
• Activity/Fragment의 라이프사이클에 맞춰
기능을 구현해야 할 경우, 프리젠터에
라이프사이클 관련 메서드 정의
27
public class StoreListPresenter {
public void onResume() { … }
public void onStop() { … }
…
}
public class StoreListActivity … {
@Override
protected void onResume() {
super.onResume();
presenter.onResume();
}
@Override
protected void onStop() {
super.onStop();
presenter.onStop();
}
유용한 도구
• Dagger
– 의존 주입(DI)
– Activity에서 직접 프리젠터나 뷰를 생성하지
않도록 해 줌
• RxJava
– 옵저버
– 콜백 인터페이스 대체
28
29
자바스크립트
기본 구현
• 구성 요소는 동일
– 언어 특성상 인터페이스없이 구현
• 초기화
– HTML 로딩 시점에 뷰/모델/프리젠터 초기화
• 예, $.ready()에서 초기화
30
뷰 예시
31
functionMeasureListView(){
varpresenter;
functiononSelect(idx){ presenter.selectMeasure(idx); }
functioninit(){
resizeContent();
...
};
...
init();
return{
setPresenter:function(_presenter){ presenter=_presenter; },
showMeasures:function(measures){
if(measures.length==0){
$("#noData").show();
}else{
$("#hasData").show();
measureBox.setState({measures:measures,loading:false});
}
},
showLoadingError:function(){console.log("error"); }
};
}
프리젠터 예시
32
function MeasureListPresenter(view, model) {
this.reloadList = function() {
model.getMeasureList({
success: function(measures) {
view.showMeasures(measures);
},
error: function() {
view.showLoadingError();
}
});
};
this.selectMeasure = function(idx) {
var measure = model.getMeasure(idx);
view.showMeasure(measure);
};
}
모델 예시
33
functionMeasureListModel(){
varmeasures=[];
functiontoCoord(coordStr){...}
functionconvertToMeasure(feeds){...};
return{
getMeasureList:function(callback){
$.ajax({url:"https://api.mycompany.com/....", type:'GET',
success:function(data){
varmeasures=convertToMeasure(data.feeds);
callback.success(measures);
},
error:function(xhr,status,error){callback.error();}
});
},
getMeasure:function(idx){returnmeasures[idx];}
};
}
초기화 예
34
<script>
$(document).ready(function() {
var model = new MeasureListModel();
var view = new MeasureListView();
var presenter = new MeasureListPresenter(view, model);
view.setPresenter(presenter);
presenter.reloadList();
});
</script>
35
생각할 거리
뷰와 외부 입력
• 뷰의 역할: 외부 데이터 입력
– 기능 예
• 블루투스로 데이터를 받는 기능
• GPS로 현재 좌표 받는 기능
– 이 두 기능은 뷰를 통해 전달받는 사용자 이벤트
36
모델 영역의 구조
• 모델에 얼마나 많은 도메인 로직이 있나?
– 앱/웹에서 모델은 주로 다음의 두 가지 수행
• 서버와 통신
– 중요 로직은 서버에 존재
• 임시로 데이터 보관
– 로컬DB, 메모리 등에 보관
• 모델에 다양한 로직이 있다면 테스트 가능한
구조로 만드는 것이 중요
37
프리젠터
• 인터페이스와 구현체로 구분 필요 여부
– 코드 수준 테스트 대상은 주로 프리젠터와 모델
– 프리젠터가 유연해야 하는 경우 드뭄
– 모델 테스트시 프리젠터에 대한 모의 객체가
필요한 경우 없음
• 프리젠터 메서드 이름, 파라미터, 리턴 타입
– 뷰에 의존하면 안 됨
• 프리젠터 먼저 구현하기
38
39
정리
MVP
• 뷰 구현, UI 로직, 모델 구현을 분리
• 복잡도 감소
– 분리에 따른 복잡도 <<< 뒤섞일 때의 복잡도
• 생산성 향상시키기
– 코드 변경이 상대적으로 쉬워짐
– UI 구현없이 사용자와의 상호작용에 대한 테스트
가능
40
41
끝

Mais conteúdo relacionado

Mais procurados

임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013
devCAT Studio, NEXON
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
devCAT Studio, NEXON
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
devCAT Studio, NEXON
 
임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012
devCAT Studio, NEXON
 

Mais procurados (20)

임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013
 
NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현
 
실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략실시간 게임 서버 최적화 전략
실시간 게임 서버 최적화 전략
 
[데브루키/141206 박민근] 유니티 최적화 테크닉 총정리
[데브루키/141206 박민근] 유니티 최적화 테크닉 총정리[데브루키/141206 박민근] 유니티 최적화 테크닉 총정리
[데브루키/141206 박민근] 유니티 최적화 테크닉 총정리
 
[Kgc2012] deferred forward 이창희
[Kgc2012] deferred forward 이창희[Kgc2012] deferred forward 이창희
[Kgc2012] deferred forward 이창희
 
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
 
AAA게임_UI_최적화_및_빌드하기.pptx
AAA게임_UI_최적화_및_빌드하기.pptxAAA게임_UI_최적화_및_빌드하기.pptx
AAA게임_UI_최적화_및_빌드하기.pptx
 
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
 
Ndc2010 김주복, v3. 마비노기2아키텍처리뷰
Ndc2010   김주복, v3. 마비노기2아키텍처리뷰Ndc2010   김주복, v3. 마비노기2아키텍처리뷰
Ndc2010 김주복, v3. 마비노기2아키텍처리뷰
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
 
[Unite2015 박민근] 유니티 최적화 테크닉 총정리
[Unite2015 박민근] 유니티 최적화 테크닉 총정리[Unite2015 박민근] 유니티 최적화 테크닉 총정리
[Unite2015 박민근] 유니티 최적화 테크닉 총정리
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
 
[NDC 2010] 그럴듯한 랜덤 생성 컨텐츠 만들기
[NDC 2010] 그럴듯한 랜덤 생성 컨텐츠 만들기[NDC 2010] 그럴듯한 랜덤 생성 컨텐츠 만들기
[NDC 2010] 그럴듯한 랜덤 생성 컨텐츠 만들기
 
UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1
 
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
고려대학교 컴퓨터학과 특강 - 대학생 때 알았더라면 좋았을 것들
 
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버
[NDC2017 : 박준철] Python 게임 서버 안녕하십니까 - 몬스터 슈퍼리그 게임 서버
 
[NDC 2009] 행동 트리로 구현하는 인공지능
[NDC 2009] 행동 트리로 구현하는 인공지능[NDC 2009] 행동 트리로 구현하는 인공지능
[NDC 2009] 행동 트리로 구현하는 인공지능
 
Umg ,이벤트 바인딩, Invaidation Box
Umg ,이벤트 바인딩, Invaidation BoxUmg ,이벤트 바인딩, Invaidation Box
Umg ,이벤트 바인딩, Invaidation Box
 
파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)파이썬 생존 안내서 (자막)
파이썬 생존 안내서 (자막)
 
임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012
 

Destaque

주니어 개발자도 이해 할 수 있는 아름다운 JVM 세상
주니어 개발자도 이해 할 수 있는 아름다운 JVM 세상주니어 개발자도 이해 할 수 있는 아름다운 JVM 세상
주니어 개발자도 이해 할 수 있는 아름다운 JVM 세상
Darion Kim
 

Destaque (10)

객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회객체 지향 발담그기 JCO 컨퍼런스 14회
객체 지향 발담그기 JCO 컨퍼런스 14회
 
Ddd start 부록 지앤선&ksug
Ddd start 부록 지앤선&ksugDdd start 부록 지앤선&ksug
Ddd start 부록 지앤선&ksug
 
모델링 연습 리뷰
모델링 연습 리뷰모델링 연습 리뷰
모델링 연습 리뷰
 
도메인구현 KSUG 20151128
도메인구현 KSUG 20151128도메인구현 KSUG 20151128
도메인구현 KSUG 20151128
 
주니어 개발자도 이해 할 수 있는 아름다운 JVM 세상
주니어 개발자도 이해 할 수 있는 아름다운 JVM 세상주니어 개발자도 이해 할 수 있는 아름다운 JVM 세상
주니어 개발자도 이해 할 수 있는 아름다운 JVM 세상
 
[JWPA-1]의존성 주입(Dependency injection)
[JWPA-1]의존성 주입(Dependency injection)[JWPA-1]의존성 주입(Dependency injection)
[JWPA-1]의존성 주입(Dependency injection)
 
토이 프로젝트를 하자.Pptx
토이 프로젝트를 하자.Pptx토이 프로젝트를 하자.Pptx
토이 프로젝트를 하자.Pptx
 
주니어 개발자도 이해 할 수 있는 의존성 주입(Dependency Injection)
주니어 개발자도 이해 할 수 있는 의존성 주입(Dependency Injection)주니어 개발자도 이해 할 수 있는 의존성 주입(Dependency Injection)
주니어 개발자도 이해 할 수 있는 의존성 주입(Dependency Injection)
 
Kotlin.md
Kotlin.mdKotlin.md
Kotlin.md
 
Dagger 2.0 을 활용한 의존성 주입
Dagger 2.0 을 활용한 의존성 주입Dagger 2.0 을 활용한 의존성 주입
Dagger 2.0 을 활용한 의존성 주입
 

Semelhante a MVP 패턴 소개

Design pattern 옵저버
Design pattern 옵저버Design pattern 옵저버
Design pattern 옵저버
Sukjin Yun
 
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
NAVER Engineering
 

Semelhante a MVP 패턴 소개 (20)

Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)Ji 개발 리뷰 (신림프로그래머)
Ji 개발 리뷰 (신림프로그래머)
 
MVVM Pattern for Android
MVVM Pattern for AndroidMVVM Pattern for Android
MVVM Pattern for Android
 
자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
 
Design pattern 옵저버
Design pattern 옵저버Design pattern 옵저버
Design pattern 옵저버
 
CRUD Pattern in Ajax
CRUD Pattern in AjaxCRUD Pattern in Ajax
CRUD Pattern in Ajax
 
Create App Easier With SVC Pattern - DroidKnights 2019 @Seoul
Create App Easier With SVC Pattern - DroidKnights 2019 @SeoulCreate App Easier With SVC Pattern - DroidKnights 2019 @Seoul
Create App Easier With SVC Pattern - DroidKnights 2019 @Seoul
 
C++ 개발자와 함께 하는 visual studio 2013
C++ 개발자와 함께 하는 visual studio 2013C++ 개발자와 함께 하는 visual studio 2013
C++ 개발자와 함께 하는 visual studio 2013
 
#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
 
주니어 입장에서 바라보는 디자인패턴 & 아키텍쳐.pdf
주니어 입장에서 바라보는 디자인패턴 & 아키텍쳐.pdf주니어 입장에서 바라보는 디자인패턴 & 아키텍쳐.pdf
주니어 입장에서 바라보는 디자인패턴 & 아키텍쳐.pdf
 
Coded ui가이드
Coded ui가이드Coded ui가이드
Coded ui가이드
 
Domain Specific Languages With Groovy
Domain Specific Languages With GroovyDomain Specific Languages With Groovy
Domain Specific Languages With Groovy
 
react-ko.pdf
react-ko.pdfreact-ko.pdf
react-ko.pdf
 
[D2 오픈세미나]3.web view hybridapp
[D2 오픈세미나]3.web view hybridapp[D2 오픈세미나]3.web view hybridapp
[D2 오픈세미나]3.web view hybridapp
 
Eclipse RCP 1/2
Eclipse RCP 1/2Eclipse RCP 1/2
Eclipse RCP 1/2
 
자바스크립트의 또다른 발전, Backbone.js
자바스크립트의 또다른 발전, Backbone.js자바스크립트의 또다른 발전, Backbone.js
자바스크립트의 또다른 발전, Backbone.js
 
Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
 
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
 
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
[TECHCON 2019: MOBILE - Android]2.예제에서는 알려주지 않는 Model 이야기
 
2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축
2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축
2017 Pycon KR - Django/AWS 를 이용한 쇼핑몰 서비스 구축
 

Mais de beom kyun choi

ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
beom kyun choi
 

Mais de beom kyun choi (20)

옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
 
DDD로 복잡함 다루기
DDD로 복잡함 다루기DDD로 복잡함 다루기
DDD로 복잡함 다루기
 
TDD 발담그기 @ 공감세미나
TDD 발담그기 @ 공감세미나TDD 발담그기 @ 공감세미나
TDD 발담그기 @ 공감세미나
 
keras 빨리 훑어보기(intro)
keras 빨리 훑어보기(intro)keras 빨리 훑어보기(intro)
keras 빨리 훑어보기(intro)
 
DDD 준비 서문래
DDD 준비 서문래DDD 준비 서문래
DDD 준비 서문래
 
Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀Tensorflow regression 텐서플로우 회귀
Tensorflow regression 텐서플로우 회귀
 
파이썬 언어 기초
파이썬 언어 기초파이썬 언어 기초
파이썬 언어 기초
 
Event source 학습 내용 공유
Event source 학습 내용 공유Event source 학습 내용 공유
Event source 학습 내용 공유
 
Spring Boot 소개
Spring Boot 소개Spring Boot 소개
Spring Boot 소개
 
ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료ALS WS에 대한 이해 자료
ALS WS에 대한 이해 자료
 
리뷰의 기술 소개
리뷰의 기술 소개리뷰의 기술 소개
리뷰의 기술 소개
 
스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해
 
자바8 스트림 API 소개
자바8 스트림 API 소개자바8 스트림 API 소개
자바8 스트림 API 소개
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
 
Zookeeper 소개
Zookeeper 소개Zookeeper 소개
Zookeeper 소개
 
하둡2 YARN 짧게 보기
하둡2 YARN 짧게 보기하둡2 YARN 짧게 보기
하둡2 YARN 짧게 보기
 
차원축소 훑어보기 (PCA, SVD, NMF)
차원축소 훑어보기 (PCA, SVD, NMF)차원축소 훑어보기 (PCA, SVD, NMF)
차원축소 훑어보기 (PCA, SVD, NMF)
 
Storm 훑어보기
Storm 훑어보기Storm 훑어보기
Storm 훑어보기
 
Hive 입문 발표 자료
Hive 입문 발표 자료Hive 입문 발표 자료
Hive 입문 발표 자료
 
HBase 훑어보기
HBase 훑어보기HBase 훑어보기
HBase 훑어보기
 

Último

Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)
Wonjun Hwang
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)
Wonjun Hwang
 

Último (6)

MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)
 
캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차
 
Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)
 

MVP 패턴 소개

  • 1. MVP 패턴 소개 (안드로이드) 신림프로그래머, 최범균, 2016-06-18 madvirus@madvirus.net
  • 2. 다룰 내용 • 막 만들면 • MVP 패턴 – 적용 결과 • MVP 패턴 적용 예 – 안드로이드 – 자바스크립트 • 정리 2
  • 3. 간단한 앱, 막 만들면… 3 드래그 탭 미림분식 별: 5
  • 4. 4 public class StoreActivity extends Activity …. { private Handler handler = new Handler(); protected void onStart() { loadingProgress.show(); LoadListThread lThread = new LoadListThread(); lThread.start(); } private class LoadListThread extends Thread { public void run() { URL url = new URL(urlstr); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); ... handler.post(new Runnable() { public void run() { loadingProgress.hide(); if (loadingResult) { localDB.save(loadedData); drawMarkerForStores(loadedData); } else { toasts..short("에러!"); } } }); } } 기능 흐름 제어 데이터 보관 처리 UI 화면 제어 네트 워크 UI 처리 위한 쓰레드 화면 제어 쓰레드 제어
  • 5. 5 public class StoreActivity extends Activity …. { private MapPoint center; public void onMapViewDragEnded( MapView mapView, MapPoint mapPoint) { center = mapPoint; loadingProgress.show(); LoadListThread lThread = new LoadListThread(); lThread.start(); } private class LoadListThread extends Thread { public void run() { URL url = new URL(urlstr); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); ... if (center != null) { params.put("center", toCoord(center)); } ... handler.post(new Runnable() { public void run() { loadingProgress.hide(); … } }); } } 사용자 이벤트 처리 UI 의존 데이터 화면 제어 + 쓰레드 제어
  • 6. 6 public class StoreActivity extends Activity …. { private LocalDB localDB; public void onMarkerTab(MapView mapView, Marker marker) { StoreData storeData = localDB.select(marker.getMeta().getId()); if (storeData == null) { alerts.showAlert("데이터가 없습니다."); } else { showBalloon(mapView, storeData); } } private void showBallon(MapView mapView, StoreData storeData) { BalloonInfoWindow infoWin = new BallonInfoWindow(this,storeData); mapView.addFigure(infoWin); … } 데이터 조회 화면 흐름 제어 위젯 제어
  • 7. 막 만들다 보면 7 UI 조작 흐름 제어 로직 쓰레드 네트워크 DB 도메인 로직
  • 8. 단점 • 실행 흐름 파악이 어렵다. – 흐름 제어 로직이 산재 • 부분적인 테스트가 어렵다. – 위젯 조작 + UI 흐름 제어 + 데이터 관리 짬뽕 • 변경이 점점 어려워진다. – 산재한 로직, 뒤섞인 코드  코드 변경 어려움 8
  • 11. Model-View-Presenter 11 모델프리젠터뷰 • 비즈니스 로직과 어플리케이션 데이터 • 어플리케이션의 인터페이스 • 사용자에게는 뷰가 곧 어플리케이션 • 빈번하게 바뀌는 영역 • 모델과 뷰를 연결 • MVP에서 프리젠터는 기능/흐름을 제공 • 요구사항이 프리젠터의 기능에 대응
  • 12. Model-View-Presenter 12 모델프리젠터뷰 • 비즈니스 로직과 어플리케이션 데이터 • 예, 인증 • 예, 특정 위치 기준 가계 정보 • 이벤트를 프리젠터에 전달 • 예, 로그인 버튼 클릭을 클릭하면 프리젠터에 인증 실행 요청 • 사용자에게 알맞은 화면 제공 • 예, 프리젠터를 통해 전달받은 데이터를 리스트와 같은 위젯을 이용해서 표현 • 로딩 중, 경고 대화창 등 안내 • 사용자 요청에 반응 • 예, 뷰를 통해 인증 요청을 받으면 모델을 사용해서 인증을 수행하고, 결과를 뷰에 전달 • 뷰의 흐름 제어 • 예, 인증 시작 전에 뷰를 통해 진행 중 대화창을 보여주고, 인증에 성공하면 뷰를 통해 메인 화면으로 이동
  • 13. 뷰 • 인터페이스 – 사용자에게 보여질 기능을 정의 – 프리젠터가 호출할 기능 • 예 – 데이터 출력 기능 – 진행 중 알림 기능 • 뷰 구현체 – 인터페이스에 정의한 기능의 구현 제공 – 사용자 이벤트를 프리젠터에 전달 • 예 – 데이터를 리스트로 표시 – 사용자가 항목을 클릭하면 프리젠터에 선택 요청 전달 13
  • 14. 뷰 구현 14 public interface StoreListView { void showLoadingMessage(); void hideLoadingMessage(); void displayStores(stores); void showFailMessage(); } public class MapStoreListView implements StoreListView, … { private StoreListPresenter presenter; public void MapStoreListView(StoreListPresenter presenter) { presenter.setView(this); } public void onMapViewDragEnded( MapView mapView, MapPoint mapPoint) { Coord center = toCoord(mapView.getCenter())) presenter.onLocationChange(center); } public void showLoadingMessage() { progress = ProgressDialog.show(this, "", "로딩중"); } public void hideLoadingMessage() { progress.hide(); } public void displayStores(List<Store> stores) { …지도위에 마커 표시 }
  • 15. 프리젠터 정의 • 사용자의 UI 행위를 추상화한 메서드로 기능을 정의 – 뷰 구현에 의존하지 않음 15 onLocationChange: 상점을 조회할 위치 기준을 변경한다는 의미, O 뷰 구현 기술에 종속되지 않음 onMapDragged: 뷰의 지도를 드래그했다는 것을 의미, X 뷰 구현 기술에 종속됨
  • 16. 프리젠터 구현 • 모델과 뷰를 사용해서 사용자의 요청 처리 16 public class StoreListPresenter { private StoreListView view; private StoreListModel model; public void onLocationChange(Coord location) { view.showLoadingMessage(); try { List<Store> stores = model.getStoresIn(location, 100); view.hideLoadingMessage(); view.displayStores(stores); } catch(Exception e) { view.hideLoading(); view.showFailMessage(); } } UI 로직을 제어 모델로 비즈니스 로직 실행
  • 18. MVP 적용 결과 • 뷰 구현 기술과 UI 로직(프리젠터)의 분리 – UI 로직 응집도 향상 18
  • 19. MVP 적용 결과 • UI 구현 기술(뷰)과 UI 로직(프리젠터)의 분리 – UI 로직에 영향을 주지 않고 뷰 구현 변경 가능 19 public class MapStoreListView implements StoreListView, … { private StoreListPresenter presenter; … public void displayStores(List<Store> stores) { listAdapter.clear(); listAdapter.addAll(stores); } public class MapStoreListView implements StoreListView, … { private StoreListPresenter presenter; … public void displayStores(List<Store> stores) { map.clearAllMarks(); for(Store store : stores) { map.addMarker(createMarker(store)); } }
  • 20. MVP 적용 결과 • UI 구현 기술(뷰), UI 로직(프리젠터), 도메인 로직(모델) 구현의 분리 – 뷰/모델 구현없이 UI 로직 테스트 가능 • 뷰를 구현하지 않아도 모의(mock) 객체로 UI 로직에 대한 테스트 가능 20
  • 23. Activity나 Fragment 역할 23 public class MapStoreListActivity implements StoreListView, … { private StoreListPresenter presenter; public void onCreate(Bundle savedInstanceState) { StoreListModel model = new RestStoreListModel(); this.presenter = new StoreListPresenter(this, model); this.presenter.init(); } public void onMapViewDragEnded(MapView mapView, MapPoint mapPoint) { Coord center = toCoord(mapView.getCenter())) presenter.onLocationChange(center); } public void showLoadingMessage() { progress = ProgressDialog.show(this, "", "로딩중"); } public void hideLoadingMessage() { progress.hide(); } public void displayStores(List<Store> stores) { …지도위에 마커 표시 } 뷰 구현 프리젠터/모델 객체를 생성하고 연결
  • 24. 안드로이드 앱에서 모델의 특징 • 외부 서버와 통신을 비동기로 처리 – 허니콤(3.0): Main(UI) 쓰레드에서 네트워크 금지 – AsyncTask나 Thread 사용 • 프리젠터에 비동기 결과 전달 방법 필요 – 주요 방법: 콜백(Callback), 옵저버(Observer) 등 24
  • 25. 모델과 콜백 25 public class RestStoreListModel implements StoreListModel { public void getStoresIn(Coord center, int distance, StoreListCallback callback) { new Thread(new Runnable() { public void run() { try { … network 처리, 데이터 변환 callback.onSuccess(results); } catch(Exception ex) { callback.onFail(ex); } } }).start(); } public interface StoreListCallback { void onSuccess(List<Store> stores); void onFail(Exception ex); }
  • 26. 프리젠터는 콜백을 통해 결과 수신 26 public class StoreListPresenter { public void onLocationChange(Coord coord) { view.showProgressMessage(); model.getStoresIn(coord, 100, new StoreListCallback() { public void onSuccess(List<Store> stores) { view.hideProgressMessage(); view.displayStores(stores); } public void onFail(Exception ex) { view.hideProgressMessage(); view.showFailMessage(ex); } }); }
  • 27. 프리젠터와 라이프사이클 • Activity/Fragment의 라이프사이클에 맞춰 기능을 구현해야 할 경우, 프리젠터에 라이프사이클 관련 메서드 정의 27 public class StoreListPresenter { public void onResume() { … } public void onStop() { … } … } public class StoreListActivity … { @Override protected void onResume() { super.onResume(); presenter.onResume(); } @Override protected void onStop() { super.onStop(); presenter.onStop(); }
  • 28. 유용한 도구 • Dagger – 의존 주입(DI) – Activity에서 직접 프리젠터나 뷰를 생성하지 않도록 해 줌 • RxJava – 옵저버 – 콜백 인터페이스 대체 28
  • 30. 기본 구현 • 구성 요소는 동일 – 언어 특성상 인터페이스없이 구현 • 초기화 – HTML 로딩 시점에 뷰/모델/프리젠터 초기화 • 예, $.ready()에서 초기화 30
  • 31. 뷰 예시 31 functionMeasureListView(){ varpresenter; functiononSelect(idx){ presenter.selectMeasure(idx); } functioninit(){ resizeContent(); ... }; ... init(); return{ setPresenter:function(_presenter){ presenter=_presenter; }, showMeasures:function(measures){ if(measures.length==0){ $("#noData").show(); }else{ $("#hasData").show(); measureBox.setState({measures:measures,loading:false}); } }, showLoadingError:function(){console.log("error"); } }; }
  • 32. 프리젠터 예시 32 function MeasureListPresenter(view, model) { this.reloadList = function() { model.getMeasureList({ success: function(measures) { view.showMeasures(measures); }, error: function() { view.showLoadingError(); } }); }; this.selectMeasure = function(idx) { var measure = model.getMeasure(idx); view.showMeasure(measure); }; }
  • 34. 초기화 예 34 <script> $(document).ready(function() { var model = new MeasureListModel(); var view = new MeasureListView(); var presenter = new MeasureListPresenter(view, model); view.setPresenter(presenter); presenter.reloadList(); }); </script>
  • 36. 뷰와 외부 입력 • 뷰의 역할: 외부 데이터 입력 – 기능 예 • 블루투스로 데이터를 받는 기능 • GPS로 현재 좌표 받는 기능 – 이 두 기능은 뷰를 통해 전달받는 사용자 이벤트 36
  • 37. 모델 영역의 구조 • 모델에 얼마나 많은 도메인 로직이 있나? – 앱/웹에서 모델은 주로 다음의 두 가지 수행 • 서버와 통신 – 중요 로직은 서버에 존재 • 임시로 데이터 보관 – 로컬DB, 메모리 등에 보관 • 모델에 다양한 로직이 있다면 테스트 가능한 구조로 만드는 것이 중요 37
  • 38. 프리젠터 • 인터페이스와 구현체로 구분 필요 여부 – 코드 수준 테스트 대상은 주로 프리젠터와 모델 – 프리젠터가 유연해야 하는 경우 드뭄 – 모델 테스트시 프리젠터에 대한 모의 객체가 필요한 경우 없음 • 프리젠터 메서드 이름, 파라미터, 리턴 타입 – 뷰에 의존하면 안 됨 • 프리젠터 먼저 구현하기 38
  • 40. MVP • 뷰 구현, UI 로직, 모델 구현을 분리 • 복잡도 감소 – 분리에 따른 복잡도 <<< 뒤섞일 때의 복잡도 • 생산성 향상시키기 – 코드 변경이 상대적으로 쉬워짐 – UI 구현없이 사용자와의 상호작용에 대한 테스트 가능 40