IntersectionObserver

GY·2021년 11월 3일
0

Basic CS

목록 보기
9/28
post-thumbnail

IntersectionObserver

what is this?

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

❗ 한가지 예로, infinite-scroll을 구현할 때도 유용하다!
맨 아래까지 도달해 스크롤 하면 더 많은 컨텐츠가 렌더링되어 페이지를 이동하지 않아도 되도록 만들 수 있다.

Element.getBoundingClientRect()

이 메서드를 호출하게 되면 intersection을 감지할 수는 있지만, 성능문제가 발생할 수 있다.

reflow

이 메서드를 호출할 때마다 브라우저는 엘리먼트의 크기와 위치값을 최신 정보로 알아오기 위해서 웹페이지 전체를 다시 그린다. 만약 스크롤 이벤트 처럼 한번에 많은 횟수로 호출하게 되면, 하나의 메인스레드에서 모두 처리하기 때문에 브라우저가 처리하는 코드의 실행 속도가 현저히 느려질 수 있다.

throttle, debounce

앞서 말한 이벤트가 과도하게 발생하는 경우에, throttle과 debounce 등을 사용해 이벤트의 실행 빈도를 조절하는 것이 브라우저의 성능을 개선하는 방법이다.

throttle과 debounce는 자주 사용되는 이벤트나 함수들의 실행 빈도를 줄여 성능을 향상시킨다.

어떻게?

예시 1. 자동완성

사용자가 키보드로 키를 하나씩 입력할 때 api로 데이터를 가져올 때, 사용자의 의도와 무관한 요청이 자주 발생된다고 한다. 이 문제를 해결하기 위해 키를 누른 후나 입력하는 중간중간 특정 텀마다 api값을 가져오도로 지정한다면 성능을 개선시킬 수 있다.

throttle

여러번 발생하는 이벤트를 일정시간 동안 한번 실행

  • 동일 이벤트가 반복적으로 시행되는 경우
  • 이벤트의 실제 반복 주기와 상관없이
  • 임의로 설정한 일정 시간 간격(밀리세컨드)으로 콜백 함수의 실행을 보장한다.

위의 예시를 적용해 보면,

키보드의 입력이 발생하면 즉시 값을 출력하는 대신,
500ms 후에 가장 최신 값을 출력하고 초기화하는데, 이 과정을 입력이 끝날때까지 반복한다.

function throttle(callback, limit = 100) {
    let waiting = false;
    return function() {
        if(!waiting) {
            callback.apply(this, arguments);
            waiting = true;
            setTimeout(() => {
                waiting = false;
            }, limit);
        }
    }
}

debounce

여러번 발생하는 이벤트 중 가장 마지막 이벤트만을 실행

  • 동일 이벤트가 반복적으로 시행되는 경우
  • 마지막 이벤트가 실행되고 나서
  • 일정 시간(밀리세컨드)동안 해당 이벤트가 다시 실행되지 않으면 해당 이벤트의 콜백 함수를 실행한다.

위의 예시를 적용해보면,

키보드입력이 발생하면 500ms동안 기다린다.
이 시간 안에 키보드 입력이 발생하면 시간을 초기화하고 다시 기다리다가, 시간이 되면 가장 최신 값을 출력한다.

function debounce(callback, limit = 100) {
    let timeout
    return function(...args) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
            callback.apply(this, args)
        }, limit)
    }
}

차이점 정리

이벤트를 언제 발생 시킬지의 시점에 차이가 있다.

  • throttle은 이벤트 발생 시간 이후에 일정 시간 동안만을 기다리고, 이벤트를 실행 후 기다린다.
  • debounce는 마지막 이벤트에서 일정 시간동안 이벤트가 발생한다면, 다시 기다린 시간을 초기화한 뒤 그 시간만큼 기다린다.

뭘 써야할지 어떻게 적절하게 선택할까?

위의 자동완성 예시로 생각해보면,
일정 주기로 자동으로 완성되는 리스트를 보여줄 때

  • 사용자 경험 측면에서는 throttle이 유리할 수 있다.
    - debounce에 비해 일정한 주기로 최신값을 보여주기 때문에, 유저 관점에서 키를 누를 때마다 자동완성 결과를 볼 수 있다는 장점이 있다.
  • 성능상에서는 debounce가 유리할 수 있다.
    - 키보드 입력이 전부 끝난 뒤 500ms가 지난 뒤에 출력하는 것이기 때문에, 1번만 결과를 출력하는 함수를 호출하여 좋은 성능을 유지할 수 있다.

사용법

이전부터 debounce와 throttle은 어떻게 쓰는지 궁금했는데, 자바스크립트 내장 메서드가 아니라는 것을 이번에 알았다.
라이브러리를 쓰거나 기본 자바스크립트에서 해당 개념을 함수로 만들어서 사용하는 것으로 보인다.

intersectionObserver - 장점

how to use

1. intersection observer 생성

let options = {
  root: document.querySelector('#scrollArea'),
  rootMargin: '0px',
  threshold: 1.0
}

let observer = new IntersectionObserver(callback, options);

root

rootMargin

threshold

2. targeting an element to be observed

let target = document.querySelector('#listItem');
observer.observe(target);

3. callback function

let callback = (entries, observer) => {
  entries.forEach(entry => {

intersectionObserverEntry

intersectionRatio

화면안에 들어온 비율

intersecting

화면 안에 있는지 여부

rootBounds

const options = {
root: null,//viewport
rootMargin: '0px',
threshold: 1, //0~1
}

root 는 document.querySelector로 기준이 될 부모 요소를 설정할 수 있다.

Reference

profile
Why?에서 시작해 How를 찾는 과정을 좋아합니다. 그 고민과 성장의 과정을 꾸준히 기록하고자 합니다.

0개의 댓글