페이지 번호를 클릭해서 이동하는 방식의 페이지 처리 방법입니다. 일반적으로 게시판 형태의 페이지에서 가장 일반적으로 사용되는 방식 입니다.

실습을 위해 GraphQL, Next.js 를 사용하였습니다.
// gql query
const FETCH_BOARDS = gql`
query fetchBoards($page: Int) {
fetchBoards(page: $page) {
_id
writer
title
}
}
`;
// fetchBoards
// data와 함께 refetch 가져오기
const { data, refetch } = useQuery(FETCH_BOARDS, { variables: { page: 1 } });
const onClickPage = (event) => {
// 위에서 가져온 refetch 사용하기
refetch({ page: Number(event.target.id) });
};
return (
<div>
<h1>페이지네이션 연습 !!!</h1>
{data?.fetchBoards?.map((el) => (
<div key={el._id}>
{el.title} {el.writer}
</div>
))}
<span onClick={onClickPage} id="1"> 1 </span>
<span onClick={onClickPage} id="2"> 2 </span>
<span onClick={onClickPage} id="3"> 3 </span>
</div>
)
위 코드를 보면 fetchBoards를 이용해서 data를 받아온 후 map함수를 이용해 화면에 흩뿌려 주고 있습니다. 이후 onClickPage를 이용해서 페이지 번호를 이동하면, 이전 포스팅에서 기재했던 refetchQueries를 이용해서 해당하는 페이지에 대한 data를 받아오고 있습니다.
허나 위와 같이 페이지의 숫자를 1,2,3 으로 페이지네이션의 숫자를 직접 입력하는 작업은 비효율적입니다. 때문에 1~10까지 배열을 만들어 표현 해보겠습니다.
{new Array(10).fill(1).map((el) => (
<span onClick={onClickPage} id={String(el)} key={el}>
{` ${el} `}
</span>}
조금 더 깔끔해진 모습을 볼 수 있습니다. 햐지만 이러한 경우 10 이상의 숫자는 표시가 되지 않습니다. 직접 하드 코딩을 할 순 없으니, startpage state를 만들고 map의 index를 이용하여 표현해보겠습니다.
const [startPage, setStartPage] = useState(1);
// 이전 페이지 클릭 시 실행할 함수
const onClickPrevPage = () => {
setStartPage((prev) => prev - 10);
};
// 다음 페이지 클릭 시 실행할 함수
const onClickNextPage = () => {
setStartPage((prev) => prev + 10);
};
return (
<span onClick={onClickPrevPage}>이전페이지 |</span>
{new Array(10).fill(1).map((_, index) => (
<span
onClick={onClickPage}
id={String(index + startPage)}
key={index + startPage}
>
{` ${index + startPage} `}
</span>
))}
<span onClick={onClickNextPage}> 다음페이지</span>
);
위와 같이 startPage state를 이용해서 map의 index (0~9)를 더해주어 자동으로 페이지네이션에 10이상의 숫자도 출력되도록 하였습니다.
허나 아직 문제가 있습니다. 마지막 페이지를 지정하지 않았기 때문에 data가 없어도 다음페이지로 숫자가 무한히 뻗어나갑니다. 이를 방지하기 위해 마지막 페이지에 도달하면 더 이상 다음 페이지 버튼이 동작하지 않도록 만들어 줍니다.
마지막 페이지를 구하기 위해서는 DB에 등록된 게시글의 총 개수를 불러와서 값을 구합니다.
const FETCH_BOARDS_COUNT = gql`
query fetchBoardsCount {
fetchBoardsCount
}
`;
// lastPage 구하기
const lastPage = Math.ceil(dataBoardsCount?.fetchBoardsCount / 10);
1페이지 미만, lastpage가 출력되면 더 이상 버튼이 작동하지 않도록 조건을 걸어주고 해당하는 page의 data를 다시 refetch 합니다.
const onClickPrevPage = () => {
// startPage가 1이면 하단 스크립트를 실행하지 않고 종료한다.
if (startPage === 1) return;
setStartPage((prev) => prev - 10);
refetch({ page: startPage - 10 });
};
const onClickNextPage = () => {
// startPage + 10가 lastPage보다 클 경우 하단 스크립트를 실행하지 않고 종료한다.
if (startPage + 10 > lastPage) return;
setStartPage((prev) => prev + 10);
refetch({ page: startPage + 10 });
};
그리고 JSX 부분에는 조건부 렌더링을 통해 lastPage보다 큰 숫자는 출력되지 않도록 합니다
{new Array(10).fill(1).map(
(_, index) =>
index + startPage <= lastPage && (
<span
onClick={onClickPage}
id={String(index + startPage)}
key={index + startPage}
>
{` ${index + startPage} `}
</span>
)
)}
이렇게 하면 정상적으로 페이지네이션이 작동하는 것을 볼 수 있습니다.
