Pagination을 해보자..

준영·2023년 3월 13일
0

코드 지갑..

목록 보기
10/20

페이징 처리를 할 때, 일반적으로 백엔드에서 다음과 같은 정보를 제공한다.

  1. 총 데이터 건수: 전체 데이터의 건수를 의미합니다. 이 값은 페이지 수를 계산하는 데 사용
  2. 페이지 번호: 사용자가 요청한 페이지 번호를 나타냄
  3. 페이지 크기: 한 페이지에 보여줄 데이터 건수를 의미
  4. 정렬 방식: 데이터를 어떤 기준으로 정렬할 것인지를 나타냄
  5. 정렬 순서: 오름차순(ascending) 또는 내림차순(descending)으로 데이터를 정렬할 것인지를 나타냄

이 정보들은 백엔드에서 페이지네이션을 처리하는 데 사용되며, 클라이언트(웹 브라우저 또는 모바일 앱)에서 요청한 페이지에 대한 데이터를 제공하는 데 사용됩니다. 이를 통해 클라이언트에서는 사용자가 요청한 페이지에 맞는 데이터를 효율적으로 가져올 수 있습니다.


하지만 Firebase로 받은 게시글의 리스트를 페이징처리를 해보려고 한다.. 아무런 정보의 제공없이 한번 페이징처리를 해보자

state

list.tsx

const [boardListData, setBoardListData] = useState([]); // list data (board)
const [boardData, setBoardData] = useState([]); // list data per page (board)
const [limit, setLimit] = useState(5); // list data length per page
const [page, setPage] = useState(1); // page value (default = 1)

fetch data func

list.tsx

async function fetchBoards() {
  const board = collection(getFirestore(firebaseApp), props.menu);
  const result = await getDocs(query(board, orderBy("timestamp", "desc")));
  const fetchData = result.docs.map((el) => el.data());
  setBoardListData(fetchData);
  setBoardData(fetchData.slice((page - 1) * limit, page * limit));
}
// first time fetch
useEffect(() => {
  fetchBoards();
}, [page]);

우선 전체 데이터(페이지 버튼 만들 떄 필요)와 페이지 버튼을 클릭 했을 떄, 보여 줄 데이터를 가져와야한다.
limit라는 state는 한 페이지에 보여줄 데이터의 갯수를 뜻하는데, 이것을 이용해서 page(현재 페이지 번호)값에 따라 몇번 Index에서 몇번 Index까지의 데이터를 가져오는지 slice 하였다.

2번 페이지면, 페이지 값에서 -1을 하고 limit를 곱해서 5. 그리고 페이지 값에서 limit를 곱해서 10. 이것을 slice 인자 값으로 준다면(5, 10), 5번 인덱스에서 9번 인덱스까지의 데이터를 반환하는 것이다.


page button

pagination.tsx

export interface PageType {
  listLength: number;
  limit: number;
  page: number;
  setPage: Function;
}

export default function PaginationBtn(props: PageType) {
  const pageLength = Math.ceil(props.listLength / props.limit); // all page length

  const onClickPageBtn = (pageNum) => {
    props.setPage(pageNum);
    console.log("click page button", props.page);
  };

  const renderPageNumbers = () => {
    const pageNumber = [];
    for (let i = 1; i <= pageLength; i++) {
      pageNumber.push(
        <button key={i} onClick={() => onClickPageBtn(i)}>
          {i}
        </button>
      );
    }
    return pageNumber;
  };

  return <div>{renderPageNumbers()}</div>;
}

우선 앞에서 밭아온 전체 게시글의 데이터의 length로 전체 데이터의 갯수를 limit(한 페이지에 보여 줄 갯수)를 나누면 전체 페이지 버튼의 갯수가 나오게 되고,
for문을 이용하여 그 갯수만큼의 버튼을 pageNumber라는 배열에 담고 반환해주었다.


list

list.tsx

다시 리스트 컴포넌트로 돌아가서, useEffect에 page로 의존성을 주고, 페이지 버튼을 눌렀을 때, 처음에 만들었던 로직이 동작하면서 나온 데이터인 boardData를 map으로 뿌려주는(?) 것이다.

<Boards.BoardListBox>
  {boardData.map((el, index) => (
    <Boards.Board key={index} id={el.id} onClick={moveToDetail}>
      <Boards.BoardNumber>
        {boardListData.length - (page - 1) * limit - index}
      </Boards.BoardNumber>
      <Boards.BoardTitle>{el.title}</Boards.BoardTitle>
      <Boards.Name>{el.name}</Boards.Name>
      <Boards.BoardDate>
        {el.timestamp.toDate().toISOString().split("T")[0]}
      </Boards.BoardDate>
    </Boards.Board>
  ))}
</Boards.BoardListBox>

그리고 나는 예를 들면 20개의 게시글이있으면, 가장 최근에 작성한 글에 게시글 번호를 20을 부여하고 화면에 보여주고 있어서 아래와 같은 코드를 사용했다.

<Boards.BoardNumber>
  {boardListData.length - (page - 1) * limit - index}
</Boards.BoardNumber>


전체 데이터의 개수(17)에서 현재 페이지(1)에서 -1한 값과 페이지 당 노출 데이터 개수(5)를 곱한 값을 빼고, 추가로 index(총 다섯개를 보여줌으로 첫번째 글의 index는 0)를 빼주면 내가 원하는 번호가 나온다!


result

글 쓰는데 역대급으로 설명하기가 어려웠다. 나중에 내가 다시 이걸 볼 때, 알아 들을 수 있을까.. 열심히 해야겠다.

profile
개인 이력, 포폴 관리 및 기술 블로그 사이트 👉 https://aimzero-web.vercel.app/

0개의 댓글