이 글은 하단 출처에서 발췌하여 필요한 부분만 따로 정리한 글입니다.
이미 지연 로딩이 실행되는 것을 본 적이 있을 것입니다. 지연 로딩은 다음과 같이 진행됩니다.
- 페이지에 도달하여 콘텐츠를 읽으면서 스크롤을 시작합니다.
- 특정 지점에서 자리표시자 이미지를 표시 영역으로 스크롤합니다.
- 자리표시자 이미지가 순간 최종 이미지로 교체됩니다.
<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="저는 이미지입니다!">
현대의 브라우저는 Intersection observer API를 통해 요소 확인 작업을 수행하는 더욱 우수하고 효율적인 방식을 제공합니다.
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.srcset = lazyImage.dataset.srcset;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Possibly fall back to a more compatible method here
}
});
예시 동영상
CSS에서도 이미지 레이지 로딩을 경험할 수 있습니다.
<div class="lazy-background">
<h1>Here's a hero heading to get your attention!</h1>
<p>Here's hero copy to convince you to buy a thing!</p>
<a href="/buy-a-thing">Buy a thing!</a>
</div>
.lazy-background {
background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}
.lazy-background.visible {
background-image: url("hero.jpg"); /* The final image */
}
document.addEventListener("DOMContentLoaded", function() {
var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));
if ("IntersectionObserver" in window) {
let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
lazyBackgroundObserver.unobserve(entry.target);
}
});
});
lazyBackgrounds.forEach(function(lazyBackground) {
lazyBackgroundObserver.observe(lazyBackground);
});
}
});
video도 poster를 통해서 먼저 로딩되는 현상을 피해야 한다
<video autoplay muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
<source data-src="one-does-not-simply.webm" type="video/webm">
<source data-src="one-does-not-simply.mp4" type="video/mp4">
</video>
위의 예를 보면 직접적인 video 컨텐츠는 source에 보관되기 때문에 다음과 같이 javascript를 통한 레이지로딩이 가능합니다.
document.addEventListener("DOMContentLoaded", function() {
var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));
if ("IntersectionObserver" in window) {
var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(video) {
if (video.isIntersecting) {
for (var source in video.target.children) {
var videoSource = video.target.children[source];
if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") {
videoSource.src = videoSource.dataset.src;
}
}
video.target.load();
video.target.classList.remove("lazy");
lazyVideoObserver.unobserve(video.target);
}
});
});
lazyVideos.forEach(function(lazyVideo) {
lazyVideoObserver.observe(lazyVideo);
});
}
});
<video> 요소를 지연 로드할 때, 모든 하위 <source> 요소에 걸쳐 반복하고 data-src 속성을 src 속성으로 전환해야 합니다. 이것을 완료하면 해당 요소의 load 방식 호출을 통해 동영상 로딩을 트리거해야 합니다.
그 후 미디어가 autoplay 속성마다 자동으로 재생을 시작합니다.
자바스크립트를 항상 이용할 수 있다고 가정해서는 안 됩니다. 이미지를 지연 로드하려면 자바스크립트를 사용할 수 없는 경우에 이미지를 data-* 속성에 넣어두었지만 다시 제대로 노출해주어야 합니다.
<!-- An image that eventually gets lazy loaded by JavaScript -->
<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load.jpg" alt="저는 이미지입니다!">
<!-- An image that is shown if JavaScript is turned off -->
<noscript>
<img src="image-to-lazy-load.jpg" alt="저는 이미지입니다!">
</noscript>
네이티브 레이지 로딩 속성 (loading="lazy")
위의 네이티브 레이지 로딩 속성이 사용 가능한 브라우저 및 플랫폼인지 아닌지의 체크도 시도해 볼 수 있겠습니다.
if ('loading' in HTMLImageElement.prototype) alert("네이티브 레이지 로딩 지원함"); else alert("지원 안함");
위처럼 처리함으로써 얻게되는 이득은 모든 플랫폼 및 브라우저에서 레이지 로딩을 일으킬 수 있다는 것입니다.
'Javascript' 카테고리의 다른 글
JS 이벤트 루프(callback, setTimeout, queue, 싱글스레드) (0) | 2020.03.29 |
---|---|
JavaScript에서 Priavate 구현 (0) | 2020.03.15 |
var, let & const 이해하기 (0) | 2019.12.15 |
반복문 없이 반복문 하기 (0) | 2019.09.14 |
Javscript Callback (0) | 2019.09.12 |
댓글