본문 바로가기

iOS

Pagenation

728x90

페이지네이션 (a.k.a 무한스크롤)이 무엇이고 어떻게 구현할 수 있는지 알아보자.

 

Pagenation

대량의 데이터와 리소스를 분할해서 가져오는 방식으로 주로 서버의 데이터/리소스를 다룰 때 사용한다.

(ex, 쇼핑몰의 경우 서버가 갖고 있는 제품들은 엄청 많지만 사용자가 해당 페이지에서 제품들의 정보를 다 볼거라는 보장이 없기 때문에 페이지네이션을 통해 데이터를 관리한다.)

주로 사용자의 스크롤 시점을 기반으로 페이지네이션 기능을 구현한다. 

 

 

Pagenation 방법

Offset Based Pagenation

오프셋페이지네이션의 종류는 크게 두 가지이다.

1. PageNumber 

2. LimitOffset 

 

몇 번째 페이지에서 몇 개의 데이터를 보여줄 지에 대한 정보를 쿼리 스트링으로 전달한다.

let url = Constant.EndPoint.imageSearchURL + "query=\(keywordData)&display=30&start=\(startPage)"

 

이 방법의 경우, 페이지 단위로 서버에 정보를 요청하는 사이에 서버의 데이터가 변하게 된다면, 중복 데이터가 노출될 수 있다.

그렇기 때문에 서버의 데이터 변하가 적은 구조인 경우에 적합하다.

ex, 쇼핑몰 / 게시판 (트위터, 인스타그램과 같은 실시간으로 변화가 빠른 서비스에는 권장하지 않는다.)

 

Cursor Pagenation

클라이언트가 갖고 있는 마지막 데이터를 기준으로 다음 데이터를 조회하는 방식 

 

사용자가 조회한 시점 이후에 최신 데이터가 서버에 추가 된 경우, 최신 데이터를 페이지네이션으로 조회하기 어려울 수 있다.

현재 페이지를 기준으로 전/후의 데이터를 호출하는 방식이므로 정보를 건너뛰고 중간 페이지에 대한 값을 얻기가 힘들다. 

(ex, 총 결과가 100개일 경우 display가 10개씩 될 때 11번째 게시글을 보고 있다면? 70번째 게시글을 보기 어렵다.)

 

 

Pagenation 구현 

구현하는 방식은 크게 세 가지가 있다.

앞서 말한 것과 같이 대부분 사용자가 스크롤한 시점을 기준으로 데이터를 받아오기 때문에 스크롤을 활용하는 경우가 많다.

 

UICollectionView Protocol - willDisplay 

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

}

컬렉션 뷰(or 테이블 뷰)가 특정 셀을 그리려는 시점에 호출되는 메서드

-> 마지막 셀에 사용자가 위치했는지 확인하기가 어렵기 때문에 권장하는 방식은 아니다.

 

UICollectionView Protocol - UIScrollView Protocol 

컬렉션 뷰(or 테이블 뷰)는 스크롤 뷰를 상속받고 있기 때문에 스크롤 뷰의 프로토콜을 사용할 수 있다.

컨텐츠 뷰의 offset을 사용하면 사용자가 어디까지 스크롤 했는 지 알 수 있으므로 이를 바탕으로 데이터를 받아온다.

 

func scrollViewDidScroll(_ scrollView: UIScrollView) {
	print(scrollView.contentOffset)
}

 

UICollectionView Protocol - UICollectionViewDataSourcePrefetching

페이지네이션이 효과적으로 사용되는 경우는 용량이 큰 데이터를 나눠서 가져오는 것에 있다.

 

세번째 방식의 경우 용량이 큰 이미지를 다운 받아서 셀에 보여주려고 할 때 효과적이다.

셀이 화면에 보이기 전에 미리 필요한 리소스를 받을 수 있고, 필요하지 않은 경우 취소도 가능하다. 

 

iOS10 이사부터 사용이 가능하고, 스크롤 성능 향상된다는 장점이 있다.

 

extension ImageSearchViewController: UICollectionViewDataSourcePrefetching {
    // 셀이 화면에 보이기 직전에 필요한 리소스를 미리 다운 받는 기능
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        for indexPath in indexPaths {
            if list.count - 1 == indexPath.item && list.count < totalCount {
                startPage += 30
                fetchImage(keyword: imageSearchBar.text!)
            }
        }
    }
    
    // 취소 : 직접 취소하는 기능 구현해야 함
    func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {
        print("========= \(indexPaths) =========")
    }
}

페이지네이션을 구현할 때 주의할 점은 서버로부터 받은 정보를 받을 때 새롭게 받아오는 것이 아니라 쌓여야 한다는 것이다.

 

주로 배열을 통해서 서버에서 받은 정보를 저장하고 이를 기반으로 화면에 알맞게 가공해서 보여주는 경우가 많을 텐데,

배열에 받을 때 매번 새롭게 데이터를 remove하고 받는 것이 아니라, (아예 새롭게 데이터를 받는 경우가 아니라면) append를 통해 정보를 다뤄야 한다.

self.list.append(contentsOf: list)

 

'iOS' 카테고리의 다른 글

TMDB - GET / Pagenation  (0) 2022.08.08
APIManager  (1) 2022.08.08
.gitignore  (0) 2022.08.05
프로토콜 - Basic To Advanced  (0) 2022.08.03
Network - 가볍게  (0) 2022.08.02