최근 무한스크롤을 구현하다가 intersection observer에 대해 알게 되어 오랜만에 정리합니다.
대부분 scroll event
를 사용하여 무한스크롤을 구현했습니다.
window.innerHeight + document.documentElement.scrollTop >= document.documentElement.offsetHeight)
윈도우 높이 + 스크롤 된 Top 좌표 >= 스크롤을 포함한 전체 페이지 길이를 계산하여 아래까지 스크롤 했을 때 데이터를 더 요청하도록 구현하는 방법입니다.
해당 방법은 스크롤할 때 마다 scoll event가 너무 많이 발생합니다. 따라서 여러 개의 스크롤 이벤트 리스너가 있다면 메인스레드에 과부하를 줄 수도 있습니다.
스크롤 이벤트에서 현재 스크롤된 Top 좌표를 알기 위해 offsetTop
을 사용하는데 이 값을 정확하게 가져오기 위해서는 매번 layout을 새로 그려야합니다. layout을 새로 그리려면 render tree를 새로 생성하여 reflow가 매번 발생합니다. 또, 스크롤 이벤트가 많이 발생함에 따라 데이터 요청도 많이 발생하게 됩니다.
따라서 스크롤 이벤트 핸들러가 호출되는 수를 줄일 수 있는 최적화 방법으로 쓰로틀링throttling
이라는 이벤트 제어 방법을 사용하곤 했습니다.
throttle
이벤트를 일정한 주기마다 발생하도록 하는 기술, 설정 시간 동안 최대 1번만 발생하게 하는 기술로 무한스크롤에 자주 사용됩니다.
타겟 요소와 상위 요소 또는 최상위 document의 viewport 사이의 intersection 내의 변화를 비동기적으로 관찰하는 방법
Intersection Observer, 말그대로 교차부분 관찰자.
그들이 감시하고자 하는 요소가 다른 요소(viewport)에 들어가거나 나갈 때 또는 요청한 부분만큼 두 요소의 교차부분이 변경될 때 마다 실행될 콜백함수를을 등록할 수 있게 합니다. 요소의 교차를 지켜보기 위해 메인 스레드를 사용할 필요 없이 브라우저는 원하는대로 교차 영역 관리를 최적화할 수 있습니다.
null
을 사용하면 됩니다.뷰포트 혹은 다른 요소를 root로 사용하건 간에 이 API는 같은 방식으로 동작합니다.
대상 요소의 가시성이 변경될 때 마다 콜백 함수를 실행하며 그것이 원하는 만큼 root 요소와 교차합니다.
간단히 설명해 target이 화면에 노출되었는 지 여부를 간단하게 구독할 수 있는 API 입니다.
const options = { threshold: 1.0 };
const callback = (entires, observer) => {
entries.forEach((entry) => {
if(entry.isIntersection) {
observer.unobserve(entry.target);
// 화면에 노출
} else {
// 화면에서 제외
}
});
}
IntersectionObserver
객체를 생성하면서 callback
과 option
을 전달합니다.IntersectionObserver
에서 observe
로 target
을 추가합니다.target
에 options.threshold
로 정의한 % 만큼 해당 요소가 화면에 노출 또는 제외되면 entires
에 추가하고 callback
을 호출합니다.target
을 구독할 필요가 없으면 unobserve
합니다.entry.isIntersecting
는 노출 여부를 나타내며
entry.intersectionRatio
는 노출 비율, entry.intersectionRect
는 노출 영역으로 정의되어 있습니다.
간단하게 구현해본 예제 https://stackblitz.com/edit/react-wghtbk?file=src%2FApp.js