프로젝트를 하던 도중 생각지 못한 기능을 마주하게 되었으니 그것은 바로 무한스크롤이었습니다. 카드형식의 리스트를 나열해야 하는데 아무래도 무한 스크롤 형태가 예쁘고 보기도 좋으니까요.
결국 해당 기능을 구현해야 한다는 뜻이죠...
인터넷을 뒤져보니 Intersection Observer API를 사용하는 방법과 전통적인 scrollTop등을 이용하는 방식이 있었는데 같이 살펴보고 왜 제가 전자의 방법을 택했는지 설명하도록 하겠습니다.
타겟 엘레멘트와 타겟의 부모 혹은 상위 엘레멘트의 뷰포트가 교차되는 부분을 비동기적으로 관찰하는 API입니다.
화면에 내가 지정한 target 엘레멘트가 보이는지를 관찰하는 API죠.
예제를 따라서 구현해보도록 하겠습니다.
우선 html에 관찰 대상을 추가했습니다. 무한스크롤이 발생할 대상인 flex설정한 div 아래에 두고 관찰되도록 하겠습니다.
<!-- 카드 나열 박스 -->
<div class="card-box w-full px-10 flex flex-wrap"></div>
<div id="observer-target"></div>
위에서 만든 타겟을 가져와줍시다.
//intersection이 발생하는지 관찰할 대상
const target = document.querySelector('observer-target');
그다음 교차 관찰시 실행될 콜백함수를 만들어 줍시다. target이 교차상태임을 확인 후 fetchData()함수를 통해 서버에서 데이터를 가져와 줍니다. observer.unobserve()는 데이터를 가져올 동안은 관찰하지 않겠다는 함수입니다. 데이터를 가져온 후 다시 관찰상태로 돌아가는 함수 observe()를 호출하면 됩니다.
const onIntersect = async ([entry], observer) => {
if (entry.isIntersecting) {
console.log("intersected!");
observer.unobserve(entry.target);
await fetchData();
observer.observe(entry.target);
}
};
콜백함수가 호출되는 상황을 정의하는 옵션을 설정해줍니다. 설정할 수 있는 값들이 많은데 그건 공식문서에서 확인하시면 될 것 같습니다. 저는 rootMargine을 100px을 주어 대상 엘리먼트가 화면 뷰포트에 100px만큼 들어온 경우, threshold를 0.5를 주어 타겟 엘리먼트의 50%이상이 뷰포트 내에 들어오면 감지하도록 설정했습니다.
const options = {
rootMargine: "100px",
threshold: 0.5,
};
그 다음 observer를 만들고 옵저빙을 시작합니다.
const observer = new IntersectionObserver(onIntersect, options);
observer.observe(target);
저같은 경우 fetchData()에서 데이터를 가져오고 엘리먼트를 추가해주는 작업도 같이 하고 있습니다.
const page = 1;
//백에서 상품 리스트 페이지로 가져오는 함수
const fetchData = async () => {
const response = await fetch(`/${page}`);
const data = await response.json();
if (data.length > 0) {
// 새로운 데이터가 있는 경우만 처리
loadCards(data.json());
page++;
}
};
scrollTop은 사용자가 웹 페이지를 얼마나 스크롤 했는지 픽셀 단위로 측정합니다. 스크롤 이벤트 리스너를 추가하여 페이지 하단에 도달했을 때 새로운 데이터를 요청하는 방식입니다.
window.addEventListener('scroll', () => {
if (window.innerHeight + window.pageYOffset >= document.body.offsetHeight - 10) {
// 서버에서 추가 데이터를 가져오는 함수 호출
fetchData();
}
});
async function fetchData() {
// 데이터 요청 및 페이지에 콘텐츠 추가 로직
}
두 방법을 비교할 때, Intersection Observer API는 다음과 같은 부분에 장점이 있습니다.