지영이의 개발 블로그

[자바스크립트]IntersectionObserver 본문

Javascript

[자바스크립트]IntersectionObserver

이지영 2022. 5. 11. 10:11

인스타그램과 페이스북처럼 스크롤을 할때마다 새로운 피드를 불러오기 위해 서는 어떻게 해야 할까?

(특정 위치에 스크롤이 도달하였을 때 미리 정의해 둔 이벤트를 적용하려면 어떻게 해야 할까)

자바스크립트의 intersection observer (인터섹션 옵서버)라는 API를 사용해 간단히 구현할수있다.

인터섹션 옵저버

 

인터섹션 옵저버 API가 없을 때에는 Scroll 이벤트를 통해서 해당 이벤트를 구현하였다.

하지만 이 방법은 단 시간에 스크롤 이벤트가 매우 많이 호출되고 동기적으로 실행되며 한 페이지에 여러 엘리먼트에 이벤트가 등록되어 있는 경우에는 사용자가 스크롤을 할 때마다 스크롤을 감지하는 이벤트가 끊임없이 동작하게 되며 이는 메인 스레드에 영향을 주며 성능에 매우 안 좋은 영향을 주게 된다.

이런 문제점을 해결하기 위해 인터섹션 옵서버를 사용하여 구현하게 되면 비동기적으로 실행되며 리플로우 현상 문제점이 발생하지 않는다.

 

mdn에서는 Intersection Observer API를 아래와 같이 정의하고 이다.

역사적으로 요소의 가시성이나 두 요소의 상대적인 가시성을 탐지하는 것은 어려운 일이었습니다. 일반적으로 알려진 해결방법은 신뢰성이 부족하고 브라우저나 사이트에 부하를 주기때문에 좋지 못한 사용자 경험을 낳습니다. 웹이 성숙함에따라 이러한 정보의 필요성은 커졌습니다. intersection 정보는 아래와 같은 여러가지 이유 때문에 필요합니다:

  • 페이지가 스크롤 되는 도중에 발생하는 이미지나 다른 컨텐츠의 지연 로딩.
  • 스크롤 시에, 더 많은 컨텐츠가 로드 및 렌더링되어 사용자가 페이지를 이동하지 않아도 되게 하는 infinite-scroll(무한스크롤) 을 구현.
  • 광고 수익을 계산하기 위한 용도로 광고의 가시성 보고.
  • 사용자에게 결과가 표시되는 여부에 따라 작업이나 애니메이션을 수행할 지 여부를 결정.

 

IntersectionObserverEntry의 속성을 활용하면 getBoundingClientRect()를 호출한 것과 같은 결과를 알 수 있기 때문에 따로  getBoundingClientRect() 함수를 호출할 필요가 없어 리플로우 현상을 방지할 수 있다.

 

인터섹션 옵서버 사용 방법

 

IntersectionObserver 생성

인터섹션 옵저버 생성자는 entries 배열을 인자로 받는 콜백 함수를 전달받아 생성하고, 생성한 옵저버 객체의 .observe 메서드를 사용해 지정한 DOM 요소의 인터섹션(화면 노출) 여부를 감지합니다.

 

클래스명이 box인 모든요소들의 인터섹션 여부를 검사해보면

box가 화면에서 사라지거나 다시 나타날 때마다 IntersectionObserverEntry 객체의 배열이 출력되고 있는것을 볼수있습니다.

methods

1.observe() : 대상 요소의 관찰을 시작합니다.                                                                                          
2.unobserve():대상 요소의 관찰을 중지합니다. 관찰이 목적이 이루어져 굳이 계속 관찰을 할 필요가 없는 경우 사용.
3.disconnect():인스턴스가 관찰하는 모든 요소의 관찰을 중지합니다.
4.takeRecords():intersectionobseverentry 객체의 배열을 반환합니다

callback

관찰할 대상(Target)이 등록되거나 가시성(visibility, 보이는지 보이지 않는지)에 변화가 생기면 관찰자는 콜백(callback)을 실행한다.

callback은 2개의 인수(entries, observer)를 가집니다.

 

