본문 바로가기

Develop Log/JavaScript

JavaScript - Lazy Loading

반응형

웹 페이지를 이용하는 사용자는 웹 사이트의 로딩 시간과 성능에 대해서 높은 기대치를 가지고 있다.

그렇기 때문에 로딩속도가 짧고 성능이 높은 사이트의 경우에는 많은 이용자가 방문을 하게 되지만 로딩 속도가 느리거나 컨텐츠의 확인에 시간이 걸리는 사이트의 경우 이용자의 이탈률과 불편함이 높아지게 된다.

이러한 문제를 해결하고 전반적인 사용자의 경험을 개선하기 위한 방법 중 하나로 Lazy Loading을 사용한다.

 

Lazy Loading이란?

Lazy Loading이란 웹 페이지의 성능을 최적화하기 위한 기법 중 하나로, 페이지의 로딩 속도를 빠르게 만들기 위해 필요한 리소스(예: 이미지, 스크립트, 동영상 등)를 초기 페이지 로딩 시에 모두 로드하는 것이 아니라 스크롤을 통해 해당 이미지가 화면에 나타나는 순간과 같은 사용자가 해당 리소스가 필요한 시점에 로드하는 방식을 의미한다.

 

Lazy Loading의 이점

대역폭과 서버 부하 감소: 불필요한 리소스를 로드하게 되면 상당한 대역폭을 사용하게 될 수 있어, 사용자와 웹사이트 소유자에게 영향을 준다.

Lazy Loading은 필요한 리소스만 로드하여 대역폭을 절약하는 데 도움이 되는데, 이는 사이트를 방문한 사용자가 아래로 스크롤하지 않을 경우 특히 유용하다.

또한, 요청 시 리소스를 가져오는 것으로 서버 부하를 더 효율적으로 분배하게 도와주는데, 이는 서버의 부담을 줄이고, 더 많은 사용자 요청을 처리할 수 있게 한다.

 

SEO 성능 향상: 검색 엔진은 페이지의 속도를 순위 결정 요소 중 하나로 간주한다. 로딩 시간을 개선함으로써, 레이지 로딩은 Google의 PageSpeed와 같은 다양한 도구로 측정된 페이지 속도 점수에 긍정적인 영향을 미치게 된다.

 

상호 작용 시간 개선: 상호 작용 시간은 사용자가 웹 페이지에서 버튼, 링크, 기타 요소와 상호 작용할 수 있게 되는 부분을 측정한 시간이다. Lazy Loading을 이용한다면 중요한 컨텐츠의 로딩을 우선시함으로써, 상호 작용 시간을 줄여 사용자에게 향상된 브라우저 사용 경험을 제공한다.

 

모바일 브라우징 최적화 및 사용자 경험 향상: 모바일 장치는 일반적으로 처리 능력과 네트워크 능력이 PC의 성능보다는 제한적인데, Lazy Loading을 적용함으로써 웹사이트는 이러한 제약 조건에 맞게 적응하게 되어, 더 부드러운 경험을 제공하고 데이터 사용량을 줄여주게 된다. 이를 통해 사용자는 화면 밖의 리소스를 기다리지 않고도 보이는 컨텐츠와 빠르게 상호 작용할 수 있다.

 

JavaScript로 Lazy Loading 구현하기

JavaScript로 Lazy Loading을 구현하는 가장 기본적인 방법은 IntersectionObserver API를 사용하는 방법이 있다.

IntersectionObserver API를 사용하면 특정 요소가 뷰포트(viewport)에 언제 들어오는지 감지하고, 이를 통해 이미지나 기타 리소스가 뷰포트에 들어올 때만 로딩을 시작하게 할 수 있다.

 

예시 코드

 

HTML

<img class="lazy" data-src="image1.jpg" alt="Description" />
<img class="lazy" data-src="image2.jpg" alt="Description" />

 

JavaScript

