동영상 지연 로드 중

게시일: 2019년 8월 16일

이미지 요소와 마찬가지로 동영상을 지연 로드하는 것이 좋습니다. 동영상은 일반적으로 <video> 요소로 로드되지만 YouTube와 같은 다른 서비스에서 호스팅되는 동영상의 경우 <iframe>를 사용할 수 있습니다 (이 경우 지연 로드 iframe의 도움말을 참고하세요).

<video>를 지연 로드하는 방법은 사용 사례에 따라 다릅니다. 몇 가지 솔루션이 있기 때문입니다.

자동재생되지 않는 동영상

동영상 자동재생은 사용자에게 제어권을 남겨주므로 일반적으로 피하는 것이 좋습니다. 이 경우 <video> 요소에서 preload 속성을 지정하는 것이 전체 동영상을 로드하지 않는 가장 좋은 방법입니다.

<video controls preload="none" poster="one-does-not-simply-placeholder.jpg">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

이전 예에서는 값이 nonepreload 속성을 사용하여 브라우저가 모든 동영상 데이터를 미리 로드하지 못하도록 합니다. poster 속성은 동영상이 로드되는 동안 공간을 차지할 자리표시자를 <video> 요소에 제공합니다.

대부분의 브라우저에서 preload는 기본적으로 metadata로 설정되며 동영상의 일부가 Content-Range 헤더를 사용하여 미리 로드됩니다. 특히 브라우저에서 Content-Range 헤더를 지원하지 않는 경우 원하는 것보다 더 많은 데이터가 다운로드될 수 있습니다. 이 기능이 지원되더라도 브라우저는 메타데이터가 저장된 바이트 위치를 알 수 없으며 파일 시작 부분에 저장되지 않을 수도 있습니다. 따라서 동영상을 로드하지 않는 가장 좋은 방법은 none를 지정하고 preload="none"를 사용하는 것입니다.

이를 더욱 개선하여 사용자가 onmouseenter 속성 (또는 이에 상응하는 mouseenter 이벤트 핸들러)을 사용하여 동영상 위로 마우스를 가져갈 때 메타데이터를 미리 로드할 수 있습니다.

<video controls
  preload="none"
  poster="one-does-not-simply-placeholder.jpg"
  onmouseenter="event.target.setAttribute('preload','metadata')">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

이렇게 하면 사용자가 동영상을 재생할 때 지연이 줄어들 뿐만 아니라 동영상이 재생되자마자 동영상 길이가 표시됩니다.

동영상이 LCP 후보로 선정될 수 있습니다. poster 이미지는 동영상보다 더 빠르게 로드되므로 poster 이미지가 LCP 후보인 경우 포스터 이미지를 사용해야 하지만 fetchpriority 속성 값이 "high"미리 로드해야 합니다.

<link rel="preload" href="one-does-not-simply-placeholder.jpg" as="image" fetchpriority="high">
<video controls preload="none"
  poster="one-does-not-simply-placeholder.jpg"
  onmouseenter="event.target.setAttribute('preload','metadata')">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

애니메이션 GIF 대체 역할을 하는 동영상

자동재생 동영상은 GIF 스타일의 빠른 애니메이션에 가장 일반적으로 사용됩니다. 애니메이션 GIF는 널리 사용되지만 동영상에 비해 여러 가지 면에서 열세입니다(특히 파일 크기). 애니메이션 GIF는 데이터가 몇 메가바이트까지 늘어날 수 있습니다. 시각적 품질이 비슷한 동영상은 훨씬 작습니다.

애니메이션 GIF 대신 <video> 요소를 사용하는 것은 <img> 요소만큼 간단하지 않습니다. 애니메이션 GIF에는 세 가지 특성이 있습니다.

  1. 로드되면 자동으로 재생됩니다.
  2. 연속으로 반복됩니다 (그러지 않을 때도 있음).
  3. 오디오 트랙이 없습니다.

<video> 요소를 사용하여 이를 실행하면 다음과 같이 표시됩니다.

<video autoplay muted loop playsinline>
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

autoplay, muted, loop 속성은 설명이 필요하지 않습니다. playsinline는 iOS에서 자동재생이 실행되기 위해 필요합니다. 이제 여러 플랫폼에서 작동하는 사용 가능한 동영상-GIF 대체 도구가 생겼습니다. 지연 로드하려면 어떻게 해야 하나요? 시작하려면 <video> 마크업을 적절하게 수정하세요.

<video class="lazy" 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> 요소의 공간을 차지할 자리표시자를 지정할 수 있는 poster 속성이 추가된 것을 확인할 수 있습니다. <img> 지연 로드 예와 마찬가지로 각 <source> 요소의 data-src 속성에 동영상 URL을 저장합니다. 그런 다음 Intersection Observer 기반 이미지 지연 로드 예와 유사한 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 속성에 따라 미디어가 자동으로 재생됩니다.

이 방법을 사용하면 애니메이션 GIF 동작을 에뮬레이션하지만 애니메이션 GIF와 동일한 데이터 사용량이 발생하지 않는 동영상 솔루션을 사용할 수 있으며 콘텐츠를 지연 로드할 수 있습니다.

라이브러리 지연 로드

다음 라이브러리를 사용하면 동영상을 지연 로드할 수 있습니다.

  • vanilla-lazyloadlozad.js는 Intersection Observer만 사용하는 초경량 옵션입니다. 따라서 성능이 우수하지만 이전 브라우저에서 사용하려면 먼저 폴리필해야 합니다.
  • yall.js는 Intersection Observer를 사용하고 이벤트 핸들러로 대체되는 라이브러리입니다. data-poster 속성을 사용하여 동영상 poster 이미지를 지연 로드할 수도 있습니다.
  • React용 지연 로드 라이브러리가 필요한 경우 react-lazyload를 사용해 보세요. Intersection Observer는 사용하지 않지만 React로 애플리케이션을 개발하는 데 익숙한 사용자를 위해 이미지를 지연 로드하는 익숙한 메서드를 제공합니다.

이러한 지연 로드 라이브러리는 각각 문서화되어 있으며 다양한 지연 로드 작업을 위한 마크업 패턴이 많이 있습니다.