이번 포스팅에서는 Paging 라이브러리에 대해 알아보도록 하겠습니다.
Paging 혹은 Pagination은 하나의 문서를 분리된 페이지로 나누는 것인데요, 아날로그 및 디지털 출판을 하는 모든 곳에서 사용되는 기술입니다. 웹이나 데이터베이스를 다루는 경우에는 취급해야 하는 데이터가 너무 클 때 그걸 작은 단위로 쪼개어 사용하는 곳에 페이징 개념이 적용되고 있습니다.
예를들어 구글에서 android를 검색하면 수십억개의 결과가 검색되지만, 첫번째 페이지에 표시되는 건 단지 10건 뿐이죠. 유저가 검색했다고 수십억개의 결과를 한번에 전달한다면 엄청난 트래픽과 자원낭비가 발생할 테니 검색결과 데이터를 10건씩 페이징하여 유저에게 보여주는 것입니다.
이렇듯 유용한 페이징 기술이지만 직접 구현하려고 하면 여러가지로 어려운 점이 많기 때문에, 구글에서는 안드로이드에서 다루는 데이터에 손쉽게 페이징을 적용할 수 있도록 Paging 라이브러리를 발표했습니다. 페이징을 사용하면 로컬 DB나 네트워크에서 받아온 데이터를 페이징하여 보여줄 수 있습니다.
Jetpack 구성요소인 Paging은 Android App Achitecture(AAA)하에서 사용할 수 있게 설계되었고, 그림과 같이 Repository, ViewModel, UI 세 층의 레이어에 관여하게 됩니다.
그럼 각 구성요소의 의미에 대해 알아보겠습니다.
PagingSource : 데이터 소스와 그 소스에서 데이터를 검색하는 방법을 정의합니다.
RemoteMediator : 로컬 데이터베이스에 네트워크 데이터를 캐시하는 동작을 관리합니다.
Pager : Repository에서 정의한 PagingSource와 PagingConfig를 생성자로 받아 PagingData를 반환하는 API를 제공합니다.
PagingData : Pager에 의해 페이징 된 데이터를 담는 컨테이너입니다.
예를들어 로컬 DB에 페이징을 적용할 경우의 스키마는 다음과 같습니다.

Repository의 개별 데이터가 PagingSource 로 변환돼 Pager에 전달됩니다. Pager는 PagingConfig에 정해진 크기대로 PagingSource를 묶어서 PagingData라는 덩어리로 만들어줍니다. 그리고 PagingDataAdapter를 통해 이 PagingData를 RecyclerView에 표시하게 되는 것입니다.
네트워크 연결이 불안정하거나 사용자가 오프라인 상태일 때는 API 응답을 정상적으로 받아올 수 없습니다. 이런 상황을 대응하는 방법 중 하나는 로컬 데이터베이스에 캐시를 만들어 표시하는데 사용하는 것인데요, RemoteMediator가 바로 그러한 역할을 하는 모듈입니다. RemoteMediator는 네트워크 응답을 Room DB에 캐시하고, 앱이 캐시된 데이터를 모두 사용한 경우 새로운 네트워크 요청을 보냅니다. 로컬 캐시인 Room DB를 단일 진실 공급원(Single source of truth)로 제공하며, RemoteMediator는 데이터를 표시하는데에는 관여하지 않습니다.
이 파트에서는 데이터 레이어의 응답에 Paging을 적용하는 법과 Paging으로 에러를 처리하는 법에 대해 알아보도록 하겠습니다. RemoteMediator는 아직 시험개발중인 API이기 때문에 이 강의에서는 다루지 않을 것입니다.