Itersection Observer API는 타겟 요소와 상위 요소 또는 document의 viewport 사이의 intersection내의 변화를 비동기적으로 관찰하는 방법이다.
❗ 한가지 예로, infinite-scroll을 구현할 때도 유용하다!
맨 아래까지 도달해 스크롤 하면 더 많은 컨텐츠가 렌더링되어 페이지를 이동하지 않아도 되도록 만들 수 있다.
이 메서드를 호출하게 되면 intersection을 감지할 수는 있지만, 성능문제가 발생할 수 있다.
이 메서드를 호출할 때마다 브라우저는 엘리먼트의 크기와 위치값을 최신 정보로 알아오기 위해서 웹페이지 전체를 다시 그린다. 만약 스크롤 이벤트 처럼 한번에 많은 횟수로 호출하게 되면, 하나의 메인스레드에서 모두 처리하기 때문에 브라우저가 처리하는 코드의 실행 속도가 현저히 느려질 수 있다.
앞서 말한 이벤트가 과도하게 발생하는 경우에, throttle과 debounce 등을 사용해 이벤트의 실행 빈도를 조절하는 것이 브라우저의 성능을 개선하는 방법이다.
throttle과 debounce는 자주 사용되는 이벤트나 함수들의 실행 빈도를 줄여 성능을 향상시킨다.
어떻게?
사용자가 키보드로 키를 하나씩 입력할 때 api로 데이터를 가져올 때, 사용자의 의도와 무관한 요청이 자주 발생된다고 한다. 이 문제를 해결하기 위해 키를 누른 후나 입력하는 중간중간 특정 텀마다 api값을 가져오도로 지정한다면 성능을 개선시킬 수 있다.
여러번 발생하는 이벤트를 일정시간 동안 한번 실행
위의 예시를 적용해 보면,
키보드의 입력이 발생하면 즉시 값을 출력하는 대신,
500ms 후에 가장 최신 값을 출력하고 초기화하는데, 이 과정을 입력이 끝날때까지 반복한다.
function throttle(callback, limit = 100) {
let waiting = false;
return function() {
if(!waiting) {
callback.apply(this, arguments);
waiting = true;
setTimeout(() => {
waiting = false;
}, limit);
}
}
}
여러번 발생하는 이벤트 중 가장 마지막 이벤트만을 실행
위의 예시를 적용해보면,
키보드입력이 발생하면 500ms동안 기다린다.
이 시간 안에 키보드 입력이 발생하면 시간을 초기화하고 다시 기다리다가, 시간이 되면 가장 최신 값을 출력한다.
function debounce(callback, limit = 100) {
let timeout
return function(...args) {
clearTimeout(timeout)
timeout = setTimeout(() => {
callback.apply(this, args)
}, limit)
}
}
이벤트를 언제 발생 시킬지의 시점에 차이가 있다.
뭘 써야할지 어떻게 적절하게 선택할까?
위의 자동완성 예시로 생각해보면,
일정 주기로 자동으로 완성되는 리스트를 보여줄 때
이전부터 debounce와 throttle은 어떻게 쓰는지 궁금했는데, 자바스크립트 내장 메서드가 아니라는 것을 이번에 알았다.
라이브러리를 쓰거나 기본 자바스크립트에서 해당 개념을 함수로 만들어서 사용하는 것으로 보인다.
let options = {
root: document.querySelector('#scrollArea'),
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(callback, options);
let target = document.querySelector('#listItem');
observer.observe(target);
let callback = (entries, observer) => {
entries.forEach(entry => {
화면안에 들어온 비율
화면 안에 있는지 여부
const options = {
root: null,//viewport
rootMargin: '0px',
threshold: 1, //0~1
}
root 는 document.querySelector로 기준이 될 부모 요소를 설정할 수 있다.