API
API에서 무한 스크롤보다 페이지네이션을 쓸 때가 있다
무한 스크롤은 UX가 좋아 보이지만, 페이지네이션이 더 나은 상황도 있다. 각각의 장단점과 선택 기준.
무한 스크롤은 모던하고 세련된 느낌을 주지만, 모든 상황에 맞는 건 아니다. 실제로 배포해보면 페이지네이션이 더 나은 경우가 많다.
무한 스크롤의 문제점
1. 사용자가 원점으로 돌아갈 수 없다
무한 스크롤로 100개 항목을 봤는데, 처음 항목으로 돌아가고 싶으면? 스크롤을 위로 올려야 하는데, 이미 로드된 데이터가 100개면 사실상 불가능하다. 페이지네이션이면 "첫 페이지"를 클릭하면 된다.
2. 검색 엔진 최적화 문제
무한 스크롤은 모든 데이터를 JavaScript로 로드하므로, 초기 HTML에는 아무 콘텐츠도 없다. SEO가 약해진다. 블로그 같은 검색 기반 서비스라면 큰 문제다.
3. 로딩 성능 악화
스크롤할 때마다 API를 호출하면, 네트워크 요청이 너무 많아진다. 특히 느린 네트워크에서는 체감 성능이 급격히 떨어진다.
4. 정확한 데이터 개수를 모를 수 있다
API가 "다음 페이지가 있는가"만 반환한다면, 총 몇 개의 항목이 있는지 알 수 없다. 사용자 입장에서는 "얼마나 더 스크롤해야 끝날까"를 알 수 없다.
페이지네이션의 장점
1. 명확한 위치 표시
"3/10 페이지"라고 명시하면, 사용자는 진행 상황을 정확히 알 수 있다.
2. 깊은 페이지 접근이 빠르다
100개 중 마지막을 보고 싶다면, 무한 스크롤은 99개를 모두 로드해야 하지만, 페이지네이션은 "마지막 페이지"를 한 번에 로드한다.
3. SEO 친화적
URL에 ?page=3을 넣으면, 각 페이지가 별도의 URL로 인덱싱될 수 있다.
하이브리드: "더 보기" 버튼
실제로는 무한 스크롤과 페이지네이션의 중간 방식이 효과적이다.
const ItemList = () => {
const [items, setItems] = useState([]);
const [hasMore, setHasMore] = useState(true);
const [page, setPage] = useState(1);
const loadMore = async () => {
const response = await fetch(`/api/items?page=${page + 1}`);
const { data, hasNext } = await response.json();
setItems([...items, ...data]);
setPage(page + 1);
setHasMore(hasNext);
};
return (
<div>
{items.map(item => <Item key={item.id} {...item} />)}
{hasMore && <button onClick={loadMore}>더 보기</button>}
</div>
);
};
이 방식은:
- 초기 로딩이 빠르다 (필요한 항목만)
- 사용자가 "더 보기"를 명시적으로 클릭한다 (제어 가능)
- 서버 부하가 적다 (자동 요청 없음)
- 검색 엔진이 초기 페이지를 인덱싱할 수 있다
상황별 선택 기준
페이지네이션을 쓰세요:
- 블로그, 뉴스 같은 콘텐츠
- SEO가 중요한 서비스
- 사용자가 특정 위치로 점프하고 싶은 경우
- 정렬, 필터링이 많은 경우
- 모바일이 아닌 데스크톱 사용자가 많은 경우
무한 스크롤을 쓰세요:
- 소셜 미디어 피드 (Twitter, Instagram)
- 실시간 업데이트가 중요한 경우
- 모바일 사용자가 대부분
- 정렬이 거의 없는 경우
- 콘텐츠 발견이 목표인 경우
"더 보기" 버튼을 쓰세요:
- 위 두 가지의 장점을 모두 원할 때
- 대부분의 웹 애플리케이션
API 설계
어느 방식을 쓰든, API는 페이지 기반으로 설계하는 게 좋다.
{
"status": "success",
"data": [...],
"pagination": {
"page": 1,
"pageSize": 20,
"total": 1000,
"hasNext": true
}
}
API가 total을 반환하면, 프론트엔드에서 페이지네이션도, 무한 스크롤도, "더 보기" 버튼도 모두 구현할 수 있다.
성능 측정
배포 후에 실제로 어느 방식이 나은지 측정해보자.
// 사용자가 마지막 항목을 봤을 때까지의 시간
const timeToLastItem = Date.now() - loadStartTime;
// 총 네트워크 요청 수
const totalRequests = requestCount;
// 체감 성능 (지표)
const userHappiness = survey();
분석해보면 보통 "더 보기" 방식이 가장 균형잡혀 있다.
정리
무한 스크롤은 매력적이지만, 모든 경우에 좋은 건 아니다. 콘텐츠 특성, 사용자층, SEO 요구도를 고려해서 선택하자. 대부분의 경우 "더 보기" 버튼이 최고의 타협이다. API는 페이지 기반으로 설계해서, 나중에 필요하면 UI만 바꿀 수 있게 하자.