express로 페이지네이션 구현하기
전통적인 방법
한 페이지에 몇 개의 글을 보여줄 것인가? 만약 다섯개라고 한다면
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)