document.addEventListener("DOMContentLoaded", function() { // 2.
    let lazyImages = [].slice.call(document.querySelectorAll("img.lazy")); // 3.

    if ("IntersectionObserver" in window) { // 4.
        let lazyImageObserver = new IntersectionObserver(function(entries, observer) { // 5.
            entries.forEach(function(entry) { // 6.
                if (entry.isIntersecting) { // 7.
                    let lazyImage = entry.target; // 8.
                    lazyImage.src = lazyImage.dataset.src;
                    lazyImage.classList.remove("lazy"); // 9.
                    lazyImageObserver.unobserve(lazyImage); // 10.
                }
            });
        });

        lazyImages.forEach(function(lazyImage) { // 11.
            lazyImageObserver.observe(lazyImage);
        });
    } else {
        lazyImages.forEach(function(lazyImage) { // 12.
            lazyImage.src = lazyImage.dataset.src;
            lazyImage.classList.remove("lazy");
        });
    }
});

 

  1. data-src 속성에 실제 이미지 경로를 저장하고, src 속성은 초기에 빈 상태로 둔다.
  2. DOMContentLoaded이벤트를 통해 HTML 구조가 메모리에 모두 로드된 직후에 해당 함수를 실행하도록 한다.
  3. 페이지 내에 있는 .lazy 클래스를 가진 모든 img 태그를 선택하고, 그것을 배열로 변환한다.
  4. 브라우저가 IntersectionObserver API를 지원하는지 확인하고, 지원한다면 해당 API를 사용하여 lazy loading을 구현하고, 지원하지 않으면 Fallback 코드를 실행한다.
  5. 새로운 IntersectionObserver 객체를 생성한다. 이 객체는 감시 대상의 요소가 뷰포트에 들어왔는지 아닌지를 확인하는 데 사용된다.
  6. IntersectionObserver는 감시 대상의 요소들을 배열로 제공하고, forEach를 사용하여 각 요소를 반복하며 검사한다.
  7. isIntersecting 프로퍼티는 해당 요소가 뷰포트에 들어왔는지 확인하여 만약 들어왔다면 이미지를 로드한다.
  8. 해당 이미지의 src 속성을 data-src의 값으로 설정하여 이미지를 로드한다.
  9. 로드된 이미지에서 lazy 클래스를 제거한다.
  10. 이미지가 로드되었으므로 해당 이미지에 대한 감시를 중지한다.
  11. 모든 .lazy 클래스를 가진 이미지에 대해 IntersectionObserver로 감시를 시작한다.
  12. 만약 브라우저가 IntersectionObserver를 지원하지 않는다면 이 부분의 Fallback 코드가 실행되어 모든 이미지를 직접 로드한다.

 

이 방법을 사용하면 이미지가 뷰포트에 들어올 때만 로드되므로 초기 페이지 로딩 속도가 향상되며, IntersectionObserver를 지원하지 않는 브라우저의 경우에는 Fallback 코드를 사용하여 모든 이미지를 직접 로드할 수 있다.

 

HTML과 CSS로 Lazy Loading 구현하기

HTML과 CSS만을 사용하여 Lazy Loading을 구현하는 것은 JavaScript 기반의 동적 처리보다는 제한적이지만, 최근 웹 표준의 발전 덕분에 HTML과 CSS만을 사용하여 이미지와 iframe에 대한 Lazy Loading을 구현하는 간단한 방법이 도입되었다.

 

HTML loading 속성을 사용한 방법

  • HTML에는 img와 iframe 태그에 loading 속성을 추가하여 Lazy Loading을 간단히 적용할 수 있다.
  • loading 속성은 두 가지 값, eager와 lazy,를 가질 수 있는데, 값을 lazy로 적용하면 브라우저는 해당 요소를 Lazy Loading하게 된다.
<img src="image.jpg" alt="Description" loading="lazy">
<iframe src="video.html" loading="lazy"></iframe>

 

CSS contain 속성을 활용한 방법

  • CSS contain 속성은 요소의 레이아웃, 스타일, 페인트의 범위를 제한하는 데 도움을 준다.
  • 이 속성을 사용하면 브라우저의 최적화 프로세스에 도움을 주어 Lazy Loading과 유사한 효과를 얻을 수 있다.
.lazy-container {
    contain: content;
}

 

그러나 이 방법은 진정한 Lazy Loading과는 다르다. contain 속성은 단순히 렌더링 성능 최적화를 도와주며, 실제 이미지나 컨텐츠의 로딩을 지연시키지는 않는다.

따라서, 실제로 이미지나 다른 미디어 리소스의 로딩을 지연시키려면 HTML의 loading 속성을 사용하는 것이 가장 효과적이기 때문에 JavaScript 없이 순수 HTML과 CSS만을 사용하여 Lazy Loading을 구현하려면 이 속성을 활용하는 것이 가장 좋다.

반응형