프론트엔드 개발자이며 페이지 성능에 관심이 있다면 화면에 보이지 않는 이미지를 레이지 로딩하기 위해 IntersectionObserver을 사용해본 사람이 많을 것이다.
IntersectionObserver는 브라우저의 빌트인 자바스크립트 API이며 상대적으로 최신 브라우저들에서만 지원Intersection을 이용한 이미지 레이지로더 커스텀 훅 예시 (이를 제공하는 외부 라이브러리가 있지만 직접 만들어서 사용해보는 것을 추천)
import { useEffect, useRef, useState } from 'react'
interface Params {
src: string
}
const useLazyImageObserver = ({ src }: Params) => {
const [imageSrc, setImageSrc] = useState<string | null>(null)
const imageRef = useRef<HTMLImageElement>(null)
useEffect(() => {
let observer: IntersectionObserver | null = null
if (imageRef && !imageSrc) {
observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setImageSrc(src)
observer!.unobserve(imageRef.current!)
}
},
{ threshold: [0.25] }
)
observer.observe(imageRef.current!)
}
}, [imageRef, imageSrc, src])
return { imageSrc, imageRef }
}
export default useLazyImageObserver
Can't find variable: IntersectionObserver해당 에러가 일어나는 경우는 드물지만 배포 후 서비스를 운영할 때 경험을 했던 문제이다.
이 문제가 일어날 수 있는 경우:
IntersectionObserver을 지원하지 않음IntrersectionObserver은 브라우저 빌트인 API이기 때문에 Node환경에서 코드가 실행이 되었다면 지원이 되지 않음 (window가 없는 경우)Fix:
import { useEffect, useRef, useState } from 'react'
interface Params {
src: string
}
const useLazyImageObserver = ({ src }: Params) => {
const [imageSrc, setImageSrc] = useState<string | null>(null)
const imageRef = useRef<HTMLImageElement>(null)
useEffect(() => {
let observer: IntersectionObserver | null = null
if (imageRef && !imageSrc && 'IntersectionObserver' in window) {
observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setImageSrc(src)
observer!.unobserve(imageRef.current!)
}
},
{ threshold: [0.25] }
)
observer.observe(imageRef.current!)
}
}, [imageRef, imageSrc, src])
return { imageSrc, imageRef }
}
export default useLazyImageObserver
'IntersectinObserver' in window 조건을 통해 IntersectionObserver의 여부를 확인하고 있을 때 만 실행하는 방법으로 간단한 수정이 가능