반응형
IntersectionObserver는 웹 개발에서 아주 유용한 API 이다.
이 API는 특정 요소(target)가 뷰포트나 지정한 컨테이너와 교차하는 정도를
비동기적으로 감지할 수 있게 해준다.
즉 스크롤할 때 요소가 화면에 나타나거나 사라지는 시점을 효율적으로 파악할 수 있도록 해준다.
IntersectionObserver를 사용하는 이유
- 성능 최적화
- 스크롤 이벤트를 직접 감시하는 방식은 매번 스크롤 이벤트가 발생할때마다
많은 연산을 해야하기 때문에 성능 이슈가 발생할 수 있다.
IntersectionObsever는 브라우저가 최적화한 방식으로 감지하므로 성능 부담이 적다는 장점이 있다. - 간편한 API
- 요소가 화면에 들어왔는지 여부를 쉽게 감지할 수 있어, lazy loading (이미지나 리소스의 지연 로딩) 또는
애니메이션 트리거 등에 유용하게 사용할 수 있다.
동작원리
- 관찰 대상 설정 : 개발자는 감시하고 싶은 요소 (ex: img, section 등)를 선택한다.
- 교차 상태 감지 : 브라우저는 이 요소가 뷰포트 또는 특정 부모 컨테이너와 얼마나 교차(intersect)하는지를 감지한다.
- 비동기 콜백 (async & await callback) 실행 : 요소가 설정한 기준 (ex: 일정 비율 이상 보임) 에 도달하면
미리 지정한 콜백 함수가 호출된다.
이 콜백 함수에서는 요소가 보이기 시작했을 때 필요한 작업 (ex: animation 실행, lazy loading등)을 수행할 수 있다.
주요 옵션 및 속성
▼ threshold
- 0부터 1사이의 숫자 또는 숫자 배열로, 요소가 어느 정도 보였을 때 콜백을 실행할지를 결정한다.
예를 들어 threshold가 0.5라면, 해당 요소의 50% 이상이 뷰표트에 들어왔을 때 콜백 함수가 호출된다.
▼ root
- 기본값은 브라우저의 뷰포트이다.
만약 특정 컨테이너 내에서 교차 여부를 감지하고 싶다면, 해당 컨테이너 요소를 root로 지정할 수 있다.
▼ rootMargin
- 뷰포트의 경계를 확장하거나 축소할 수 있는 마진을 설정한다.
예를 들어 '0px 0px -100px 0px'와 같이 설정하면 뷰포트 하단에서 100px 만큼 여유를 두어
그 영역에 들어올 때 콜백을 실행할 수 있다.
이는 요소가 실제로 완전이 보이기 전에 미리 작업을 시작할 수 있게 도와준다.
// 사용 예제
{
// thershold: 요소가 보이는 비율을 설정
threshold: 0.5, // 이 값을 높이면 요소가 일정 비율 이상 보일 때까지 애니메이션이 실행되지 않음
// rootMargin: 뷰포트 경계에 대해 추가적인 마진을 설정
rootMargin: '0px 0px -100px 0px', // 음수 값을 늘리면 요소가 뷰포트에 들어오기 전에 애니메이션을 늦출 수 있음
}
IntersectionObserverEntry 객체
콜백 함수는 IntersectionObserver 객체를 배열 형태로 전달받는다.
이 객체에는 다음과 같은 중요한 속성들이 있다.
- isIntersecting: 요소가 현재 교차 상태인지 (true/false)
- intersectionRatio: 요소가 뷰포트와 얼마나 곂치는지를 나타내는 비율 (0~1)
- target: 감시 중인 실제 DOM 요소
- boundingClientRect, intersectionRect, rootBounds: 요소와 뷰포트의 위치와 크기에 대한 정보를 제공
// IntersectionObserver객체 및 옵션 사용 예제
import { useEffect, useRef } from 'react';
// useScrollReveal custom hook - 요소가 뷰포트에 일정 비율 이상이 보이면 'fade-in' 클래스를 추가.
const useScrollReveal = (threshold = 0.1) => {
// threshold 매개변수는 기본값이 0.1 (요소가 10% 보이면 애니메이션 효과를 트리거)
const elementRef = useRef(null); // 관찰할 요소에 대한 참조를 생성
useEffect(() => {
const element = elementRef.current; // 실제 DOM 요소에 접근
if (!element) return; // 요소가 없으면 진행 X
// IntersectionObserver 생성
const observer = new IntersectionObserver(
([entry]) => {
// entry.inIntersectiong이 true이면 요소가 뷰포트 내에 일정 비율 이상 보임
if (entry.isIntersecting) {
entry.target.classList.add('fade-in'); // fade-in 클래스 추가
observer.unobserve(entry.target); // 한번 애니메이션이 실행되면 중지
}
},
{
// thershold: 요소가 보이는 비율을 설정
threshold: 0.5, // 이 값을 높이면 요소가 일정 비율 이상 보일 때까지 애니메이션이 실행되지 않음
// rootMargin: 뷰포트 경계에 대해 추가적인 마진을 설정
rootMargin: '0px 0px -100px 0px', // 음수 값을 늘리면 요소가 뷰포트에 들어오기 전에 애니메이션을 늦출 수 있음
}
);
observer.observe(element); // oberver를 이용해 실제 DOM 요소를 감시하기 시작.
// 컴포넌트가 언마운트될 때 옵저버를 해제하여 메모리 누수 방지
return () => observer.disconnect();
}, [threshold]); // threshold 값이 변경되면 재실행
// 관찰할 DOM 요소의 ref를 반환하고 이 ref를 각 컴포넌트의 ref 속성에 할당하면,
// 해당 요소가 IntersectionObsever에 의해 감시됨.
return elementRef;
};
export default useScrollReveal;
실무 적용
src/
├── components/
│ ├── OOO.jsx
├── hooks/
│ └── useScrollReveal.js
├── App.jsx
├── main.jsx
└── index.css
실제로 리액트 같은 프레임워크에서 IntersectionObserver를 사용할 때는
커스텀 훅 (useScrollReveal) 등을 만들어 각 컴포넌트에 쉽게 적용할 수 있다.
- 각 섹션이나 컴포넌트의 초기 CSS 상태를 opacity-0 또는 transform translate-y-10과 같이 설정해두고
InterSectionObserver가 감지되면 fade-in 클래스를 추가하여 애니메이션을 적용한다.
@tailwind base;
@tailwind components;
@tailwind utilities;
html {
scroll-behavior: smooth;
}
body {
font-family: 'Inter', sans-serif;
}
.dark {
color-scheme: dark;
}
/* IntersectionObserver 초기 CSS 상태 - fade-in 클래스 적용*/
.fade-in {
opacity: 1 !important;
transform: translateY(0) !important;
}
- 이 방법으로 lazy loading, 애니메이션 트리거, 인피니트 스크롤등 다양한 기능을 손쉽게 구현할 수 있다.
이와 같이 IntersectionObserver는 웹 페이지의 성능 최적화와 사용자 경험 향상에 매우 유용한 도구이다.
실제 적용 시에는 프로젝트의 요구사항에 맞게 threshold, rootMargin등 옵션을 조절하여
최적의 타이밍에 원하는 효과를 낼 수 있도록 설정할 수 있다.
반응형
'React' 카테고리의 다른 글
React - useRef (0) | 2025.03.12 |
---|---|
React- React에서 인라인 스타일 사용하기 (0) | 2025.02.28 |
React - React의 렌더링 방식 : State (0) | 2025.02.27 |
React - State (0) | 2025.02.26 |
React - children props (0) | 2025.02.21 |