핵심 요약
무한 스크롤은 scroll 이벤트로 스크롤 위치를 계산하지 말고, 리스트 끝에 둔 빈 "sentinel" 요소를 IntersectionObserver로 감시해 화면에 들어오면 다음 페이지를 부르는 방식이 정석이다. 메인 스레드 부담이 적고 코드도 단순하다.
1. 핵심 구현
const ref = useRef(null)
useEffect(() => {
const io = new IntersectionObserver(([e]) => {
if (e.isIntersecting) loadMore()
}, { rootMargin: '200px' }) // 미리 당겨 로드
if (ref.current) io.observe(ref.current)
return () => io.disconnect()
}, [loadMore])
// 리스트 끝: <div ref={ref} />
2. 체크포인트
rootMargin으로 사용자가 끝에 닿기 전에 미리 로드- 로딩 중·마지막 페이지면 loadMore 호출 막기(중복 방지)
- loadMore는 useCallback으로 안정화
3. 함정
- 관찰 대상이 처음부터 화면 안이면 즉시 발화 — 초기 데이터로 화면을 채운 뒤 sentinel 배치
- 스크롤 위치 복원이 필요하면 가상화(react-virtuoso 등) 고려
- 접근성: 무한 스크롤은 푸터에 도달 못 하니 "더 보기" 대안도 제공
자주 묻는 질문
scroll 이벤트 방식보다 뭐가 나은가요?
scroll은 초당 수십 번 발화해 throttle가 필요하고 레이아웃 계산 비용이 큽니다. IntersectionObserver는 브라우저가 비동기로 처리해 더 가볍고 정확합니다.
중복 요청을 어떻게 막나요?
로딩 상태 플래그와 "다음 페이지 존재" 플래그를 두고, 둘을 만족할 때만 loadMore를 호출하세요.

댓글 0