IntersectionObserver MDN docs를 참조한 글 입니다
팀프로젝트에서 맡은 페이지중 무한스크롤 기능이 있어
해당 기능을 구현하는 법을 찾아보니 많이 쓰는 두가지 방법이 있었다
Scroll Event를 등록해 해당 이벤트가 일어날 때 마다
뷰포트의 최하단에 도착했는지를 체크하고 이벤트 핸들러를 실행하는 방식
특정 요소를 관찰 대상으로 등록하고 해당 요소가 뷰포트에 진입하거나 빠져나갈 때를 감시,
즉 교차 상태의 변화를 감시해 상태가 변할때마다 콜백함수를 호출 하는 방식
이런 두가지의 방식이 있는데 스크롤 이벤트는 이벤트가 발생할 때마다 브라우저에서
스크롤 위치를 계산하고, 이에 따른 DOM 요소의 상태 변경 등을 처리해야 하는 반면 IntersectionObserver는 등록된 특정 요소의 교차 상태의 변화가 났을때만 콜백함수를
실행하기 때문에 자원소비가 줄어들어 성능저하 측면으로 Scroll Event보다 좋다고 판단했다!
먼저 IntersectionObserver 관련 문서, 무한 스크롤 기능구현 시 주로 쓰는 속성을 알아보았다
// IntersectionObserver 등록
const io = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
// 주시 대상이 뷰포트 안으로 들어오면 active 클래스 추가
if (entry.intersectionRatio > 0) {
entry.target.classList.add("active");
}
// 아니면 active 클래스 제거
else {
entry.target.classList.remove("active");
}
});
});
// 주시 대상 선언, 주시 시작
const boxElList = document.querySelectorAll(".box");
boxElList.forEach((el) => {
io.observe(el);
});
entries
콜백 함수의 매개변수로 전달되는 배열
entry
entries 배열 안의 각 객체요소
isIntersecting
entry 객체의 속성 대상 요소가 뷰 포트와 교차하는지 여부
true이면 교차 중, false이면 교차 상태 아님
observe(요소)
IntersectionObserver에 대상 요소 등록 시 사용
등록된 요소는 교차 상태의 변화를 감지하게 되며,
교차 상태가 변할 때마다 콜백 함수 호출
unobserve(요소)
IntersectionObserver에 대상 요소 등록을 해제 시 사용
해당 프로젝트는 프론트엔드 기반 프로젝트이다보니 코드잇에서 서버를 지원해줬는데
스웨거를 확인 해보니 cursorId이 같이 데이터로 넘오고 있었기 때문에 cursorId 기반으로
로직을 구성해보았다!-!
IntersectionObserver 셋팅
useEffect에 컴포넌트가 마운트되거나 cursorId가 변경될 때 실행
IntersectionObserver 실행
IntersectionObserver를 생성, 마지막 요소(useRef로 선언된 변수에 저장)를 감시 대상으로 등록,
등록된 요소가 화면에 진입하면 (entry.isIntersecting⇒true),
api가 요청되는 함수를 호출(= 추가 된 초대 요소 로드)
데이터 로드 및 업데이트
cursorId를 기반으로 api가 요청되는 함수를 실행해 현재 초대 요소를 추가 로드,
로드 된 데이터는 이전의 초대 요소 리스트에 추가
IntersectionObserver 정리
컴포넌트가 언마운트되거나 cursorId가 변경될 때, IntersectionObserver 등록 해제
useEffect(() => {
const intersectionObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return;
loadMoreInvitations();
});
});
// 마지막 요소를 감시 대상으로 등록
if (lastElementRef.current) {
intersectionObserver.observe(lastElementRef.current);
}
// 컴포넌트가 언마운트되거나 cursorId가 변경될 때, IntersectionObserver 등록 해제
return () => {
if (lastElementRef.current) {
intersectionObserver.unobserve(lastElementRef.current);
}
};
}, [cursorId.current]);