Pagination?? 뭔데??

0
post-thumbnail

1. Pagination

  • Pagination : 보여줄 데이터는 많은데, 한 번에 다 보여줄 수 없을때 사용할 수 있는 기능이다.
    Paging이라고도 불린다.
    예를 들면, 데이터베이스의 10000개의 상품 아이템이 있을때 한 번에 만개를 돌려주는게 아니라 0번부터 49번까지 50개씩 돌려주는 것을 의미한다고 한다. 이렇게 50번부터 99번까지, 100번부터 149번까지 돌려준다. 따라서, 네트워크의 낭비를 막고 빠른 응답을 기대할 수 있게 한다.
https://todo.com/todos?offset=5&limit=30 // 페이지는 5번, 갯수는 30개!
  • 위와 같이 전통적인 페이지네이션 방식을 써왔다고 한다. offset = 페이지위치, limit = 돌려줄 갯수를 의미한다.

2. 종류

  • 오프셋 기반 페이지네이션(Offset based Pagination)
    1. DB의 Offset쿼리와 Limit 쿼리를 사용
    1. 페이지 단위로 구분
  • 커서 기반 페이지네이션(Cursor based Pagination)
    1. Cursor의 개념을 사용
    1. 사용자에게 응답해준 마지막의 데이터가 Cursor가 된다.
    2. Cursor를 기준으로 Cursor다음 n개의 데이터를 응답한다.

2-1) 오프셋 기반 페이지네이션(Offset based Pagination)

  • 첫번째 페이지
/*MySQL*/

SELECT ID, CONTENT, CREATION_DATE
FROM POST
ORDER BY CREATION_DATE DESC
LIMIT 5

/*MONGO*/

db.posts.find().limit(5)
  • LIMIT는 제한을 뜻한다. 즉, 최대 5개의 값만 출력이 된다.
  • 첫번째 페이지 이후
/*MySQL*/

SELECT ID, CONTENT, CREATION_DATE
FROM POST
ORDER BY CREATION_DATE DESC
LIMIT 5
OFFSET ((page-1) x limit)

/*MONGO*/

db.posts.find().skip(((page-1) x limit)).limit(5)
  • 여기서는 Offset,skip 쿼리문을 사용하였다.
  • 해당 쿼리들은 건너뛰라는 의미가 있다. Offset과 skip은 몇번째 페이지에 따라서 값이 증가 한다.
    ex) 4페이지 = ((4-1)x5)15, 6페이지 = ((6-1)x5)25 이런식으로
    즉 4페이지면 15 건너뛰고 16 5개를 보여줘라 라는 의미이다.
  • 오프셋 페이지네이션은 단점이 존재한다 => 데이터 중복 issue

  • 1페이지를 요청하면 날짜를 내림차순(최신순)으로 정렬을 하고 1~5번째 데이터를 응답해준다.

  • 하지만, 2페이지를 요청하였을때 그 사이 5개의 새로운 게시물(id6 ~ id10)이 생기면, 상황이 벌어진다.
  • DB에선 쿼리가 Offset 5또는 skip(5)로 되어있으니 5개를 건너뛰고, 6번째인 id1~id5를 또다시 응답해줄 것이다.
  • 또한, 극단적으로 페이지의 크기가 엄청 커지게 되면 offset이나 skip에 매우 큰 숫자가 들어가게 된다.
  • 마무리 :
    1. 데이터의 생성이 거의 없음
    1. 중복된 데이터를 노출해도 상관없음
    2. 데이터의 양이 많지 않아 퍼포먼스적 이슈를 고려할 필요가 없음
  • 이럴때 , 오프셋 페이지네이션을 사용해도 무방하다고 한다.

2-2) 커서 페이지네이션(Cursor Pagination)

  • 첫번째 페이지
/*MySQL*/

SELECT ID, CONTENT, CREATION_DATE
FROM POST
ORDER BY CREATION_DATE DESC
LIMIT 5

/*MONGO*/

db.posts.find().limit(5)
  • 첫번째 페이지 이후
/*MySQL*/

SELECT ID, CONTENT, CREATION_DATE
FROM POST
WHERE CREATION_DATE < (CreationDate Cursor)
    OR (CREATION_DATE = (CreationDate Cursor) AND id>(Id Cursor))
ORDER BY CREATION_DATE DESC, ID ASC
LIMIT 5

/*MONGO*/

db.posts
.find(
'CREATION_DATE' : {'$lt' : (CreationDate Cursor)}
{ $or : [ { $and : [{'CREATION_DATE' : (CreationDate Cursor)},{'id' : {'$gt' : (Id Cursor)}}]}]}
).limit(5)
  • 유저에게 마지막으로 응답했던 데이터 중에서 마지막 데이터가 Cursor가 된다. 여기서 Cursor는 책갈피 같은 개념으로 보면 된다.
  • 마지막 data의 CreationDate와 id가 각각의 cursor가 된다.
  • OR절은 만약 정확히 같은 시간에 여러개의 게시글이 생겼을 때 1개의 게시들 제외하고 나머지는 무시될수 있기 때문에 OR절을 활용한다.

  • 첫번째 페이지 오프셋

  • 아무리 새로운 데이터가 생성이 되도 Cursor기반이므로 중복되지 않는다.
  • 위의 쿼리대로 생성시간이 6보다 작거나 생성시간이 6이랑 같고 id가 5보다 큰 값만 검색한다.
    위 같은 이유로 OR절을 쓴다.
  • Cursor기반은 페이지 개념이 아니고 인스타, 페이스북 같은 스크롤 개념이다. 따라서, 한번에 다 조회해서 보여 주게 되었을 때 클라이언트가 10번째 12번째 게시물만 보고 사용을 종료하면 네트워크의 낭비가 심하다. 또, 속도도 굉장히 느리다. 그래서 위와 같은 기술이 나왔다.

마무리

=> 솔직히 처음 보는 개념이라 잘 이해가 되지 않았지만, 내가 사용자라 생각하고 보면 이해가 편한거 같다.

profile
끝날때 까지 끝난게 아니야. 결국 내가 이겨!

0개의 댓글