img 로딩 패턴
📻

img 로딩 패턴

작성일
2024년 10월 16일
태그
카테고리
JavaScript
Last edited time
Last updated October 20, 2024
날짜
 

이미지를 로딩후 삽입하기.

img 태그의 load 이벤트리스너를 이용해서 로딩을 시킨 후 이미지를 삽입하는 코드.
const loadImg = function (url, callback) { const img = document.createElement('img'); img.src = url; img.addEventListener('load', function () { callback(img); }); } const containerEl = document.querySelector('.container'); loadImg('https://picsum.photos/200/300', function (img) { containerEl.innerHTML = ''; containerEl.appendChild(img); });
🔥
이미지태그를 생성해서 이미지를 로드 후 이미지를 삽입하는 형식! 이러면 이미지태그가 새로 생성되기 때문에 이미지를 2번 로드하는것이 아니냐는 의문이 들 수 있는데, 브라우저는 이미지 url을 캐싱하기때문에 2번 패칭하는 일은 일어나지 않는다.
 

lazy load 예제

 
interception observer api 를 사용해서 이미지를 로딩하는예제. 뷰포트에 들어오기전까지 이미지를 로딩하지 않는다
notion image
img 출처:
 
<!-- src를 비워두고 data-src에 값 전달 --> <img data-src="image.jpg" alt="Lazy Loaded Image" class="lazy-image">
const images = document.querySelectorAll('.lazy-image'); const options = { root: null, // 뷰포트가 기준 rootMargin: '0px', threshold: 0.1 }; const callback = (entries, observer) => { entries.forEach(entry => { // 교차되면 src 삽입 if (entry.isIntersecting) { const img = entry.target; img.src = img.getAttribute('data-src'); observer.unobserve(img); // 관찰 중지 } }); }; const observer = new IntersectionObserver(callback, options); images.forEach(image => { observer.observe(image); });
 

react 에서 응용

import React, { useEffect, useRef, useState } from 'react'; function LazyImage({ src, alt }) { const imgRef = useRef(null); const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { const options = { root: null, threshold: 0.1, }; const callback = (entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { setIsLoaded(true); observer.unobserve(entry.target); } }); }; const observer = new IntersectionObserver(callback, options); if (imgRef.current) { observer.observe(imgRef.current); } return () => { if (imgRef.current) { observer.unobserve(imgRef.current); } }; }, []); return ( <img ref={imgRef} src={isLoaded ? src : ''} alt={alt} style={{ minHeight: '200px', backgroundColor: '#f0f0f0' }} /> ); } export default LazyImage;
 

use inview 라이브러리 활용

훅으로 만들어져있어 편하게 활용가능
import React from 'react'; import { useInView } from 'react-intersection-observer'; function LazyImage({ src, alt }) { const { ref, inView } = useInView({ threshold: 0.1, triggerOnce: true, }); return ( <img ref={ref} src={inView ? src : ''} alt={alt} style={{ minHeight: '200px', backgroundColor: '#f0f0f0' }} /> ); } export default LazyImage;