-
Intersection Observer - Lazy-loading, 무한스크롤을 구현하기 좋은 API!Frontend 2020. 11. 23. 11:15
나는 Intersection Observer API를 좋아한다..
그냥 정이 간다.
Intersection Observer는 특정 엘리먼트가 사용자의 화면에 노출되어있는지 감시할 수 있는 API이다.
이 짤 생각나고 귀엽다.
- web api 중 하나
- 2016년 4월 구글 개발자 페이지 통해 소개됨
- 특정 Element가 화면에 노출되어있는지 감시할 수 있는 API
Intersection Observer를 사용해서 구현할 수 있는 멋진 것들
1. 이미지 Lazy-loading (지연 로딩)
웹사이트에 이미지가 많을 때 화면 상에 존재하는 이미지를 한꺼번에 불러오면 불필요한 네트워킹 비용이 증가한다.
사용자가 스크롤을 내려 모든 이미지를 보기 전에 사이트를 끌 수도 있는데, 굳이 처음부터 다 불러올 필요가 없다.
처음에 모든 이미지를 불러오면 초기 리소스 로딩도 길어진다. (사용자 이탈!)
그럴 때 Intersection Observer를 이용하면 된다.
사용자가 스크롤을 내려서, 화면에 이미지 영역이 보이면 그 때 이미지를 선별적으로 로딩하면 된다.
예시)
Intersection Observer 말고 이전에는 element.getBoundingClientRect 같은 방법을 사용하기도 했다.
얘는 몇가지 단점이 있는데
- 브라우저가 해당 엘리먼트의 크기와 위치값을 계산해야한다.
- reflow가 일어나서 메인 스레드 과부화가 될 수 있다.
- iframe 내부에선 가시성을 판단할 수 없다.
=> 하지만 intersection observer를 사용하면 reflow도 일으키지 않고 iframe 내부에서도 가시성을 판단할 수 있다.
2. 무한 스크롤 구현 (Infinite scrolling)
무한 스크롤을 어떻게 구현할 지 생각해보면
"스크롤이 바닥을 치면 다음 리스트를 불러와야겠다.🧐"
가 제일 먼저 떠오른다.
Intersection Observer를 사용하면 좀 더 기름기 빼고 구현할 수 있다.
기름기 : 기존에 사용되던 scroll 이벤트는 단시간에 수백번, 수천번 호출될 수 있다.
또한 동기적으로 실행되기 때문에 메인 스레드에 영향을 준다.
리스트 하단에 target Element을 추가해놓고
해당 target이 화면에 보이면 특정 액션(callback)을 수행하는 방식으로 무한 스크롤을 구현하면 된다. 💡
예시)
googlechrome.github.io/samples/intersectionobserver/
3. 광고 수익 측정
광고수익 측정은 Intersection Observer로 실제로 구현해본적은 없다.
우리 팀은 Vue를 사용해서.. mounted 훅에 GA 트래킹 등을 걸어놓으니까..
근데! 스크롤을 내려야 노출되는 특정 배너광고 노출 측정을 할 때 유용할 것 같다.💡💡
4. 애니메이션 구현
뭔가 스크롤 내리면 뾰로롱! 하는 것들.. 💫
기본 사용법을 뜯어보자
// 콜백함수와 옵션을 받는다. const io = new IntersectionObserver(callback, { root: null, // 또는 scrollable 한 element rootMargin: '0px', // 기본값 0px threshold: 0.5 // 0.0 ~ 1.0 사이의 숫자. 배열도 가능 })
옵션값을 하나하나 살펴보자
root
target (관측 대상) 을 감싸는 element (container)
default인 null 로 지정하면 viewport가 된다.
rootMargin
root 요소를 감싸는 margin
문자열로 작성해야하며 px 또는 % 단위로 작성할 수 있다.
threshold
root와 target element의 교차 영역 비율
몇 % 교차했을때 callback을 실행할것인가 결정하는 값 (0.0 ~ 1.0)
콜백함수를 살펴보자
target element 의 visibility 가 threshold 만큼 도달했을 때 호출될 함수
Element 배열인 entries와 자기 자신인 observer 가 매개 변수로 전달됨
관련 메소드들을 살펴보자
IntersectionObserver.observe(targetElement)
-
타겟 엘리먼트에 대한 IntersectionObserver를 등록할 때(관찰을 시작할 때) 사용
IntersectionObserver.unobserve(targetElement)
-
타겟 엘리먼트에 대한 관찰을 멈추고 싶을 때 사용
IntersectionObserver.disconnect()
-
다수의 엘리먼트를 관찰하고 있을 때, 이에 대한 모든 관찰을 멈추고 싶을 때 사용
IntersectionObserver.takerecords()
-
IntersectionObserverEntry 객체의 배열을 리턴
코드를 보면서 살펴보자
(Intersection Observer로 무한 스크롤을 구현한 Vue 코드)
mounted() { this.initIntersectionObserver(); }
: 마운트 될 때, interserction observer를 초기화할 함수를 호출함
initIntersectionObserver() { // element는 하나니까 배열에서 하나만 가져옴 const io = new IntersectionObserver(async ([entry], observer) => { // 가시성이 생기면 if (entry.isIntersecting) { // 중복 실행을 막기 위해 관찰을 멈춘다 observer.unobserve(entry.target); // Article을 더 가져오는 메소드 await this.handleGetMoreArticles(); // 실행 뒤에는 다시 관찰을 시작한다 observer.observe(entry.target); } }, { // 30% 정도 보이면 실행 시작 threshold: 0.3 }) io.observe(this.$refs.scrollObserver); }
<div ref="scrollObserver" v-if="isMore"> <div class="spinner"></div> </div>
: 리스트 맨 아래 로딩 엘리먼트를 만들고 scrollObserver라는 ref를 건다. 그 ref에 Intersection Observer를 걸었다.
브라우저 호환성
IE를 지원하지 않는다 😐
만약 IE에서도 사용하고 싶다면 아래의 polyfill을 사용하면 된다.
'Frontend' 카테고리의 다른 글
🔎 Javascript this의 모든것 (0) 2020.03.19 'installVueDevtools' is defined but never used 오류 해결법 (0) 2020.02.03 Docsify와 netlify로 TIL 페이지 만들기 (0) 2020.01.31 vue에서 got 모듈 에러 핸들링하기 (0) 2019.11.18 webpack 완전 초보들을 위한 기초 (0) 2019.10.18