intersectionObserverEntry는 읽기 전용의 다음 속성들을 포함한다. 

entries

1.boundingClientRect  : 관찰 대상의 사각형 정보를 반환한다. 이 값은 Element.getBoundingClientRect()를 사용해 동일하게 얻을 수 있다.
2.intersectionRec : 관찰 대상과 루트 요소와 교차하는 영역에 대한 사각형 정보를 반환한다.
3.intersectRatio : 관찰 대상이 루트 요소와 얼마나 교차하는지의 수치를 0과 1 사이의 숫자로 반환한다
4.intersecting : 현재 엘리먼트가 루트에 대해 교차하고 있는지의 여부에 대해 판단해주는 boolean 값이다.
5.rootBounds : 루트 요소에 대한 사각형 정보를 반환한다.
6.target : 관찰 대상(Element)을 반환한다.
7.time : 문서가 작성된 시간을 기준으로 교차 상태 변경이 발생한 시간을 나타내는 DomHighResTimesStamp를 반환한다.
8.unobserve : 해당 엔트리에 더 이상 observe 하지 않겠다는 의미로 한 번만 효과를 주고 싶을 때 유용.

 

 

감지 비율 설정하기 : threshold 옵션

이번에는 모든 요소의 인터섹션을 감지해, 요소가 화면에 나타날 때마다 애니메이션을 추가해 보겠습니다.

 

요소가 1픽셀이라도 뷰포트에 위치하면 콜백이 호출되는데요, 요소가 감지되는 비율을 조금 조정하고 싶다면 옵저버 객체에 threshold 라는 옵션을 추가로 전달할 수도 있습니다.

 

ex) threshold: 0.5 옵션을 통해 요소가 반쯤 보일 때 애니메이션을 적용할 수 있다.

 

options

1.root: defaut : null , 브라우저의 viewport
교차영역의 기준이 될 root 엘리먼트. observe의 대상으로 등록할 엘리먼트는 반드시 root의 하위 엘리먼트여야 한다.
옵션을 지정하지 않을 경우 브라우저 화면에서 현재 보이는 영역인 뷰포트가 기본이 됩니다.


 2.rootMargin : default : '0px 0px 0px 0px ' root엘리먼트의 마진 값.
css에서 margin을 사용하는 방법으로 선언할 수 있고, px와 %로 표현할 수 있다. 이 옵션을 이용하면 이미지 동적 로딩에서 해당 엘리먼
트가 화면에 나타나기 전에 이미지를 불러오기 시작해 이미지 공백을 줄이는데 유용하게 이용할 수 있습니

 
3.threshold : default : 0 
threshold 옵션은 엘리먼트가 콜백 함수의 호출 시점을 정하는 옵션입니다.0과 1을 포함한 그 사이의 숫자 또는 숫자 배열을 지정할 수 있는데 이 숫자는 엘리먼트의 전체 영역 중에 현재 보이는 영역의 비율입니다. 이 비율의 경계를 넘나들 때마다 콜백 함수가 호출됩니다.

 

+옵저버 감지 해제하기

스크롤을 올리고 내릴때 모두 옵저버 객체의 콜백을 호출하고 있는데요, 만약 콜백 함수에 이미지를 페칭하는 로직이 있다면 스크롤을 다시 위로 올릴 때에도 불필요한 페칭을 수행하게 될 것입니다.

불필요한 페칭을 수행하는 대신, 한번 화면에 나타난 요소는 감지를 해제해 단 한번만 콜백이 호출되도록 수정해 보겠습니다.

이제 이미지를 내릴 때만 애니메이션이 적용되고, 올릴 때는 일반적인 스크롤을 수행하는 모습입니다!

이미지//

 


전체코드 방법 

See the Pen Untitled by jiyounggo (@jiyounggo) on CodePen.

 

더많은 기능을 구현해보고 싶다면 🎁https://jssq2468.tistory.com/64?category=1009601🎁

 

사이트로 이동해서 인터섹션 옵저를 이용해 다양한 기능을 구현해보자

 

Comments