이 글은 안드로이드 공식문서를 참고하여 작성했다.

https://developer.android.com/codelabs/basic-android-kotlin-training-repository-pattern?hl=ko#0 

 

저장소 패턴  |  Android Developers

저장소 패턴을 사용하여 기존 앱에서 캐싱을 구현합니다.

developer.android.com

 

Repository Pattern 이란?

데이터 레이어를 앱의 나머지 부분에서 분리하는 디자인 패턴이다.

- 데이터 레이어는 UI와 별도로 앱의 데이터와 비지니스 로직을 처리하는 앱 부분을 나타내며 앱의 나머지 부분에서 이 데이터에 액세스할 수 있도록 일관된 API를 노출한다.

- UI가 사용자에게 정보를 제공하는 동안 데이터 레이어에는 네트워킹 코드, Room 데이터베이스, 오류 처리, 데이터를 읽거나 조작하는 코드를 포함한다.

 

뭔 말이냐... 그림을 보며 이해해보자!

데이터는 Room Data, Retorfit, Firebase 등 다양한 곳에서 데이터를 받을 수 있다. 그래서 어떤 형태로 데이터가 접근을 해도 Repository 클래스를 통해 캡슐화해서 깔끔하게 접근하겠다는 거지!!

 

즉, 데이터가 어디서 왔든지 동일한 Repository 인터페이스로 접근하겠다는 것이다!!!


코드 예제

작업 1. 저장소 만들기

- 오프라인 캐시를 관리할 저장소를 만들어보자!!

- 베이스 코드는 위의 안드로이드 공홈에서 다운로드 받자.

 

저장소 추가 및 데이터베이스에서 데이터 검색

VideosRepository.kt

class VideosRepository(private val database:VideosDatabase){

    // LiveData 객체를 만들어 데이터베이스에서 동영상 재생목록을 읽는다.
    val videos: LiveData<List<DevByteVideo>> = Transformations.map(database.videoDao.getVideos()){
        it.asDomainModel()
    }
    suspend fun refreshVideos(){
        // 코루틴 컨텍스트를 Dispatchers.IO로 전환하여 네트워크 및 데이터베이스 작업을 실행
        withContext(Dispatchers.IO){
            // 네트워크에서 재생목록을 가져온 후 재생목록을 RoomDB에 저장
            val playlist = DevByteNetwork.devbytes.getPlaylist()
            // insertAll() DAO 메소드를 호출하여 네트워크에서 검색된 재생목록을 전달
            // asDatabaseModel() 확장 함수를 사용하여 재생목록을 데이터베이스 객체에 매핑
            database.videoDao.insertAll(playlist.asDatabaseModel())
        }
    }
}

- Retrofit 서비스 인스턴스인 DevByteNetwork를 사용해 playlist를 네트워크에서 가져온다.

- 재생목록을 데이터베이스에 저장한다.

- videos라고 LiveData 객체를 만들어 데이터베이스에서 재생목록을 읽는다.

 

 

작업 2. 새로고침 전략을 사용하여 저장소 통합

- 저장소를 ViewModel과 통합

- 네트워크에서 직접 가져오지 않고 Room 데이터베이스의 동영상 재생목록을 표시

 

DevByteViewModel.kt

private val videosRepository = VideosRepository(getDatabase(application))

// Network에서 부터 데이터를 가져오던 것에서 Repository에서 가져오게 변경
private fun refreshDataFromRepository() = viewModelScope.launch {
    viewModelScope.launch {
        try{
            videosRepository.refreshVideos()
            _eventNetworkError.value = false
            _isNetworkErrorShown.value = false
        }catch (networkError:IOException){
            if(playlist.value.isNullOrEmpty())
                _eventNetworkError.value=true
        }
    }
}

 

- 네트워크에서 데이터를 받아오던 코드를 위와 같이 Repository에서 받아오게끔 수정한다.

- 한 번 실행 후 비행기 모드로 설정해서 앱을 다시 실행하면 오프라인 캐시에서 가져와 에러 없이 재생목록을 가져올 수 있다.

+ Recent posts