이번 글에서는 Clean Architecture에서 Paging 라이브러리를 사용할 경우 의존성을 어떤 식으로 관리해야 할지에 대해 다뤄보겠습니다.
프로젝트 구조
제가 현재 진행 중인 개인 프로젝트는 Clean Architecture + Multi module로 구성되어 있습니다.
위의 사진과 같이 Clean Architecture의 data, domain, presentation 계층에 맞게 총 3개의 모듈로 나누어져 있으며, data -> domain, presentation -> domain의 의존 관계를 가지고 있습니다.
또한 data와 presentation 모듈은 안드로이드 라이브러리로 되어 있고, domain 모듈은 안드로이드에 대한 의존성이 없는 Kotlin 라이브러리 되어 있습니다.
Clean Architecture와 Multi module에 대한 자세한 내용은 이 글을 참고해주세요.
문제점
프로젝트를 진행하며 페이징을 사용해야 하는 경우가 생겼습니다.
구글의 Paging 라이브러리 공식 문서에는 PagingSource를 Repository에서 생성한 뒤, Pager를 통해 PagingData를 가져오게끔 아키텍처가 되어 있습니다. 이를 제 프로젝트에 적용한다고 하면, PagingSource는 data 모듈에서 구현한 뒤, domain 모듈의 interface를 통해 presentation 모듈의 ViewModel로 값을 넘겨주게 됩니다.
implementation "androidx.paging:paging-runtime:$paging_version"
문제는 Paging 라이브러리의 의존성을 추가하는 과정에서 생겼습니다. 앞서 설명했듯이 domain 모듈은 순수 Kotlin 코드로만 되어 있기 때문에 안드로이드에 대한 의존성을 추가할 수 없습니다.
Could not resolve androidx.paging:paging-runtime-ktx:3.0.0.
Possible solution:
- Declare repository providing the artifact, see the documentation at https://docs.gradle.org/current/userguide/declaring_repositories.html
domain 모듈의 Paging 의존성을 추가하려고 하면 위의 오류가 발생하게 됩니다. 하지만 domain 계층의 interface를 통해 PagingData를 반환해주기 위해서는 Paging에 대한 의존성을 가지고 있어야 합니다.
해결 방법
이를 해결하기 위해 여러 가지 방법을 생각해봤습니다.
1. domain 모듈을 안드로이드 라이브러리로 만든다.
클린 아키텍처를 공부하며 여러 자료를 찾아봤을 때 Room에서 LiveData를 반환하는 경우에 domain 모듈을 안드로이드 모듈로 만드는 경우가 있었습니다. 이와 비슷하게 페이징을 사용하기 위해 안드로이드 모듈로 변경해볼까 생각했었지만, 클린 아키텍처에 맞지 않는 구성이라고 생각하여 다른 방법을 찾아보게 되었습니다.
2. PagingSource를 presentation 모듈에서 구현한다.
domain 계층에서 Paging을 사용하지 않기 위해 PagingSource 자체를 presentation 모듈에서 구현하는 방법도 있습니다. 이 경우엔 domain 모듈의 repository interface에 query, offset 등의 인자를 넘겨서 데이터를 반환받은 뒤, presentation 모듈에서 PagingSource를 구현합니다. 구현한 PagingSource는 ViewModel로 넘겨져서 Pager를 통해 사용할 수 있습니다.
하지만 PagingSource는 엄연히 데이터를 가져오는 동작을 하기 때문에 data 계층에 포함되는 것이 맞다고 생각했고, Paging 공식 문서에서 제공하는 아키텍처에도 맞지 않는 방법이라고 판단했습니다. 구글에서 권장하는 아키텍처를 따르고 싶기도 했습니다.
고민에 고민을 거듭하다 다소 허무한 방법으로 해결할 수 있었습니다. 문제의 원인은 domain 계층에 Paging에 대한 의존성을 추가하지 못하기 때문이었고, 의존성을 추가할 수 있는 방법을 찾아보았습니다.
// alternatively - without Android dependencies for tests
implementation "androidx.paging:paging-common:$paging_version"
구글 Paging 라이브러리 공식 문서에 안드로이드에 대한 의존성이 없이도 가져올 수 있는 방법이 있었습니다. 'for tests'라는 주석만 보고 유심히 보지 않아서 눈에 들어오지 않았습니다. 바로 프로젝트로 돌아와서 domain 모듈에 의존성을 추가했고, 성공적으로 sync 되는 것을 확인할 수 있었습니다.
참고
https://developer.android.com/topic/libraries/architecture/paging/v3-overview
'Android' 카테고리의 다른 글
[Android] ViewModel에서 실행한 이벤트 기다리기 (6) | 2022.06.09 |
---|---|
[Android] MVVM 패턴과 AAC에서의 ViewModel (8) | 2021.10.06 |
[Android] Gson을 이용한 Room에 다양한 타입의 데이터 저장하기 (0) | 2021.09.24 |
[Android] 스켈레톤 로딩 화면 구현하기 - Facebook shimmer library (0) | 2021.09.13 |
[Android] viewModelScope.launch() 간단하게 바꿔보기 (0) | 2021.09.11 |