
프론트엔드
Intersection Observer APIIntersection Observer API
Intersection Observer API는 특정 요소가 뷰포트(또는 부모 요소)와 교차하는지 비동기적으로 감지하는 브라우저 API다. 스크롤 이벤트 없이 효율적으로 요소의 가시성을 추적해 지연 로딩, 무한 스크롤, 애니메이션 트리거에 활용한다.
기본 사용법
javascript
// Observer 생성
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log(entry.target, '가 보입니다!');
console.log('교차 비율:', entry.intersectionRatio);
}
});
},
{
root: null, // null = 뷰포트
rootMargin: '0px', // 마진 (CSS처럼)
threshold: [0, 0.25, 0.5, 0.75, 1.0], // 교차 비율 트리거 지점
}
);
// 요소 관찰
observer.observe(document.querySelector('.target'));
// 관찰 중지
observer.unobserve(element);
observer.disconnect();지연 로딩 구현
javascript
function lazyLoadImage(img) {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
img.src = img.dataset.src;
img.classList.add('loaded');
observer.unobserve(img); // 로드 후 관찰 중지
}
}, { rootMargin: '200px' }); // 200px 전에 로드 시작
observer.observe(img);
}
document.querySelectorAll('img[data-src]').forEach(lazyLoadImage);스크롤 애니메이션
javascript
const animateObserver = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
entry.target.classList.toggle('visible', entry.isIntersecting);
});
},
{ threshold: 0.1 }
);
document.querySelectorAll('.animate-on-scroll').forEach(el => {
animateObserver.observe(el);
});css
.animate-on-scroll {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.animate-on-scroll.visible {
opacity: 1;
transform: translateY(0);
}React Hook으로 추상화
typescript
import { useEffect, useRef, useState } from 'react';
function useIntersectionObserver(options?: IntersectionObserverInit) {
const ref = useRef<HTMLElement>(null);
const [isIntersecting, setIsIntersecting] = useState(false);
useEffect(() => {
const element = ref.current;
if (!element) return;
const observer = new IntersectionObserver(([entry]) => {
setIsIntersecting(entry.isIntersecting);
}, options);
observer.observe(element);
return () => observer.disconnect();
}, []);
return { ref, isIntersecting };
}
// 사용
function LazySection() {
const { ref, isIntersecting } = useIntersectionObserver({ threshold: 0.1 });
return <section ref={ref}>{isIntersecting && <HeavyContent />}</section>;
}관련 개념
- •지연 로딩
- •무한 스크롤
- •Web Workers