Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
Tags
- typescript
- 오블완
- ci/cd
- react19
- 실행컨텍스트
- 개발자
- 기술블로그
- 디자인패턴
- 티스토리챌린지
- 개발 지식
- 프엔
- 개발지식
- react
- 리액트
- 모닝스터디
- 업데이트
- 취뽀
- 프론트엔드면접
- React Query
- 개발과정
- 프론트엔드
- 타입스크립트
- 요노피플
- 상태관리
- CS지식
- jest
- 취준생
- 자바스크립트
- 모던 자바스크립트 Deep Dive
- 라우팅
Archives
- Today
- Total
eokeuroding 님의 블로그
데이터 처리 기법 - 페이지네이션 본문
Git : DynamicDataHandling/Pagination at main · dasom-jo/DynamicDataHandling
1.페이지네이션(Pagination)
웹에서 효율적인 데이터 표시방법
많은 양의 데이터를 한 번에 사용자에게 보여주는 것은 성능이나 사용자 경험 측면에서 비효율적입니다. 그래서 대부분의 웹사이트는 데이터를 나누어 순차적으로 제공하는 방식을 사용하며, 이를 페이지네이션이라고 합니다. \
2.왜 페이지네이션이 필요한가요
- 성능 향상 : 수천개의 데이터가 한번에 렌더링 되면 브라우저가 느려집니다.
- 사용자 경험 개선 : 사용자가 정보를 찾기 쉽게 그룹화 할수있습니다.
3.페이지네이션 vs. 무한 스크롤 vs. 가상 스크롤
| 방식 | 설명 | 장점 | 단점 |
| 페이지네이션 | 일정 개수만큼 잘라서 페이지별로 보여줌 | 직관적이고 컨트롤이 쉬움 | 사용자 클릭이 필요 |
| 무한스크롤 | 사용자가 스크롤할때마다 데이터를 계속 불러옴 | 자연스럽고 몰입도 높은 UX | 페이지 이동이 어려움 |
| 가상 스크롤 | 실제 렌더링은 화면에 보이는 부분만 함 | 퍼포먼스 최적화에 강함 | 구현 난이도 높음 |
4.페이지네이션의 구성 요소
- 현재 페이지(current page) : 사용자가 현재 보고있는 페이지 번호
- 총 데이터 수 (total items) : 전체 데이터가 몇개인지
- 페이지 당 항목 수 (items per page) : 한페이지에 표시할 데이터의 개수
- 총 페이지 수 (total pages) : Math.ceil (총 데이터 수 / 페이지당 항목 수)
- 페이지 이동 컨드롤 : 이전, 다음 버튼, 숫자 페이지 버튼, 첫 페이지/ 마지막 페이지 이동
5. 페이지네이션 구현 시 고려할 점
- 페이지 변경 시 스크롤 위치 초기화 여부
- URL에 페이지 정보를 반영할지 여부 (/page/3)
- 현재 페이지 강조 스타일링
- 데이터 없는 페이지로 접근 방지 처리
- 반응형 환경에서의 UX 최적화
6.페이지네이션 방식 종류
- 서버 사이드 페이지네이션 : 백엔드가 필요한 데이터만 전송, 대규모 데이터에 적합, 쿼리스트링(?page=2)기반요청
- 클라이언트 사이드 페이지네이션 : 프론트엔드에서 모든 데이터를 받고 페이지별로 나누어 표시, 데이터 양이 적을 때 적합, 빠른 페이지 이동 가능하지만 초기 로딩이 오래걸릴수있음.
7.페이지네이션 구현( 라이브러리 ❌ )
// useGetTopRateMovies.js
import { useQuery } from "@tanstack/react-query";
const FetchTopRatedMovies = async (page) => {
const res = await fetch(
`https://api.themoviedb.org/3/movie/top_rated?page=${page}`,
{
headers: {
Authorization: `Bearer ${process.env.REACT_APP_API_KEY}`,
accept: "application/json",
},
}
);
if (!res.ok) throw new Error("데이터 요청 실패");
return res.json();
};
const useGetTopRateMovies = (page) => {
return useQuery({
queryKey: ["top-rated-movie", page],
queryFn: () => FetchTopRatedMovies(page),
keepPreviousData: true,
});
};
export default useGetTopRateMovies;
// MovieList.jsx
const [currentPage, setCurrentPage] = useState(1);
const { data, isLoading } = useGetTopRateMovies(currentPage);
<button onClick={() => setCurrentPage((p) => p - 1)} disabled={currentPage === 1}>
◀ Prev
</button>
<span>{currentPage} / {data?.total_pages}</span>
<button onClick={() => setCurrentPage((p) => p + 1)} disabled={currentPage === data?.total_pages}>
Next ▶
</button>