본문 바로가기

Tech/iOS

[iOS]Day 32 - Pagenation

728x90

무한으로 즐기자..

페이지 말고 과자..


Pagenation 방법

Pagenation?

App을 사용한 경험이 있다면 무한 스크롤을 한 경험이 있을텐데 이럴 경우 대량의 데이터와 리소스를 분할해서 가져오는 방식이다

 

*Offset Based Pagenation

첫번째 방법은 Offset Based Pagenation이다

몇 번째 페이지에서 몇개의 데이터를 보여줄지 QueryString으로 전달해준다

서버 데이터의 변화가 적은 환경에서 사용하는 기술이다

-> 데이터를 가지고 오는 도중에 새로운 데이터가 추가 된다면 추가된 데이터가 중복으로 보일 수 있다

-> 실시간으로 게시글이 많은 웹사이트에서 3페이지를 읽고 다시 목록으로 갔을 때 페이지를 넘겼을 때 아까 봤던 3페이지의 게시글이 보이는 경험을 해봤을 것이다

대부분의 앱이 Offset Based Pagenation을 채택한다

 

*Cursor Pagenation

두번째 방법은 Cursor Pagenation이다 

Client가 가지고 있는 마지막 데이터 기준으로 다음 데이터를 조회하는 방식이다

마지막 데이터 기준이기 때문에 Offset Based Pagenation과 다르게 앞쪽에 데이터가 추가 되더라도 마지막 데이터 기준이기 때문에 데이터가 중복으로 보이지 않는다

정보값의 중간을 뛰고 얻는 것은 힘들고 휘발성이 높고 데이터 변화가 많은 환경에 적합하다


Pagenation 구현

페이지네이션 방법 1.

willdisplay 컬렉션뷰가 특정 셀을 그리려는 시점에 호출되는 메서드
마지막 셀에 사용자가 위치해있는지 명확하게 확인하기가 어려움
*권장하지 않는 방식

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {

}

페이지네이션 방법2.

UIScrollViewDelegateProtocol

테이블뷰/컬렉션뷰 스크롤뷰를 상속받고 있어서, 스크롤뷰 프로토콜 사용할 수 있음

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        //사용자가 얼마나 내려 왔는가 찍을 수 있음 스크롤 할때마다 호출됨 스크롤 아래를 의미
        //scrollView.contentSize.height
        //스크롤뷰의 contentOffset.y를 찍으면 알 수 있다
        //남아있는 뷰가 얼마 남아있지 않을때 데이터 요청
        //print(scrollView.contentOffset)
}

페이지네이션 방법 3.

용량이 큰 이미지를 다운 받아 셀에 보여주려고 하는 경우에 효과적

셀이 화면에 보이기 전에 미리 필요한 리소스를 다운받을 수 있고 필요하지 않는다면 데이터를 취소할 수 있다

3번째 페이지네이션 방법으로 실습을 해보자

//네트워크 요청할 시작 페이지 넘버
    var startPage = 1
    var totalCount = 0
extension ImageSearchViewController: UICollectionViewDataSourcePrefetching {
    
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        
        for indexPath in indexPaths {
            if imgList.count - 1 == indexPath.item && imgList.count < totalCount{
                startPage += 30
                fetchImage(query: searchBar.text!)
            }
        }
        
        print("====\(indexPaths)")
    }
    
    func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {
        print("===취소: \(indexPaths)")
    }
        
    }

첫 페이지와 전체 페이지 갯수를 선언한 후에 

Extension을 활용하여 구현중인 VC에 UICollectionViewDataSourcePrefetching을 채택한다 

 

UICollectionViewDataSourcePrefetching을 채택하면 prefetchItemsAt Method를 사용할 수 있다

User가 앱 사용시에 스크롤을 엄청 빠르게 내린다고 생각해보자 눈에 보이지 않은 데이터가 스크롤을 할 때 보이지 않으면서 내려갈텐데 

PrefetchItemsAt Method는 위에서 말한 보이지 않는 셀에 대해서는 데이터 처리가 필요하지 않아서 취소 해야하는데 이 메서드를 활용해서 네트워크 호출 횟수와 리소스를 덜 사용한다

 

구현되는 셀이 화면에 구현되기 전에 리소스를 다운 받는데 사용자가 스크롤을 내리기 전 화면에 보여지는 마지막 셀의 데이터를 체크한다

API 통신을 통해 받은 thumnail의 데이터 갯수와  indexPath의 갯수가 같은지 확인하고 마지막 페이지의 데이터가 아닌 것이 판단이  된다면 30번째까지의 데이터를 받아왔으니 30을 더해서 31번째 데이터 부터 60번째 데이터를 요청한다 (이후로 계속 데이터가 끝날 때 30씩 더해줌)

Pagenation 구현이 되는 것을 볼 수 있다