이전 포스팅에서는 Pagination 컴포넌트에 대한 설명을 했고,
이번 포스팅에서는 서버측 설정에 대해 설명한 후, createPagination.js
에 대해 설명을 하고자 한다.
우선 Helper 전체 목록을 불러오는 코드를 보면서 설명을 하겠다.
module.exports = {
getFilteredList: async (req, res) => {
// 설명 1
const id = parseInt(req.params.id);
// 설명 2
let page = Math.abs(parseInt(req.query.page));
let limit = Math.abs(parseInt(req.query.limit));
// 설명 3
page = !isNaN(page) ? page : 1;
limit = !isNaN(limit) ? limit : 9;
// 설명 4
const skip = (page - 1) * limit;
if (id === 0) {
try {
// 설명 5
const allList = await helper.findAndCountAll({
limit,
offset: skip,
where: {},
attributes: { exclude: ['password', 'createdAt', 'updatedAt'] },
});
const { count, rows: list } = allList;
// 설명 6
const maxPage = Math.ceil(count / limit);
res.send({ list, maxPage });
} catch (e) {
console.log(e);
}
} else {
// 생략
}
}
},
};
설명 1
클라이언트 측에서는 아래와 같은 주소로 서버에 정보를 요청한다.
http://localhost:3000/helperlist/category/0?page=1&limit=9
위의 주소에서 0인 부분이 바로 id
에 할당될 값인데,
query string은 string으로 값이 전달되기 때문에, parseInt()
함수를 사용해서 정수로 바꾸어 주었다.
설명 2
page
와 limit
도 id
와 마찬가지로, parseInt()
함수를 사용해서 정수로 일단 바꿔주었다.
그리고 page
와 limit
은 무조건 양수여야만 하므로, Math.abs()
함수를 사용해 무조건 양수가 나올 수 있도록 설정하였다.
설명 3
query string 값이 정수로 변환될 수 없을 경우를 생각하여,
page
와 limit
의 기본값을 각각 1와 9로 설정해주었다.
설명 4
skip
이라는 변수에 무시할 게시물의 수를 담아준다.
만약, 2 페이지를 클릭하면, DB에서 처음 9개 게시물을 무시하고 10번째부터 9개의 게시물을 보여주게 된다.
설명 5
sequelize pagination 관련 문법이다.
limit
에는 한번에 불러올 데이터의 갯수를 설정하고,
offset
에는 건너뛸 데이터의 갯수를 설정하면 된다.
설명 6
총 페이지 갯수를 서버측에서 계산해서 클라이언트로 보내준다.
sequelize의 findAndCountAll()
문법을 사용해서 총 데이터 갯수를 불러와서
count
변수에 담아 준 후에, count
를 limit
(한 번에 불러올 데이터 갯수)로 나누어 주면, 총 페이지 갯수를 구할 수 있다.
이렇게 구한 총 페이지 갯수를 maxPage
변수에 담아 클라이언트로 보내준다.
이전 포스팅에서 언급했듯이, codesandbox에서 가져온 코드였기에
우리 프로젝트에 맞게끔 코드를 수정하면서 코드를 하나하나씩 뜯어봐야만 했다.
우선 Pagination 컴포넌트 코드를 보면 아래와 같은 코드가 있다.
const { pagination } = createPagination({
numberOfPage: 5,
currentPage,
maxPage,
});
이 부분이 createPagination.js
파일로 보내는 정보들이 담겨 있는 부분이다.
createPagination.js
파일에서는 아래와 같이 위의 정보들을 받아온다.
const createPagination = (info) => {
const { numberOfPage, currentPage, maxPage } = info;
}
현재 위치해 있는 페이지 넘버가 maxPage보다 커지거나, 페이지 넘버가 1보다 작은 경우를 예외 경우 처리해주었다.
if (currentPage > maxPage || currentPage < 1) {
return {
pagination: [],
currentPage,
};
}
pageNumList
const pageNumList = Array(maxPage)
.fill(1)
.map((x, idx) => x + idx);
만약 maxPage
가 10 이라면,
pageNumList
에는 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 배열이 담기게 된다.
sideBtn
const sideBtn =
numberOfPage % 2 === 0 ? numberOfPage / 2 : (numberOfPage - 1) / 2;
만약 numberOfPage
가 5인 경우,
5 % 2는 0이 아니므로 콜론(:) 뒷부분이 실행되고, sideBtn
에는 2가 할당된다.
즉, 5개의 페이지 넘버를 화면에 출력 할 경우,
가운데 페이지를 기준으로 양쪽에 몇개의 페이지 넘버를 출력할 것인지에 대한 정보를 담는 변수이다.
(bind()
메소드 공부한게 여기서 도움이 되는 구나 🙂🙃)
const calculLeft = (rest = 0) => {
return {
array: pageNumList
.slice(0, currentPage - 1)
.reverse()
.slice(0, sideBtn + rest)
.reverse(),
rest: function () {
return sideBtn - this.array.length;
},
};
};
array
pageNumList
는 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 이고, currentPage
가 5 인 경우,
출력되어야 하는 페이지 넘버들은 3 4 5 6 7 과 같다.
currentPage
를 기준으로 왼쪽에 위치한 3 4를 얻어내는 과정이다.
rest
sideBtn
은 위에서 계산한 결과 2가 할당되어 있고,
this.array.length
값은 현재 array에는 [3, 4]가 들어가 있기 때문에 2가 된다.
그러므로 이 경우에서는 0이 return 된다.
const calculRight = (rest = 0) => {
return {
array: pageNumList.slice(currentPage).slice(0, sideBtn + rest),
rest: function () {
return sideBtn - this.array.length;
},
};
};
왼쪽 화살표(이전 페이지)와 비슷한 코드이므로 별도의 설명은 생략하겠다.
const leftBtn = calculLeft(calculRight().rest()).array;
const rightBtn = calculRight(calculLeft().rest()).array;
CASE 1
pageNumList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
currentPage = 1
leftBtn
calculRight().rest()
실행calculLeft(0)
실행calculLeft(calculRight().rest()).array
= [ ]leftBtn
= [ ] rightBtn
calculLeft().rest()
실행calculRight(2)
실행calculRight(calculLeft().rest()).array
= [2, 3, 4, 5]rightBtn
= [2, 3, 4, 5]CASE 2
pageNumList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
currentPage = 6
leftBtn
calculRight().rest()
실행calculLeft(0)
실행calculLeft(calculRight().rest()).array
= [4, 5]leftBtn
= [4, 5] rightBtn
calculLeft().rest()
실행calculRight(0)
실행calculRight(calculLeft().rest()).array
= [7, 8]rightBtn
= [7, 8] return {
pagination: [...leftBtn, currentPage, ...rightBtn],
currentPage,
};
2-6에서 얻은 변수들 값을 pagination에 담아서 리턴해주면,
페이지 넘버가 5개씩 일정하게 잘 출력된다.
비록 다른 누군가의 코드를 가져와서 우리 프로젝트에 적용했지만,
그만큼 코드에 대해 이해를 하고, 어떤 방식으로 동작이 되는 건지
내 나름대로 파악하려고 많은 노력을 했다.
클라이언트 코드는 좀 더 파악하기 쉽게 포스팅을 하면서 고쳐나갔지만,
createPagination.js
파일에 대한 코드도 좀 더 간단히 수정할 수 있으면 수정해 보고 싶다.
아직 구현해야할 기능들이 남아있기에, 이 부분은 추후 시간이 남을때 진행해 보도록 해야겠다.