[Frontend] 이미지 최적화
프론트엔드 이미지 최적화 방법
1. 뷰포트 밖의 이미지는 나중에 로드하기
2. webp 이미지 형식 사용하기
1. 뷰포트 밖의 이미지는 나중에 로드하기
당장 화면에 먼저 보이는 이미지만 먼저 로드하고
스크롤 아래 이미지는 이미지 영역이 화면에 등장하는 시점에 이미지를 로드하는 방법!!
scroll 할 때마다 이미지 영역이 화면에 들어오는지 체크하는 건 너무 이벤트 호출이 잦기 때문에
IntersectionObserver를 사용할 것이다
IntersectionObserver - Web API | MDN
Intersection Observer API의 IntersectionObserver 인터페이스는 대상 요소와 상위 요소, 또는 대상 요소와 최상위 문서의 뷰포트가 서로 교차하는 영역이 달라지는 경우 이를 비동기적으로 감지할 수 있는
developer.mozilla.org
IntersectionObserver가 생성되면 루트 내에서 설정된 가시성 비율이 자신의 주시 대상 중에서 나타나는지 감지하기 시작
-> DOM 요소 관찰하다가 화면에 나타나는지, 화면에서 사라지는지 포착한다.
// react
const LazyImage = (props) => {
const imgRef = useRef(null);
useEffect(() => {
const options = {...};
const callback = (entries, _observer) => {
entries.forEach((entry) => {
/**
* IntersectionObserver는
* 화면에 DOM 요소가 들어왔을 때,화면에서 나갈 때 두번 콜백 함수를 호출함
* 따라서 화면에 DOM 요소가 들어왔을 때 이미지를 로드 하면 됨
*/
if (entry.isIntersecting) {
// src를 data-src로 교체
entry.target.src = entry.target.dataset.src;
// 이미지 한번 부르면 끝. observe 해제
observer.unobserve(entry.target);
}
});
};
const observer = new IntersectionObserver(callback, options);
observer.observe(imgRef.current);
}, []); // 렌더링 시 1번만 실행하면 됨
// data-src로 이미지의 영역만 갖고 실제 이미지 로드는 되지 않는다
return <img data-src={props.image} ref={imgRef} />;
};
이렇게 하면 이미지 영역이 화면에 들어오는 순간 이미지를 로드하기 시작한다
++ 추가로 img 태그 내 data-src에 대해 간단히 살펴보면
data-* 속성은 표준이 아닌 속성이나 추가적인 DOM 속성과 같은 다른 조작을 하지 않고도, 의미론적 표준 HTML 요소에 추가 정보를 저장할 수 있게 도와줍니다. (https://developer.mozilla.org/ko/docs/Learn/HTML/Howto/Use_data_attributes)
-> DOM에 따로 표시는 안되지만 태그 내에 data-src에 정의한 정보를 가지고 있도록 한다
2. webp 이미지 형식 사용하기
webp는 구글에서 만든 비교적 최신 이미지 형식이다.
그래서 지원하지 않는 브라우저도 있긴함.
하지만 용량이 jpg보다도 작고 화질은 좀 더 낫다는 장점이 있다.
Squoosh
Simple Open your image, inspect the differences, then save instantly. Feeling adventurous? Adjust the settings for even smaller files.
squoosh.app
구글에서 제공해주는 webp 변환 사이트다
대량으로 이미지 변환하기에는 불편해서 cwebp 명령어로도 변환한다고 한다.. < 이걸로는 안해봤다
아무튼 webp를 지원하지 않는 브라우저가 있다보니 분기처리를 해야한다.
picture 태그를 쓰면 간단해진다.
<picture>
<source srcset="photo.webp" type="image/webp" />
<img src="photo.jpg" alt="photo" />
</picture>
source 태그의 WebP를 렌더링 할 수 없는 경우, 아래 img 태그를 로드한다
비슷한 맥락으로 비디오는 webm이 있는데
<video autoplay loop muted playsinline>
<source src="my-video.webm" type="video/webm" />
<source src="my-video.mp4" type="video/mp4" />
</video>
video 태그 아래 source를 두개 놓고
위에 있는 source를 로드 하지 못할 시 아래 source를 로드한다