무한스크롤, intersection observer

silverj-kim·2022년 4월 10일
0

최근 무한스크롤을 구현하다가 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번만 발생하게 하는 기술로 무한스크롤에 자주 사용됩니다.

Intersection Observer

타겟 요소와 상위 요소 또는 최상위 document의 viewport 사이의 intersection 내의 변화를 비동기적으로 관찰하는 방법


Intersection Observer, 말그대로 교차부분 관찰자.
그들이 감시하고자 하는 요소가 다른 요소(viewport)에 들어가거나 나갈 때 또는 요청한 부분만큼 두 요소의 교차부분이 변경될 때 마다 실행될 콜백함수를을 등록할 수 있게 합니다. 요소의 교차를 지켜보기 위해 메인 스레드를 사용할 필요 없이 브라우저는 원하는대로 교차 영역 관리를 최적화할 수 있습니다.

컨셉과 사용

  1. target으로 칭하는 요소가 기기 뷰포트나 특정요소(root)와 교차
  2. observer가 최초로 타겟을 관측하도록 요청받을 때 마다
    일반적으로, 요소의 교차성이 가장 가까운 scollable 조상에 의해 변경되길 원할 것입니다. 도큐먼트의 루트 요소를 기준으로 해당 요소를 관찰하기 위해서는 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 {
      // 화면에서 제외
    }
  });
}
  1. 먼저 IntersectionObserver 객체를 생성하면서 callbackoption을 전달합니다.
  2. IntersectionObserver에서 observetarget을 추가합니다.
  3. targetoptions.threshold 로 정의한 % 만큼 해당 요소가 화면에 노출 또는 제외되면 entires에 추가하고 callback을 호출합니다.
  4. 더이상 target을 구독할 필요가 없으면 unobserve 합니다.

entry.isIntersecting는 노출 여부를 나타내며
entry.intersectionRatio는 노출 비율, entry.intersectionRect는 노출 영역으로 정의되어 있습니다.


간단하게 구현해본 예제 https://stackblitz.com/edit/react-wghtbk?file=src%2FApp.js

장점

  • offsetTop 값이 필요없어 reflow가 발생하지 않습니다.
  • 동기적으로 너무 많이 발생하는 스크롤 이벤트를 사용하지 않아도 됩니다.

참고
mdn - intersection observer
IntersectionObserver 간단정리

profile
Front-end developer

0개의 댓글