프론트엔드 프로젝트에서 초기 로딩 성능(LCP, Largest Contentful Paint) 개선은 매우 중요한 요소다. 특히 콘텐츠 양이 많고 무한스크롤 구조를 사용하는 경우, 화면에 보이지 않는 컴포넌트를 미리 렌더링하지 않도록 최적화하는 것이 핵심이다.
이를 위해 사용할 수 있는 대표적인 두 가지 라이브러리가 있다.
| 구분 | react-lazyload | react-intersection-observer |
|---|---|---|
| 목적 | 화면에 보일 때만 컴포넌트를 렌더링 (Lazy 렌더링) | 화면에 들어왔는지 감지하여 특정 로직 실행 (e.g. 데이터 패칭) |
| 동작 방식 | 스크롤 이벤트 + 높이 계산 | 브라우저의 IntersectionObserver API 사용 |
| 주요 사용 사례 | 이미지 렌더링 최적화 | 무한스크롤, 뷰포트 진입 시 데이터 로딩 |
| 제어 범위 | 제한적 (컴포넌트 감싸기만 가능) | 유연함 (ref, inView 등으로 상태 제어 가능) |
| SSR 환경 | 제한적 | 더 나은 호환성 |
| 유지 상태 | 유지 중이나 오래됨 | 최신 방식, 활발히 유지됨 |
IntersectionObserver란?
브라우저에서 어떤 요소가 화면에 보이는지 자동으로 감지해주는 기능
사용 예시
const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { console.log('요소가 화면에 보여요!'); } }); }); ㅤ observer.observe(document.querySelector('#target'));
#target요소가 화면에 들어오면 콜백이 실행- 직접 스크롤 이벤트 처리 안 해도 됨
스크롤에 따라 필요한 데이터만 로드 + 필요한 컴포넌트만 렌더링 구조로 변경IntersectionObserver로 뷰포트 진입 시 필요한 데이터만 불러오도록 설계fetchNextPage() 실행react-lazyload는 단순 렌더링 제어만 가능하여 무한스크롤 감지에 부적합import { useInView } from 'react-intersection-observer';
import { useEffect } from 'react';
function InfiniteList({ items, fetchNextPage, hasNextPage }) {
const { ref, inView } = useInView({ threshold: 0.1 });
useEffect(() => {
if (inView && hasNextPage) {
fetchNextPage();
}
}, [inView, hasNextPage]);
return (
<>
{items.map((item) => (
<div key={item.id}>{item.name}</div>
))}
<div ref={ref}>로딩 중...</div>
</>
);
}
| 목적 | 추천 라이브러리 | 이유 |
|---|---|---|
| 이미지나 컴포넌트를 보일 때만 렌더링 | react-lazyload | 간편한 렌더링 최적화에 적합 |
| 콘텐츠 하단 진입 시 데이터 패칭 또는 스크롤 감지 | react-intersection-observer | 무한스크롤, 인터랙션 감지, LCP 개선에 효과적 |
| 무한스크롤 + LCP 개선 | react-intersection-observer | 초기 렌더링 최소화, 뷰포트 기반 로딩, 성능 최적화 가능 |