My Boundary As Much As I Experienced

express로 페이지네이션 구현하기 본문

BackEnd/Node.js

express로 페이지네이션 구현하기

Bumang 2024. 8. 3. 17:21

전통적인 방법

한 페이지에 몇 개의 글을 보여줄 것인가? 만약 다섯개라고 한다면

1, 2, 3, 4, 5, ... 페이지 번호에 -1을 하고 5를 곱한 것을 skip 시작점으로,

그리고 추가적으로 보여줄 양을 limit량으로 설정하면 된다.

이걸 toArray로 묶어서 가져오면 된다. 끝이다..

 

클라이언트가 원하는 페이지 번호를 패러미터로 보내면 이를 반영해서 보여주면 된다.

app.get("/list/:id", async (req, res) => {
  const col = db.collection("post");
  // skip은 성능이 좋지않다.
  const doc = await col
    .find()
    .skip(5 * (req.params.id - 1))
    .limit(5)
    .toArray();

  res.render("list.ejs", { doc: doc });
});

 

이 방식의 장점은 직관적이고 쉽다. 그리고 가장 많이 쓰는 방법이라고 한다.

그러나 skip메소드는 꽤 성능이 안 좋아서 10,000번째 글까지 가면 다음페이지 조회가 느려진다고 한다.

 

성능이 좀 더 좋은 다른 방법

그나마 좀 더 성능이 좋은 find메소드를 사용하는 것이다. mongoDB의 id는 연산자 비교가 가능하다.

예를 들어 $gt(greater than)같은 것들..

 

프론트에서 마지막 글의 id를 보내라하고 그 다음 글 5개를 보내는 방식이다.

그러나 이건 인피니티 스크롤, 더 보기 등에는 쓰일 수 있지만,

실제 넘버링이 된 페이지네이션을 만들기에는 무리가 있다.

다음 5개 글을 불러오는 것이지 '72페이지의 글을 보기'는 불가능한 방식이다.

await db.collection('post').find({_id : {$gt : 방금본 마지막게시물_id}}).limit(5).toArray()

 

최종 api:

app.get('/list/next/:id', async (요청, 응답) => {
  let result = await db.collection('post').find({_id : {$gt : new ObjectId(요청.params.id) }}).limit(5)
  응답.render('list.ejs', { 글목록 : result })
})


장점 : 매우 빠르다. 원래 _id 기준으로 뭔가 찾는건 찾는건 DB가 가장 빠르게 하는 작업이다.

단점 : 페이지네이션 버튼을 다음버튼으로 바꿔야한다.

 

 

두 가지 장점을 혼합하는 방법

만약 두 가지 장점을 모두 흡수해서 id조회로 빠르게 글을 찾으면서도 특정 페이지로 이동도 쉽게 하려면?

id를 정수로 만들어라. 그리고 1000번째 글 보여달라하면 아래처럼 하면 되는 것이다.

(mongoDB에서 id를 정수로 생성하는 것은 글을 생성할 때 처리해줘야한다고 한다.)

db.collection('post').find({_id : { $gt : 1000 }}).limit(5)