2023. 6. 12. 07:50ㆍUX Engineer 이야기
들어가며
실무에서 스크롤을 내리다 특정 시점에 실행되어야 하는 이벤트를 구현하는 일이 있었습니다.
자연스럽게 window scroll 이벤트를 이용해서 작업을 했는데, 더 나은 방법인 Intersection Observer API라는 걸 알게 되면서 적용해 보고 느낀 점을 적어보려 합니다.
Intersection Observer API 란?
구글 번역기로 Intersection Observer를 직역해 보면 ‘교차로 관찰자’라고 합니다. ‘교차로 관찰자’, 너무 직역된 것 같죠? 이해하기 쉽게 의역해 보자면 브라우저의 뷰포트와 타깃 엘리먼트의 교차점을 관찰하는 API라고 합니다. 더 쉽게 말해보면 브라우저에 우리가 지정한 요소가 지금 보이는지 구별하는 기능을 제공한다고 생각하면 됩니다.
앞서 이 API가 더 나은 방법이라고 소개한 이유가 있는데요, 기존 방식인 window의 scroll 이벤트로 구현하게 되면 스크롤을 할 때마다 이벤트가 호출되어서 브라우저 성능에 부담을 줄 수 있습니다. 반면에 Intersection Observer API는 비동기적으로 실행되기 때문에 이런 부담을 줄일 수 있는 장점이 있습니다.
이런 장점으로 인해 mdn 문서에서는 이 API가 필요한 경우 4가지를 말해주고 있습니다.
- 페이지가 스크롤 될 때 이미지 또는 콘텐츠를 지연 로드 시킬 때 → Lazy load
- 스크롤 할 때 점점 더 많은 콘텐츠가 로드되고 렌더링 될 때 → 인피니티 스크롤
- 광고 수익을 계산하기 위해 광고의 가시성을 보고할 때
- 사용자가 결과를 볼 수 있는지에 따른 작업 또는 애니메이션 프로세스
위의 경우 스크롤 이벤트 보다 Intersection Observer API를 통해 구현한다면 좀 더 나은 사용자 경험을 제공할 수 있습니다.
하지만 이런 API도 한계가 있는데요, 보여지는 영역을 정확한 px 값이 아닌 %, 즉 보여지는 비율로만 알 수 있다는 점입니다.
사용 방법
Intersection Observer API를 사용해 보겠습니다. Intersection Observer API는 2개의 인자를 받습니다.
callback과 options입니다.
observer라는 이름으로 IntersectionObserver를 만들어 봅시다.
let options = {
root: document.querySelector('#scrollArea'),
rootMargin: '0px',
threshold: 0.5,
};
let observer = new IntersectionObserver(callback, options);
observer를 만든 후에는 관찰할 대상 요소를 지정해야 합니다.
let target = document.querySelector('#target'); // 타깃
observer.observe(target);
대상이 threshold에 지정한 임계값을 충족할 때마다 callback 함수가 호출됩니다.
callback 함수는 IntersectionObserverEntry의 객체 목록과 관찰자를 받습니다.
let callback = (entries, observer) => {
entries.forEach((entry) => {
// Each entry describes an intersection change for one observed
// target element:
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
});
};
React로 적용한 샘플코드를 통해 확인해 볼 수 있습니다. console 창을 열어 수치를 확인해 보세요. target 영역의 50%가 보이는 순간 색상이 바뀌는 걸 확인해 보실 수 있습니다.
callback
- boundingClientRect: 타깃 요소의 사각형 정보를 나타냅니다.
- intersectionRatio: 교차한 영역 정보를 사각형 정보로 나타냅니다.
- intersectionRect: 교차한 영역의 백분율 정보를 나타냅니다.
- isIntersecting: 교차한 상태인지 boolean값으로 나타냅니다.
- rootBounds: 지정한 root 요소의 사각형 정보를 나타냅니다.
- target: 타깃 요소
- time: 교차가 시작된 시점을 기록합니다.
options
- root: 뷰포트로 사용되는 요소입니다. 타깃 요소의 조상을 지정합니다. 지정되지 않았거나 null인 경우 뷰포트가 기본값입니다.
- rootMargin: 루트 요소의 여백을 지정합니다. css의 margin 속성과 유사한 값을 가질 수 있습니다. 값은 백분율이 될 수도 있습니다. ex) ‘10px 20px 30px 40px’, ‘50%’
- threshold: 타깃 요소의 가시성 비율을 나타냅니다. 기본값은 0이며 단일 숫자 또는 배열로 나타낼 수 있습니다. 예를 들어 타깃 요소의 50%를 통과할 때 나타나게 하고 싶다면 0.5를 사용하면 됩니다.
실무에서 매번 위의 방법으로 호출하는 것은 비효율적이고 hook을 만들어서 사용하거나 react-intersection-observer 라이브러리를 이용하면 좀 더 편리하게 사용할 수 있습니다.
마치며
Intersection Observer API에 대한 간단한 사용법과 원리를 알아보았는데요. 저는 이런 유용한 API를 아직도 몰랐다는 사실이 좀 부끄러웠고 역시 공부를 해야겠다는 생각이 들었습니다.
또한 스크롤 이벤트를 모두 Intersection Observer API로 대체시킬 수는 없는 한계는 분명히 존재하고 상황에 맞게 적용하면 좋을 것 같습니다.
이 글을 통해서 스크롤 관련 작업 시 해당 API를 활용하여 브라우저 성능을 좀 더 향상하셨으면 좋겠습니다.
감사합니다.
이 글은 pxd XE Group Blog에서도 보실 수 있습니다.