본문 바로가기

안드로이드/JetPack

[안드로이드] Paging Library 개요

개요

페이징(Paging)은 데이터를 작게 나누어 로드하는 데 적합한 라이브러리이다. 예를 들어, 게시판에 게시글 3000개가 있는데 이를 네트워킹을 통해 한번에 로드한다면 딜레이가 매우 클 것이다. 따라서, 3000개의 라이브러리를 100개 씩 페이지 단위로 나누고 RecyclerView에 해당 아이템들이 거의 소모되기 전에 다시 다음 100개를 로드하는 방식이다.

 

UI의 PagedList에서 ViewModel, Repository를 관찰하고, 만약 보여줄 아이템이 부족해진다면 DataSource에서 다시 DB나 네트워크에 접근하여 데이터를 가져온다. 그 후 이를 관찰하던 결과가 UI에 반영된다.

 


구성요소

다음은 페이징 라이브러리의 주요 구성요소이다.

 

DataSource

데이터를 작게 나누어 불러온 다음 PagedList로 로드하는 최상위 클래스이다. 기본 DataSource는 데이터의 정렬, 삽입, 삭제, 갱신 등의 변경사항이 발생하면 다시 새로운 PagedList와 DataSouce를 생성하여 다시 처음부터 로드한다. 따라서, 변경되지 않는 데이터를 페이징한다면 단일 DataSouce를 활용하기도 한다. 만약, 데이터 변경, 당겨서 새로고침과 같은 변경사항이 생길 경우 명시적으로 invalidate()를 호출해야한다.

 

DataSouce.Factory

만약, 업데이트를 제공하는 데이터를 페이징하려면 DataSource.Factory를 만드는게 적합한 선택이다. 팩토리에서 생성된 DataSource는 데이터에 대한 변경사항이 생기면 기존 스냅숏을 무효화한다. 스냅숏이 무효화되면 create() 메서드에서 새로운 DataSource를 만든다.

 

PagedList

DataSource에서 페지이된 데이터들을 관리하는 리스트이다.

 

LivePagedListBuilder, RxPagedListBuilder

위 둘은 공통적으로 DataSource.Factory와 PagedList.Config를 생성자 매개 변수로 가지며, LiveData<PagedList> 혹은 Observable<PagedList>(,Flowable<PagedList>)를 만드는 빌더 클래스이다. 

 

PagedListAdapter

PagedList에서 페이징된 데이터를 표시하는 RecyclerView.Adapter 기반의 클래스이다. ListAdapter와 유사하여 DiffUtil.ItemCallback을 필수적으로 구현해야 하며, 데이터 요청은 submitList()를 활용한다. 

 


 

DataSouce의 종류

PositionalDataSource

주소록과 같이 로컬에 데이터가 있지만 사용자가 임의의 지점으로 이동하려는 경우 적합한 DataSource이다. 

 

RecyclerView가 초기화 되고 첫 번째 위치에서 loadInitial() 메서드가 호출된다. 이 메서드의 매개 변수인 LoadInitialParams로부터 시작 위치, 페이지 크기 및 초기에 로드할 데이터의 크기를 전달받는다. 그 이후 LoadInitialCallback.onResult() 메서드를 통해 가져온 데이터를 반환한다. 이때 해당 데이터가 시작되는 위치와 총 아이템 수를 반환할 수 있다. 

 

사용자가 스크롤하다 데이터가 부족한 것을 인식하면 loadRange()가 호출되고 매개 변수인 LoadInitialParams를 통해 누락된 데이터의 시작 위치와 페이지 크기를 전달한다. 이후 가져온 데이터는 LoadRangeCallback.onResult()를 통해 전달한다.

 

 

ItemKeyedDataSource

유니크한 아이템 키를 페이징하는 DataSource이다. 이전에 로드된 아이템의 키 값이 다음 아이템을 로드하는 데 사용된다.

위와 같이 이름순으로 정렬된 데이터가 존재할 경우, 가져온 페이지의 첫 번재 혹은 마지막 이름을 통해 이전 페이지, 다음 페이지를 요청하는 방식이다.

 

RecyclerView가 초기화되고 첫 번째 포지션에서 loadInitial() 메서드가 호출된다. 해당 메서드의 매개 변수로부터 초기 키를 얻어 데이터를 로드하고 전달한다.

 

그리고 사용자가 스크롤하여 마지막 아이템에 가까워 질 때쯤 loadAfter()가 호출되어 매개 변수로 부터 키를 얻어 다음 페이지를 로드하는데 사용한다. 만약, 스크롤을 위로 이동하면 이전 데이터를 얻기 위해 loadBefore() 콜백 메서드가 호출된다.

 

 

PageKeyedDataSource

이는 서버 사이드 API를 이용할 시 가장 일반적인 페이징 방식이다. 클라이언트는 페이징 요청을 보내고 서버는 그에 해당하는 데이터와 다음 페이지에 대한 데이터(키, 오프셋)도 응답으로 보낸다.

 

RecyclerView가 초기화되고 첫 번째 포지션에서 loadInitial() 메서드가 호출된다. 해당 메서드에서 서버에서 응답으로 받은 페이지 데이터를 LoadInitialCallback.onResult() 메서드를 통해 전달하고, 다음 페이지의 정보도 전달한다.

 

이후 사용자가 스크롤하여 마지막 아이템에 가까워 질 때쯤 loadAfter() 메서드를 호출하고 이전 요청으로 반환된 페이지 정보(키, 오프셋 등)을 통해 서버로 다음 페이지를 요청한다. 그리고 LoadAfterCallback.onResult()을 호출하여 페이지 데이터와 다음 페이지의 정보를 전달한다.

 


Reference

  • 아키텍처를 알아야 앱 개발이 보인다.