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는 밀접하게 관련되어 있으며 요소가 얼마나 표시되는지 알려줍니다. 이 정보를 활용하면 애셋이 화면에 표시되기 전에 적시에 로드하는 등의 기능을 구현할 수 있습니다. 효율적으로.
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]로 변경하면 요소의 추가 1/4이 표시될 때마다 알림을 받게 됩니다.
다른 옵션이 있나요?
현재로서는 위에 나열된 옵션 외에 추가 옵션이 하나만 있습니다. rootMargin를 사용하면 루트의 여백을 지정할 수 있으므로 교차에 사용되는 영역을 효과적으로 늘리거나 줄일 수 있습니다. 이러한 여백은 CSS 스타일 문자열(예: "10px 20px 30px 40px")을 사용하여 지정되며 각각 위쪽, 오른쪽, 아래쪽, 왼쪽 여백을 지정합니다. 요약하자면 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을(를) 사용할 수 있습니다. 어떤 아이디어가 떠올랐는지 알려주세요.