이미지 지연 로드

이미지는 HTML에서 <img> 요소 또는 CSS 배경 이미지로 인라인으로 표시되므로 웹페이지에 표시될 수 있습니다. 이 게시물에서는 두 가지 유형의 이미지를 모두 지연 로드하는 방법을 알아봅니다.

인라인 이미지

가장 일반적인 지연 로드 후보는 <img> 요소에 사용되는 이미지입니다. 인라인 이미지에는 지연 로드의 세 가지 옵션이 있으며, 여러 브라우저에서 최상의 호환성을 위해 함께 사용할 수 있습니다.

브라우저 수준 지연 로드 사용

Chrome과 Firefox 모두 loading 속성을 사용하여 지연 로드를 지원합니다. 이 속성은 <img> 요소와 <iframe> 요소에도 추가할 수 있습니다. 값 lazy은 이미지가 표시 영역에 있으면 즉시 로드하고 사용자가 이미지 근처로 스크롤하면 다른 이미지를 가져오도록 브라우저에 지시합니다.

브라우저 지원에 관한 자세한 내용은 MDN 브라우저 호환성 표의 loading 필드를 참고하세요. 브라우저에서 지연 로드를 지원하지 않으면 이 속성은 무시되고 이미지가 정상적으로 즉시 로드됩니다.

대부분의 웹사이트에서 이 속성을 인라인 이미지에 추가하면 성능이 향상되며 사용자가 스크롤하지 않을 이미지를 로드하는 것을 방지할 수 있습니다. 이미지가 많고 지연 로드의 이점을 지원하지 않는 브라우저 사용자에게도 이를 적용하려면 이를 다음에 설명된 방법 중 하나와 결합해야 합니다.

자세한 내용은 브라우저 수준 웹용 지연 로드를 참고하세요.

Intersection Observer 사용

<img> 요소의 지연 로드를 폴리필하기 위해 자바스크립트를 사용하여 표시 영역에 있는지 확인합니다. 사용 설정되어 있으면 src (때로는 srcset) 속성이 원하는 이미지 콘텐츠의 URL로 채워집니다.

이전에 지연 로드 코드를 작성한 적이 있다면 scroll 또는 resize와 같은 이벤트 핸들러를 사용하여 작업을 완료했을 수 있습니다. 이 접근 방식이 브라우저 간에 가장 호환되지만 최신 브라우저에서는 Intersection Observer API를 통해 요소 가시성을 확인하는 작업을 더 우수하고 효율적인 방법을 제공합니다.

Intersection Observer는 지루한 요소 공개 상태 감지 코드를 작성하는 대신 관찰자를 감시 요소에만 등록하면 되므로 다양한 이벤트 핸들러에 의존하는 코드보다 사용과 읽기가 더 쉽습니다. 이제 요소가 표시될 때 실행할 작업을 결정하기만 하면 됩니다. 지연 로드되는 <img> 요소에 다음과 같은 기본 마크업 패턴을 사용한다고 가정해 보겠습니다.

<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="I'm an image!">

이 마크업에서 중점을 두어야 하는 세 가지 관련 요소가 있습니다.

  1. JavaScript에서 요소를 선택하는 class 속성
  2. src 속성: 페이지가 처음 로드될 때 표시되는 자리표시자 이미지를 참조합니다.
  3. data-srcdata-srcset 속성. 요소가 표시 영역에 있으면 로드할 이미지의 URL이 포함된 자리표시자 속성입니다.

이제 자바스크립트에서 Intersection Observer를 사용하여 다음 마크업 패턴으로 이미지를 지연 로드하는 방법을 살펴보겠습니다.

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 event handlers here
  }
});

문서의 DOMContentLoaded 이벤트에서 이 스크립트는 lazy 클래스가 있는 모든 <img> 요소의 DOM을 쿼리합니다. Intersection Observer를 사용할 수 있는 경우 img.lazy 요소가 표시 영역에 진입할 때 콜백을 실행하는 새 관찰자를 만듭니다.

Intersection Observer는 모든 최신 브라우저에서 사용할 수 있습니다. 따라서 loading="lazy"의 폴리필로 사용하면 대부분의 방문자가 지연 로드를 사용할 수 있습니다.

CSS의 이미지

<img> 태그는 웹페이지에서 이미지를 사용하는 가장 일반적인 방법이지만 CSS background-image 속성 및 기타 속성을 통해서도 이미지를 호출할 수 있습니다. 브라우저 수준의 지연 로드는 CSS 배경 이미지에는 적용되지 않으므로 지연 로드할 백그라운드 이미지가 있는 경우 다른 방법을 고려해야 합니다.

공개 상태와 관계없이 로드되는 <img> 요소와 달리 CSS의 이미지 로드 동작은 더 많은 추측으로 실행됩니다. 문서 및 CSS 객체 모델렌더링 트리가 빌드되면 브라우저는 외부 리소스를 요청하기 전에 CSS가 문서에 적용되는 방식을 검사합니다. 외부 리소스와 관련된 CSS 규칙이 현재 구성된 대로 문서에 적용되지 않는다고 브라우저에서 판단하면 브라우저가 이를 요청하지 않습니다.

