React에서 Infinite Scroll 구현 및 성능 최적화
무한 스크롤(Infinite Scroll)은 사용자가 페이지 하단에 도달할 때마다 API를 호출하여 새로운 콘텐츠를 추가로 로드하는 방식입니다. 이 방식은 페이지 네이션(pagination)과 달리 사용자가 끊임없이 콘텐츠를 확인할 수 있어 **사용자 경험(UX)**을 향상시키는 중요한 기술입니다. 그러나 제대로 구현하지 않으면 성능 문제를 일으킬 수 있기 때문에 성능 최적화가 중요합니다.
이 글에서는 React에서 Infinite Scroll을 구현하는 방법과 성능 최적화를 위한 기술을 다룹니다. 특히 디바운스(Debounce), 쓰로틀(Throttle), 그리고 Intersection Observer API를 사용하여 효율적인 무한 스크롤을 구현하는 예제를 살펴봅니다.
1. Infinite Scroll 개요
Infinite Scroll은 사용자가 특정 페이지의 하단에 도달할 때, 새로운 데이터를 동적으로 불러와서 추가로 렌더링하는 방식입니다. 이를 통해 사용자는 페이지 전환 없이 끊임없이 콘텐츠를 탐색할 수 있습니다.
Infinite Scroll의 장점:
- 사용 편의성: 사용자는 페이지를 전환하지 않고 스크롤만으로 콘텐츠를 이어서 볼 수 있습니다.
- 부드러운 UI: 동적으로 데이터를 추가해 페이지를 끊김 없이 렌더링할 수 있습니다.
Infinite Scroll의 단점:
- 과도한 API 요청: 스크롤 시점에 지나치게 많은 API 요청을 보낼 경우 서버와 클라이언트 성능에 악영향을 미칠 수 있습니다.
- 사용자 위치 기억 문제: 무한 스크롤은 특정 위치로 쉽게 이동하기 어렵고, 페이지 새로고침 시 상태를 잃을 수 있습니다.
이 문제를 해결하기 위해, Intersection Observer API와 디바운스(Debounce) 및 쓰로틀(Throttle) 기술을 결합하여 성능을 최적화할 수 있습니다.
2. 성능 최적화를 위한 기술
2.1. 디바운스(Debounce)
디바운스는 사용자가 이벤트를 연속적으로 발생시킬 때, 일정 시간이 지난 후에 한 번만 이벤트를 호출하는 방식입니다. 주로 입력 필드와 같은 이벤트에서 많이 사용됩니다.
2.2. 쓰로틀(Throttle)
쓰로틀은 일정 시간 간격으로 이벤트를 발생시키는 방식입니다. 스크롤 이벤트와 같이 자주 발생하는 이벤트에서 쓰로틀을 적용하면, 지정된 시간 간격으로만 이벤트가 호출되도록 제한할 수 있습니다. 이를 통해 API 요청을 조절하여 성능을 향상시킬 수 있습니다.
2.3. Intersection Observer API
Intersection Observer API는 특정 요소가 화면에 나타났는지 또는 사라졌는지 여부를 관찰하는 API입니다. 이를 사용하면, 사용자가 페이지의 하단에 도달했을 때 자동으로 API 요청을 보내 새로운 데이터를 로드할 수 있습니다.
3. React에서 Infinite Scroll 구현하기
3.1. 기본 Infinite Scroll 컴포넌트
Intersection Observer API를 사용하여 무한 스크롤을 구현하는 예제입니다.
// InfiniteScroll.js
import React, { useState, useEffect, useRef } from 'react';
import axios from 'axios';
function InfiniteScroll() {
const [data, setData] = useState([]);
const [page, setPage] = useState(1);
const [loading, setLoading] = useState(false);
const loader = useRef(null);
useEffect(() => {
const fetchData = async () => {
setLoading(true);
const result = await axios.get(`https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=10`);
setData((prevData) => [...prevData, ...result.data]);
setLoading(false);
};
fetchData();
}, [page]);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
setPage((prevPage) => prevPage + 1);
}
},
{ threshold: 1.0 }
);
if (loader.current) {
observer.observe(loader.current);
}
return () => {
if (loader.current) {
observer.unobserve(loader.current);
}
};
}, []);
return (
<div>
<h1>Infinite Scroll Example</h1>
<ul>
{data.map((item) => (
<li key={item.id}>
<h4>{item.title}</h4>
<p>{item.body}</p>
</li>
))}
</ul>
<div ref={loader} style={{ height: '100px', backgroundColor: '#f0f0f0' }}>
{loading && <p>Loading more data...</p>}
</div>
</div>
);
}
export default InfiniteScroll;
코드 설명:
- 데이터 로딩: useEffect를 사용하여 API에서 데이터를 가져오고, 기존 데이터에 추가하는 방식으로 구현됩니다.
- 페이지 증가: Intersection Observer API를 사용하여 페이지 하단의 loader 요소가 화면에 보일 때마다 setPage를 호출하여 페이지 번호를 증가시킵니다.
- 로딩 상태: loading 상태를 사용하여 데이터를 로딩 중일 때는 "Loading more data..." 메시지를 표시합니다.
4. 성능 최적화 적용
4.1. 쓰로틀 적용하기
스크롤 이벤트에 쓰로틀을 적용하면 성능이 더 향상됩니다. lodash의 throttle 함수를 사용할 수 있습니다.
npm install lodash.throttle
import throttle from 'lodash.throttle';
useEffect(() => {
const observer = new IntersectionObserver(
throttle((entries) => {
if (entries[0].isIntersecting) {
setPage((prevPage) => prevPage + 1);
}
}, 2000), // 2초마다 한 번씩만 API 호출
{ threshold: 1.0 }
);
if (loader.current) {
observer.observe(loader.current);
}
return () => {
if (loader.current) {
observer.unobserve(loader.current);
}
};
}, []);
4.2. 디바운스 적용하기
또는 디바운스를 사용하여 일정 시간 후에 API 요청을 보낼 수 있습니다. 예를 들어, 사용자가 스크롤을 멈춘 후에 데이터를 불러오고 싶을 때 디바운스를 사용할 수 있습니다.
5. 결론
Infinite Scroll은 사용자 경험을 향상시킬 수 있는 중요한 기술이지만, 성능 최적화가 필수적입니다. 디바운스, 쓰로틀, 그리고 Intersection Observer API를 활용하면 성능을 크게 개선할 수 있습니다. 특히, 사용자가 페이지 하단에 도달할 때만 데이터를 로드하도록 구현하면 서버 부담을 줄이면서 원활한 사용자 경험을 제공할 수 있습니다.
이 가이드를 통해 React 애플리케이션에서 Infinite Scroll을 효과적으로 구현하고 성능을 최적화할 수 있습니다.
'개발 방법론 & 아키텍쳐' 카테고리의 다른 글
React Player – 비디오 플레이어 컴포넌트 구현 및 기능 설명 (1) | 2024.09.27 |
---|---|
Zod + Zustand + React Query로 인증(Auth) 구현하기 (ErrorBoundary & AxiosInstance 사용) (0) | 2024.09.27 |
React Error Handling: 효과적인 에러 처리를 위한 Error Boundaries 가이드 (1) | 2024.09.27 |
VS Code에서 ESLint와 Airbnb 스타일 가이드 플러그인 설치 및 사용 가이드(React) (2) | 2024.09.26 |
React 개발 프로젝트에서 Airbnb 컨벤션을 사용하는 가이드 (0) | 2024.09.26 |