반응형

<언어의 장벽 없이 Pagination에 대한 설명을 하지만, Flutter 언어로 구현된 방법을 예시로 들 예정입니다.>

 

Flutter 강의를 듣다보면서 Pagination 많이 들었고 어떤 건지는 알고 있는건데 라고 생각하며 들어봤다.

 

역시 제가 알고 있는 것과 마찬가지였지만, 강의 내에서 강의자 분이 강의 해주신 부분에 제가

 

예전에 회사에서 구현하였던 방법이랑 큰 틀은 비슷하였으나, 세부적으로 봤을 때는 다른 부분이 있었다.

 

많은 분들은 Pagination ? 이게 무슨 소리지? 하겠지만, 많은 사람들이 실제로 어플을 사용하다보면 

 

거기 내에서도 많이 겪어본 부분들이라 생각됩니다.

 

Pagination 이란 결국 많은 데이터를 부분적으로 나눠서 불러오는 기술인데,

 

이 부분에 대해서는 클라이언트 부분과 서버 부분에서 큰 차이 없이 사용하고 있습니다.

 

어떤 게시글을 예로 들어보면, 처음에는 게시물이 몇개 없는 경우에는 데이터를 불러와서 렌더링 해주는 과정에서 큰 문제가 없어 보일 수도 있습니다.

 

10개? 20개? 뭐 그냥 불러오지! 라는 생각이 들 수도 있어요.

 

하지만, 게시물이란 계속하여 끊임없이 쌓이게 됩니다. 그러면 추후에 게시물이 5000개가 되었을 때,

 

그것을 한 번에 불러오면 어떻게 될까요?

 

엄청난 로딩 시간이 걸릴 수도 있습니다. 가끔 어플이나 사이트를 보면 로딩 화면 뱅글뱅글 돌아다니잖아요.

 

그 부분이 오래 걸리면 엇? 렉인가? 라는 생각이 들도록 해주죠.

 

그러면 이것을 어떻게 하면 효율적으로 나눠보내 줄 수 있을까? 라고 생각하겠죠.

 

가장 간단한 방법이 나눠서 보내주는거란 결과에 도달하게 됩니다.

 

정리하자면 쿼리에 해당되는 모든 데이터를 한 번에 다 불러오지 않고 부분적으로 쪼개어 불러옵니다.

 

어떤 쇼핑몰에 들어갔을 때, 상품 검색 화면에 들어가게 되면 수많은 상품정보들이 클라이언트에서 보여주게 됩니다.

 

그러면 사용자가 처음 그 화면에 들어갔을 때, 보여지는 부분은 어느정도 정해진 경우가 많습니다.

 

수천~수억개의 데이터를 한 번에 유저가 받게 된다면 로딩화면이 길어질 것이니깐요.

 

즉, FrontEnd 관점에서는 서버에서 데이터를 받아오는데, 오래 걸리기 때문에 데이터 렌더링 하는데 있어 오래 걸릴 수 밖에 없고, 유저가 그 부분을 볼 때, 오래 걸릴수 밖에 없습니다.

 

BackEnd 관점에서는 DataBase 부분에 저장된 데이터를 불러오는데 있어 많은 시간이 걸립니다.

 

그렇게 되면 프론트와 백엔드 둘다 오래 걸릴 수 밖에 없는거죠.

 

그리고 또한 현시점에서는 클라우드 서비스를 많이 사용하고 있습니다. (ex: AWS, Azure 등)

 

매번 데이터를 Call하여 가져오는데 있어 비용처리가 많이 든다는거죠. 돈이든 시간이든 ^_^..

 

그리고 수억개의 데이터를 한 번에 처리하려고 하면 메모리가 과부하되어 문제가 되거나 오랜 시간이 걸리게 되는거죠.

 

고로 옛날에는 Page Based Pagination을 많이 사용하였을 때, 한 Page 당 20, 30개 등씩 나눠서 보여주게 되었습니다.

 