이러한 예측 동작은 JavaScript를 사용하여 요소가 표시 영역 내에 있는지 확인하고 배경 이미지를 호출하는 스타일을 적용하는 클래스를 해당 요소에 적용하여 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>

div.lazy-background 요소에는 일반적으로 일부 CSS에서 호출한 히어로 배경 이미지가 포함됩니다. 그러나 이 지연 로드 예에서는 요소가 표시 영역에 있을 때 요소에 추가된 visible 클래스를 통해 div.lazy-background 요소의 background-image 속성을 격리할 수 있습니다.

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

여기에서 JavaScript를 사용하여 요소가 표시 영역에 있는지 확인하고 (Intersection Observer! 사용) 그 시점에 이미지를 로드하는 div.lazy-background 요소에 visible 클래스를 추가합니다.

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);
    });
  }
});

최대 콘텐츠 페인트 (LCP)에 미치는 영향

지연 로드는 이미지 로드를 실제로 필요한 시점에 지연하여 시작 시 전반적인 데이터 사용량과 네트워크 경합을 모두 줄이는 훌륭한 최적화 기능입니다. 이를 통해 시작 시간을 개선하고 이미지 디코딩에 필요한 시간을 줄여 기본 스레드의 처리를 줄일 수 있습니다.

하지만 지연 로드는 사용자가 지연 로드 기술에 너무 관심이 있는 경우 웹사이트의 최대 콘텐츠 페인트 LCP에 부정적인 영향을 줄 수 있는 기법입니다. 한 가지는 시작 시 표시 영역에 표시되는 이미지의 지연 로드를 피해야 합니다.

JavaScript 기반 지연 로더를 사용하는 경우 표시 영역 내 이미지의 지연 로드를 피하는 것이 좋습니다. 이러한 솔루션에서 data-src 또는 data-srcset 속성을 srcsrcset 속성의 자리표시자로 사용하는 경우가 많기 때문입니다. 여기서 문제는 브라우저 미리 로드 스캐너가 시작 시 이미지를 찾을 수 없어 이러한 이미지의 로드가 지연된다는 점입니다.

브라우저 수준의 지연 로드를 사용하여 표시 영역 내 이미지를 지연 로드해도 역효과가 날 수 있습니다. 표시 영역 내 이미지에 loading="lazy"를 적용하면 이미지가 표시 영역에 있음을 브라우저에서 인식할 때까지 이미지가 지연되며 이는 페이지의 LCP에 영향을 미칠 수 있습니다.

시작 시 표시 영역에 표시되는 이미지를 지연 로드하지 마세요. 이는 사이트의 LCP에 부정적인 영향을 주어 사용자 경험에 부정적인 영향을 미치는 패턴입니다. 시작 시 이미지가 필요한 경우 지연 로드를 사용하지 않고 최대한 빨리 시작할 때 이미지를 로드하세요.

라이브러리 지연 로드

가능한 경우 브라우저 수준의 지연 로드를 사용해야 하지만, 상당한 수의 사용자가 여전히 이전 브라우저를 사용하는 등 그렇게 할 수 없는 상황에서는 다음 라이브러리를 사용하여 이미지를 지연 로드할 수 있습니다.

  • laysizes는 모든 기능을 갖춘 지연 로드 라이브러리로, 이미지 및 iframe을 지연 로드합니다. 사용하는 패턴은 <img> 요소의 lazyload 클래스에 자동으로 결합되며 data-src 또는 data-srcset 속성에 이미지 URL을 지정해야 한다는 점에서 여기에 표시된 코드 예시와 매우 유사합니다. 이미지 URL의 콘텐츠는 각각 src 또는 srcset 속성으로 교체됩니다. Intersection Observer (폴리필 가능)를 사용하며 여러 플러그인으로 확장하여 동영상 지연 로드와 같은 작업을 실행할 수 있습니다. 지연 크기 사용에 관해 자세히 알아보기
  • vanilla-latencyload는 지연 로드 이미지, 배경 이미지, 동영상, iframe, 스크립트를 위한 경량 옵션입니다. Intersection Observer를 활용하고, 반응형 이미지를 지원하고, 브라우저 수준의 지연 로드를 사용 설정합니다.
  • lozad.js는 Intersection Observer만 사용하는 또 다른 가벼운 옵션입니다. 따라서 성능은 매우 우수하지만 이전 브라우저에서 사용하려면 먼저 폴리필해야 합니다.
  • React 전용 지연 로드 라이브러리가 필요한 경우 react-latencyload를 고려하세요. Intersection Observer를 사용하지는 않지만 React로 애플리케이션을 개발하는 데 익숙한 사용자에게 익숙한 지연 로드 이미지 방법을 제공합니다.