본문 바로가기
Javascript

[이미지] Lazy Loading에 대한 고찰

by F.E.D 2020. 2. 15.

이 글은 하단 출처에서 발췌하여 필요한 부분만 따로 정리한 글입니다.

 

이미 지연 로딩이 실행되는 것을 본 적이 있을 것입니다. 지연 로딩은 다음과 같이 진행됩니다.

  • 페이지에 도달하여 콘텐츠를 읽으면서 스크롤을 시작합니다.
  • 특정 지점에서 자리표시자 이미지를 표시 영역으로 스크롤합니다.
  • 자리표시자 이미지가 순간 최종 이미지로 교체됩니다.

출처 : https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video?hl=ko

<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")

출처 : https://meetup.toast.com/posts/183

위의 네이티브 레이지 로딩 속성이 사용 가능한 브라우저 및 플랫폼인지 아닌지의 체크도 시도해 볼 수 있겠습니다.

if ('loading' in HTMLImageElement.prototype) alert("네이티브 레이지 로딩 지원함"); else alert("지원 안함");

출처 : https://meetup.toast.com/posts/183

위처럼 처리함으로써 얻게되는 이득은 모든 플랫폼 및 브라우저에서 레이지 로딩을 일으킬 수 있다는 것입니다.

 

'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

댓글