Nuke Olaf - Log Store

[MVP] 안드로이드에 mvp 패턴 적용하기(3) - Model 정의 본문

ComputerScience/[디자인 패턴]

[MVP] 안드로이드에 mvp 패턴 적용하기(3) - Model 정의

NukeOlaf 2020. 3. 10. 05:50
<안드로이드에 mvp 패턴 적용하기 시리즈>
안드로이드에 mvp 패턴 적용하기(1) mvp 패턴이란?
안드로이드에 mvp 패턴 적용하기(2) Contract 작성
안드로이드에 mvp 패턴 적용하기(3) Model 정의
안드로이드에 mvp 패턴 적용하기(4) Presenter 만들기
안드로이드에 mvp 패턴 적용하기(5) Activity 에 View 구현

이전의 포스팅에서 아래의 화면을 MVP 패턴으로 구현하기 위해 View 와 Presenter 의 기능을 정의한 Contract 인터페이스를 작성하는 방법에 대해 알아보았다. 이번에는 이 화면에서 사용할 Model 을 구현하는 방법에 대해 생각해보자.

 

1. Model 이란?

 basic MVP 패턴 도식화

mvp 패턴에서의 Model 이란, 쉽게 말해서 Data 그 자체와 Data 를 저장하고, 가져오고, 관리하는 로직을 포함한 것이다.

구글의 architecture-sample 예제에서는 이 Model 에 Repository 패턴을 적용하여 Model 을 정의한다.

아래 그림의 Repository 는 loacl 과 remote 중 어느 곳의 Data Source 를 사용할지를 판단하고 접근하는 곳이다. 만약 local 또는 remote 데이터에 대한 캐싱이 필요하다면, 캐시 처리 또한 Repository 에서 진행한다. Local Data Source 는 말 그대로 안드로이드 기기에 저장된 데이터를 불러온다. Remote Data Source 는 서버를 통해 데이터를 불러온다.

 

2. DataSource interface 작성하기

EditText 로 입력된 이름과 이메일 정보를 
{ "name" : "olaf", "email" : "olaf@naver.com" } 
이런 형식의 JSONObject 로 관리할 것이라고 이전의 포스팅에서 얘기했었다.

이 info 데이터를 불러올때, LoadInfoCallback 을 사용하여 성공했을때와 오류가 났을 때를 구분하여 Listener 를 추가해 주어야 한다. 그래서 이와 관련된 콜백함수와 get 함수를 정의한 InfoDataSource 인터페이스를 작성하고, 이를 Repository 와 local/remote Data Source 에 implement 하여 사용한다.

interface InfoDataSource {

    interface LoadInfoCallback {
        fun onInfoLoaded(info: JSONObject)
        fun onDataNotAvailable()
    }

    fun getInfo(callback: LoadInfoCallback)
    fun saveInfo(info: JSONObject)
}

 

3. Local/Remote DataSource 작성하기

여기서는 remote data source 는 사용하지 않고, Shared Preference 를 사용하여 local remote data source 만 정의하여 사용할 것이다. 위에서 작성한 InfoDataSource 인터페이스를 implement 하여 사용한다.

InfoDataSource 에 있었던 getInfo() 함수와 saveInfo() 함수를 local Data Source 에 맞게 작성해준다.

class InfoLocalDataSource(context: Context) : InfoDataSource{

    private val sharedPreferences = context.getSharedPreferences("info", Context.MODE_PRIVATE)
    private val editor = sharedPreferences.edit()

    override fun getInfo(callback: InfoDataSource.LoadInfoCallback) {
        var info = sharedPreferences.getString("info", null)
        if(info != null) {
        	callback.onInfoLoaded(JSONObject(info))
        }else {
        	callback.onDataNotAvailable()
        }
    }
    
    override fun saveInfo(info: JSONObject) {
    	editor.putString("info", info.toString())
        editor.commit()
    }
}

 

4. Repository 작성하기

Repository 는 보통은 object class 를 사용하여 싱글톤으로 생성한다. 여기서는 싱글톤으로 만들지 않고 Repository 를 작성했다. Repository 또한 위에서 정의했던 DataSource 인터페이스를 implement 하여 구현해준다.

Repository 생성자를 통해 Local/Remote DataSource 를 생성하여 사용할 수도 있다.

class InfoRepository(context: Context) : InfoDataSource{

    private val infoLocalDataSource = InfoLocalDataSource(context)

    override fun getInfo(callback: InfoDataSource.LoadInfoCallback) {
        infoLocalDataSource.getInfo(callback)
    }
    
    override fun saveInfo(info: JSONObject) {
    	infoLocalDataSource.saveInfo(info)
    }
}

이렇게 DataSource 인터페이스와, Local DataSource, Repository 를 작성하여 MVP 의 Model 을 만들어보았다. 이제 만들어진 Model 을 토대로 Presenter 와 View 를 만들고, 이들을 연결하여 사용하면 된다. 다음 포스팅에서는 이제 Presenter 를 만들어볼 것이다.

Comments