구글 Architecture에서 설명하는 모델 정의를 살펴보려고 한다.

위와 같이 구분할 수 있는데 기본적인 Model을 정의해야 Clean 코드도 적용해 볼 수 있다. 그래서 이번에 Google Architecture의 가장 기본적인 Model 정의를 살펴보겠다.

Model

구글에서 설명하는 Model은 ios viper라는 개념과 동일하다고 생각하면 될 것 같다. 원래는 Google Architecture clean 코드까지 viper 적용이라고 보이지만 viper와 유사한 형태이다. Interactor에서 Google Repository 역할을 처리하게 된다.

비슷하지만 용어도 다르고, 실제 구성이 다르다…

Google Architecture Model

구글에서 설명하고 있는 Model 정의는 아래와 같다.

  • Repository : 로컬/서버 중 어떤 데이터를 불러올지 정의하고, 메모리 캐시를 포함한다.
  • Remote data source : 서버에서 데이터를 받아온다.
  • Local data source : 로컬에서 데이터를 받아온다.

가장 기본적으로는 위와 같다. 로컬/서버에서 받아오는 데이터는 Repository에서 캐시 처리할 수 있다. 필요에 따라서 캐리를 하고, 이를 Presenter에 다시 콜백을 해주게 된다. RxJava로 구성을 하면 async / await 형태로 만들어지므로 return Observable/Flowable의 형태가 만들어질 수 있다고 한다… [RxJava는 잘 모르는 내용이다.]

그래서 가장 basic MVP는 아래의 그림을 가진다.

여기에서 Repository가 왼쪽과 같이 표현될 수 있다. Presenter와 Repository 사이의 데이터를 가공할 수 있는 Loader가 추가될 수도 있고, Clean 코드를 위한 Domain Layout이 포함될 수도 있다.

이런 Loader와 Domain Layout 정의는 Clean 코드를 위한 정의이다. 필요할 경우 추가하여 사용이 가능하다.

TODO MVP

모델의 정의는 다음과 같은 형태로 생성된다.

  • Presenter 생성하는 위치에서 Repositroy 생성
  • Presenter에서 Model(Repository) 포함(setter)
  • Presenter에서 Model(Repository) 호출
  • Model(Repository)는 Remote/Local의 데이터를 선택하고 이를 캐시
  • 데이터 호출이 완료되면 Loader 또는 Presenter에서 세팅한 Listener에 값을 전달

추가로 Loader의 정의는 아래와 같다.

Repository interface 정의

LoadImageCallback을 통해서 성공했을 대와 오류 났을 때를 구분하여 Listener을 추가한다. RxJava를 사용할 때는 다음이 필요하지 않다.

1
2
3
4
5
6
7
8
9
10
public interface ImageSource{

interface LoadImageCallback{
void onImageLoaded(List<PhotoItem> photoItem);
void onDataNotAvailable();
void onLoadFai(int code, String message);
}

void getImageItems(int page, LoadImageCallback loadImageCallback);
}

ImageSource를 상속받아서 Repository의 Remote/Local DataSource 구분을 하면 된다.

Repository

Repository은 싱글톤을 통해서 생성하면 된다. 생성자를 통해 Remote/Local DataSource 생성을 하여 사용할 수 있다. kotlin에서는 object class 생성을 통해 처리할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ImageRepository implements ImageSource{

private ImageRemoteDataSource imageRemoteDataSource;



public static ImageRepository getInstance(){
return LazyHolder.imageSampleRepository;
}

private ImageRepository(){
imageRemoteDataSource = ImageRemoteDataSource.getInstance();
}

private static class LazyHolder{
private static final ImageRepository imageSampleRepository = new ImageRepository;
}

}

Remote/Local DataSource

서버/로컬 데이터 소스를 정의할 수 있다. 여기에서는 Local SQLite/Realm DB를 사용하여 구성할 수 있고, Retrofit을 사용하여 서버 데이터를 불러올 수 이다. 역시 DataSource interface 상속을 통해서 정리하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ImageRemoteDataSource implements ImageSource {

private static ImageRemoteDataSource INSTANCE;

private final FlickrService flickrService;

private ImageRemoteDataSource() {
flickrService = RetrofitCreator.createRetrofit().create(FlickrService.class);
}

public static ImageRemoteDataSource getInstance() {
if (INSTANCE == null) {
INSTANCE = new ImageRemoteDataSource();
}

return INSTANCE;
}

@Override
public void getImageItems(int page, final LoadImageCallback loadImageCallback) {
// 생략
}
}

참고