이 방법이 Pagination 기법 중 하나인거죠. 데이터 갯수와 몇번째 페이지 데이터를 가져올 것인지 등에 대해 요청하면 그것과 관련된 정보들을 받게 되는거죠.

 

물론 데이터를 추가되거나 삭제될 경우 저장되는 데이터가 누락되거나 중복이 될 수도 있다는 단점이 있죠.

 

갑작스럽게 데이터가 추가되거나 삭제되면 원래 있던 게시물들이 페이지가 뒤로 밀리거나 앞으로 당겨져 오는거죠.

 

요즘에는 대다수 어플들 내에서 보면 Cursor Based Pagination 을 사용하고 있습니다.

 

즉, 스크롤을 통하여 이미 불러와있는 게시글들 밑으로 가면 다음 게시물들이 보여지는 형태이죠.

 

그리고 맨 위로 가면 가장 위에 업데이트된 게시물들을 가져옵니다.

 

프론트에서 백엔드로 가장 마지막 데이터의 기준값(uid와 같은)과 몇개의 데이터를 가져올지에 대해 요청을 하고 서버에서는 그 요청한 기준값을 시작으로 데이터를 몇개 가져올지 데이터베이스에 요청하여 정보를 가져와 프론트로 넘겨줍니다.

 

이 부분에 있어 한 번에 불러오는 부분을 불러오는데 제한을 둠으로써 프론트엔드쪽과 백엔드 관점에서 부하가 걸리는 것을 막게 되는거죠.

 

@JsonSerializable(genericArgumentFactories: true)
class CursorPagination<T> {
  final CursorPaginationMeta meta;
  final List<T> data;

  CursorPagination({required this.meta, required this.data});

  factory CursorPagination.fromJson(
          Map<String, dynamic> json, T Function(Object? json) fromJsonT) =>
      _$CursorPaginationFromJson(json, fromJsonT);
}

@JsonSerializable()
class CursorPaginationMeta {
  final int count;
  final bool hasMore;

  CursorPaginationMeta({required this.count, required this.hasMore});

  factory CursorPaginationMeta.fromJson(Map<String, dynamic> json) =>
      _$CursorPaginationMetaFromJson(json);
}

강의에서 보았을 때, 이런식으로 meta class를 두어 몇개의 데이터를 주는지(count)와 더 가져올 데이터 존재하는지 (hasMore)를 두어 관리하였습니다.

 

아마 강의 내에서는 가져오는 데이터 양이 많지 않아 이렇게 된것 같습니다.

 

제가 회사에서 구매내역 관련하여 Cursor Based Pagination을 구현하였을 때는 log uid(기준값)과 count로 관리를 해주었는데, 

 

이렇게 작성했던 이유는 구매내역에 사용자마다 얼마나 많은 데이터를 가져오는지 파악하기 힘들었다는겁니다.

 

그래서 가장 최신의 데이터 같은 경우는 log uid가 가장 큰 값이기 때문에 서버에서 last uid를 받았고 그것 이하의 데이터 중에서 특정 count 만큼 limit을 걸어 데이터를 가져왔습니다.

 

그리고 더 이상 데이터를 가져 올 수 없는 경우에는 log uid = -1로 처리하였습니다.

 

굳이 bool 값을 하나 더 넣어서 데이터 낭비를 하고 싶지 않았던 부분이 컸던것 같습니다.

 

근데 생각해보면 굳이 그렇게 할 필요 없이, 이미 프론트에서 데이터를 log uid를 알고 있기 때문에

 

서버에서는 저런 식으로 강의해서 했던 것으로 구현하면 좀 더 가독성 있지 않았을까 라는 생각이 들긴합니다.

 

log uid 같은 경우에는 결과적으로 받아오고자 하는 데이터에 내장되어 있다면 서버에서는 log uid = -1로 처리했던 부분을

 

좀 더 가독성 있게 만들 수 있지 않았을까 라고요.

 

반응형

+ Recent posts