IntersectionObserver를 사용하면 관찰된 요소가 브라우저의 표시 영역에 진입하거나 종료될 때 이를 알 수 있습니다.
DOM의 요소가 표시되는 표시 영역에 진입하는 시점을 추적하려고 한다고 가정해 보겠습니다. 이미지를 적시에 지연 로드할 수 있도록 하거나 사용자가 실제로 특정 광고 배너를 보고 있는지 확인해야 할 수 있기 때문에 이렇게 할 수 있습니다. 스크롤 이벤트를 연결하거나 주기적 타이머를 사용하고 해당 요소에서 getBoundingClientRect()
를 호출하면 됩니다.
그러나 이 접근 방식은 getBoundingClientRect()
를 호출할 때마다 브라우저가 전체 페이지를 다시 레이아웃하도록 강제하고 웹사이트에 상당한 버벅거림을 유발하므로 매우 느립니다. 사이트가 iframe 내부에서 로드되고 있는 것을 알고 사용자가 언제 요소를 볼 수 있는지 알고 싶다면 거의 불가능합니다. 단일 출처 모델과 브라우저를 사용하면 iframe이 포함된 웹페이지의 데이터에 액세스할 수 없습니다. 이는 iframe을 사용하여 자주 로드되는 광고에서 흔히 발생하는 문제입니다.
IntersectionObserver
는 이 가시성 테스트를 더 효율적으로 만드는 것을 목적으로 설계되었으며 모든 최신 브라우저에 제공됩니다. IntersectionObserver
를 사용하면 관찰된 요소가 브라우저의 표시 영역을 진입하거나 종료할 때 이를 알 수 있습니다.
IntersectionObserver
를 만드는 방법
이 API는 비교적 작으며 예를 사용하여 설명하는 것이 가장 좋습니다.
const io = new IntersectionObserver(entries => {
console.log(entries);
}, {
/* Using default options. Details below */
});
// Start observing an element
io.observe(element);
// Stop observing an element
// io.unobserve(element);
// Disable entire IntersectionObserver
// io.disconnect();
IntersectionObserver
의 기본 옵션을 사용하면 요소가 부분적으로 표시될 때와 완전히 표시 영역을 벗어날 때 모두 콜백이 호출됩니다.
여러 요소를 관찰해야 하는 경우 observe()
를 여러 번 호출하여 동일한 IntersectionObserver
인스턴스를 사용하여 여러 요소를 관찰할 수 있으며 그렇게 하는 것이 좋습니다.
entries
매개변수는 IntersectionObserverEntry
객체의 배열인 콜백에 전달됩니다. 이러한 각 객체에는 관찰된 요소 중 하나의 업데이트된 교차 데이터가 포함됩니다.
🔽[IntersectionObserverEntry]
time: 3893.92
🔽rootBounds: ClientRect
bottom: 920
height: 1024
left: 0
right: 1024
top: 0
width: 920
🔽boundingClientRect: ClientRect
// ...
🔽intersectionRect: ClientRect
// ...
intersectionRatio: 0.54
🔽target: div#observee
// ...
rootBounds
는 기본적으로 표시 영역인 루트 요소에서 getBoundingClientRect()
를 호출한 결과입니다. boundingClientRect
는 관찰된 요소에서 호출된 getBoundingClientRect()
의 결과입니다. intersectionRect
는 이 두 직사각형의 교차점으로, 관찰된 요소의 어떤 부분이 표시되는지 알려줍니다. intersectionRatio
은 밀접한 관련이 있으며 요소가 얼마나 표시되는지 알려줍니다. 이 정보를 사용하면 애셋이 화면에 표시되기 전에 애셋의 JIT 로드와 같은 기능을 구현할 수 있습니다. 효율적으로
IntersectionObserver
는 데이터를 비동기식으로 전송하며 콜백 코드는 메인 스레드에서 실행됩니다. 또한 사양에 따르면 IntersectionObserver
구현은 requestIdleCallback()
를 사용해야 합니다. 즉, 제공된 콜백 호출은 우선순위가 낮으며 유휴 시간 동안 브라우저에서 실행됩니다. 이는 의도적인 디자인 결정입니다.
스크롤 div
요소 내에서 스크롤하는 것은 별로 좋아하지 않지만, 판단하는 것은 저나 IntersectionObserver
의 일이 아닙니다. options
객체는 뷰포트의 대안을 루트로 정의할 수 있는 root
옵션을 사용합니다. root
는 관찰된 모든 요소의 조상여야 한다는 점에 유의해야 합니다.
모든 것을 교차하세요.
아니요 나쁜 개발자! 이는 사용자의 CPU 사이클을 신중하게 사용하지 않는 것입니다. 무한 스크롤러를 예로 들어 보겠습니다. 이 시나리오에서는 DOM에 센티널을 추가하고 이를 관찰 (및 재활용)하는 것이 좋습니다. 무한 스크롤러의 마지막 항목 근처에 센티널을 추가해야 합니다. 이 감시자가 표시되면 콜백을 사용하여 데이터를 로드하고, 다음 항목을 만들고, DOM에 연결하고, 적절하게 감시자를 재배치할 수 있습니다. 센티널을 올바르게 재활용하면 observe()
를 추가로 호출할 필요가 없습니다. IntersectionObserver
은 계속 작동합니다.
더 많은 업데이트가 필요합니다.
앞서 언급한 대로 콜백은 관찰된 요소가 부분적으로 표시될 때 한 번, 표시 영역을 벗어날 때 한 번 트리거됩니다. 이렇게 하면 IntersectionObserver
가 'X 요소가 표시되나요?'라는 질문에 답변을 제공합니다. 하지만 일부 사용 사례에서는 이 방법만으로는 충분하지 않을 수 있습니다.
이때 threshold
옵션이 유용합니다. 이를 통해 intersectionRatio
임곗값 배열을 정의할 수 있습니다. intersectionRatio
가 이러한 값 중 하나를 넘을 때마다 콜백이 호출됩니다. threshold
의 기본값은 [0]
이며, 이는 기본 동작을 설명합니다. threshold
를 [0, 0.25, 0.5, 0.75, 1]
로 변경하면 요소의 4분의 1이 추가로 표시될 때마다 알림이 전송됩니다.
다른 옵션이 있나요?
현재 위에 나열된 옵션에 추가되는 옵션은 하나뿐입니다. rootMargin
를 사용하면 루트의 여백을 지정할 수 있으므로 교차에 사용되는 영역을 효과적으로 늘리거나 줄일 수 있습니다. 이러한 여백은 "10px 20px 30px 40px"
와 같이 CSS 스타일 문자열을 사용하여 지정되며, 각각 상단, 오른쪽, 하단, 왼쪽 여백을 지정합니다. 요약하자면 IntersectionObserver
옵션 구조체는 다음 옵션을 제공합니다.
new IntersectionObserver(entries => {/* … */}, {
// The root to use for intersection.
// If not provided, use the top-level document's viewport.
root: null,
// Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
// If an explicit root element is specified, components may be percentages of the
// root element size. If no explicit root element is specified, using a
// percentage is an error.
rootMargin: "0px",
// Threshold(s) at which to trigger callback, specified as a ratio, or list of
// ratios, of (visible area / total area) of the observed element (hence all
// entries must be in the range [0, 1]). Callback will be invoked when the
// visible ratio of the observed element crosses a threshold in the list.
threshold: [0],
});
<iframe>
매직
IntersectionObserver
는 <iframe>
요소를 자주 사용하고 이러한 요소가 표시되는지 여부를 알면 유용할 수 있는 광고 서비스 및 소셜 네트워크 위젯을 염두에 두고 설계되었습니다. <iframe>
가 요소 중 하나를 관찰하면 <iframe>
를 스크롤할 때와 <iframe>
가 포함된 창을 스크롤할 때 모두 적절한 시점에 콜백이 트리거됩니다. 그러나 후자의 경우 출처 간에 데이터가 유출되지 않도록 rootBounds
가 null
로 설정됩니다.
IntersectionObserver
가 아닌 것은 무엇인가요?
IntersectionObserver
는 의도적으로 픽셀 완벽도나 지연 시간이 짧지 않습니다. 스크롤에 종속된 애니메이션과 같은 작업을 구현하는 데 이를 사용하면 실패할 수밖에 없습니다. 데이터를 사용할 때쯤에는 엄밀히 말해 데이터가 오래되었기 때문입니다. IntersectionObserver
의 원래 사용 사례에 관한 자세한 내용은 설명을 참고하세요.
콜백에서 얼마나 많은 작업을 할 수 있나요?
간단히 요약: 콜백에서 너무 많은 시간을 소비하면 앱이 지연됩니다. 모든 일반적인 관행이 적용됩니다.
요소를 교차하세요.
IntersectionObserver
는 모든 최신 브라우저에서 사용할 수 있으므로 브라우저 지원이 우수합니다. 필요한 경우 이전 브라우저에서 폴리필을 사용할 수 있으며 WICG 저장소에서 사용할 수 있습니다. 물론 이 폴리필을 사용하면 네이티브 구현에서 얻을 수 있는 성능 이점을 얻을 수 없습니다.
지금 바로 IntersectionObserver
을(를) 사용할 수 있습니다. 생각해낸 내용을 알려주세요.