웹페이지 이미지 지연 로딩(레이지 로딩-Lazy loading) 구현하기

지연 로딩의 개념

지연 로딩은 웹 브라우저의 뷰포트 바깥에 위치한 웹 페이지의 대상 컨텐츠가 웹 페이지 로딩이 완료된 후 스크롤 등의 동작에 의해 뷰포트 안으로 들어오면, 그때 웹 서버에서 해당 컨텐츠를 가져와 표시를 하는 기능을 말합니다.

웹 페이지를 구성하는 컨텐츠 중에서 개별적인 URI에서 따로 가져오는 리소스를 가진 요소는 지연 로딩을 이용해 불필요한 트래픽을 줄이고, 더 빠른 페이지 로딩을 완료할 수 있습니다.

예를 들어 웹 페이지에 크기가 큰 이미지 파일이 여러 개 있는 경우 이 이미지들을 모두 다운로드해서 웹페이지에 표시할 때까지 웹페이지는 로딩 중 상태가 되고 완료 시점까지 사용자와의 인터렉션이 제한되게 됩니다.

특히 속도가 느린 모바일 인터넷 환경에서는 꽤 오랜 시간을 기다리게 될 수도 있습니다.

지연 로딩을 이용해 페이지 로딩을 빠르게 완료하면, 웹 페이지 로딩 완료가 더 빠르게 되고 사용자와의 인터렉션 시작이 빨라지면서 웹페이지의 반응성이 좋아지는 장점이 있습니다.

검색엔진 입장에서는 지연 로딩이 적용된 웹페이지는 빠른 웹페이지로 인식되기 때문에 검색 지수에도 좋은 영향을 미칩니다.

지연 로딩은 이미지에만 국한된 것은 아니며, 비동기로 로딩이 가능한 많은 웹 요소에 적용되는 내용입니다.

아이프레임이나, 동영상에도 지연 로딩을 적용해서 조금 더 빠른 웹을 구현할 수 있습니다.

지연 로딩으로 인해 극적인 효과가 가장 많이 나타나는 부분이 이미지이기 때문에 주로 이미지에 사용하며, 표준 태그 속성을 이용하는 지연 로딩은 파이어폭스에서는 이미지만 지원하므로 이미지에 한해 지연 로딩을 사용하는 것이 호환성 측면에서 좋습니다.


지연 로딩을 가능하게 하는 기능들

- loading="lazy" 태그 속성 사용

HTML 태그 속성으로 지원되는 표준 지연 로딩 기능입니다.

<img src="./image.jpg" loading="lazy">

지연 로딩이 가능한 요소에 속성을 표시하면(이미지, 객체, 아이프레임 등) 요소가 웹 브라우저 뷰포트에 들어오는 시점에 해당 컨텐츠의 다운로드 및 화면 표시가 이루어집니다.

구글 크롬과 신형 엣지 브라우저는 여러 태그들에 대해서 지연 로딩 속성이 지원되지만, 파이어폭스는 이미지 파일에 대해서만 지원됩니다.

나머지 구형 브라우저들과 애플 계열 웹 브라우저들은 지연 로딩이 지원되지 않습니다.

대부분 웹 브라우저에서 지원되고 사용이 쉽지만, 기능적으로는 지연 로딩 여부만 가능하기 때문에 지연 로딩되는 대상에 대한 세세한 제어는 할 수 없습니다.

세세한 제어를 하려면 자바스크립트로 구현하는 Intersection Observer API를 사용해야 합니다.

그리고 반드시 이미지의 크기 속성 값이 있어야만 loading="lazy" 속성이 적용되어 동작합니다.

명시적으로 크기를 표시하지 않은 이미지는 지연 로딩이 적용되지 않습니다.

크기를 표시할 때는 꼭 스크롤하는 방향에 대한 크기를 정해야 합니다.

세로로 스크롤하는 웹페이지면 높이값이 있어야 지연 로딩이 적용됩니다.

애플 계열 웹 브라우저는 지원이 되지 않음

- 자바스크립트 Intersection Observer API 이용

정기적으로 업데이트가 되고 있는 모던 웹 브라우저에서는 모두 지원되는 자바스크립트 API 기능입니다.

이 API는 지연 로딩을 위한 API라기보다는 웹페이지의 특정 요소가 뷰포트 영역과 교차를 하는지(뷰포트 영역 안에 들어왔는지)를 감시하는 모니터링 API입니다.

웹페이지 요소가 뷰포트 영역 안에 들어오면, 해당 요소를 표시하거나, 또는 다른 특정 동작을 하도록 하는 트리거를 발생시켜 콜백 함수의 코드를 실행합니다.

이 API를 이용한 대표적인 기능이 지연 로딩입니다.

웹 페이지 로딩 완료 후, 뷰포트 바깥에 있는 이미지는 이미지 URI 없이 크기 정보만 가지고 있으며, 자바스크립트로 생성한 옵저버(Observer)는 이미지 요소를 실시간으로 감시합니다. 이미지 영역이 웹 브라우저 뷰포트 안으로 들어오면 이미지 URI를 적용해 이미지가 로딩되도록 합니다.

Intersection Observer API 기능은 자바스크립트를 통해 기능을 구현하며, 웹 브라우저 뷰포트 안으로 들어오는 요소의 동작을 세밀하게, 또 선택적으로 제어할 수 있어서 트래픽을 더 효율적으로 제어할 수 있습니다.

지연 로딩 표준 태그와 달리 자바스크립트 코드로 작성해야 하기 때문에 자바스크립트 프로그래밍 지식이 없으면 직접 구현하는데 어려움이 있는 단점이 있습니다.

- 자연 로딩 자바스크립트 라이브러리 이용

자체적인 기능 구현으로 지연 로딩을 구현하거나 앞서의 Intersection Observer API를 이용해 구현한 자바스크립트 라이브러리입니다.

이미 완성된 프로그램을 사용하기 때문에 빠르고 쉽게 지연 로딩을 구현할 수 있습니다.

이미 사용자 검증이 된 라이브러리들은 웹 브라우저 호환성에서도 가장 유리하지만, 외부 라이브러리를 사용하는 것인 만큼 성능상의 불리함이 약간 더 있을 수 있습니다.

https://github.com/verlok/vanilla-lazyload

 GitHub - verlok/vanilla-lazyload: LazyLoad is a lightweight, flexible script that speeds up your website by deferring the loadinLazyLoad is a lightweight, flexible script that speeds up your website by deferring the loading of your below-the-fold images, backgrounds, videos, iframes and scripts to when they will enter the v...github.com

https://github.com/aFarkas/lazysizes

 GitHub - aFarkas/lazysizes: High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more,High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more, that detects any visibility changes triggered through user interaction, CSS or JavaScript without...github.com


웹 브라우저 지원 호환성

최신 웹 브라우저들은 지연 로딩 태그 속성 및 Intersection Observer API를 모두 지원합니다.

파이어폭스는 지연 로딩 태그 속성(loading="lazy")을 이미지 태그에만 사용할 수 있는 제약이 있지만, 실무에서는 이미지 태그 외에는 거의 사용하지 않기 때문에 특별히 문제가 되지는 않습니다.

그보다는 지연 로딩을 하는 이미지, 또는 요소의 크기 정보가 태그 속성이나 CSS로 명시되지 않았을 경우 지연 로딩이 동작하지 않는다는 점을 꼭 알아두어야 합니다.

지연 로딩을 구현하는 개발자들이 같은 문제로 웹 브라우저 호환성 문제, 또는 웹 브라우저의 기능 지원 여부를 확인하지만, 실제로는 대부분의 문제가 지연 로딩을 하는 이미지 크기 정보를 명시적으로 표현하지 않아서 생기는 문제입니다.

이 문제는 Intersection Observer API를 사용해 자바스크립트로 구현할 때도 동일하게 적용됩니다.

그리고, 애플 사파리 계열 웹 브라우저(데스크탑, 모바일)에서는 지연 로딩 태그 속성이 지원되지 않습니다.

데스크탑용 사파리 브라우저는 실험실 기능으로 제공되기 때문에 기능을 켜서 기능을 사용할 수는 있지만, 여전히 정상적인 지원은 이루어지지 않는다고 봐야 합니다.

기능을 구현하거나 테스트할 때는 애플 사파리를 사용하면 안 됩니다.


지연 로딩 태그 속성으로 구현(loading="lazy")

이미지 태그에 loading="lazy" 속성을 추가하고, CSS로 이미지들의 높이를 900px로 설정합니다.

세로 스크롤을 하는 웹 페이지이기 때문에 이미지에 높이 값이 없으면 지연 로딩이 동작하지 않습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        .spacer{
            height: 1200px;
            width: 100%;
            background-color: #f0f0f0;
        }
        img{
            height: 900px; /* 반드시 이미지 높이 설정 */
            clear: both;
        }
    </style>
</head>
<body>
    <div class="spacer"></div>
    <div><img src="./lazyimg1.jpg" loading="lazy"></div>
    <div><img src="./lazyimg2.jpg" loading="lazy"></div>
    <div><img src="./lazyimg3.jpg" loading="lazy"></div>
    <div><img src="./lazyimg4.jpg" loading="lazy"></div>
    <div><img src="./lazyimg5.jpg" loading="lazy"></div>
</body>
</html>

주의할 점이 있습니다.

지연 로딩된 이미지가 웹페이지 스크롤에 반응해서 뷰포트 영역에 근접할 때 실제로 이미지가 로딩되는 시점이 웹 브라우저에 따라 조금씩 다를 수 있습니다.

웹 브라우저는 지연 로딩된 이미지가 뷰포트 영역에 실제로 걸쳐지는 시점이 로딩하는 것이 아니라 조금 더 미리 로딩합니다. 일종의 프리캐싱(pre-caching)처럼 스크롤되는 현재 뷰포트 영역보다 조금 더 앞의 지연 로딩 이미지를 로딩합니다.

파이어폭스는 범위가 좁아서 지연 로딩된 이미지가 뷰포트에 거의 근접하면 이미지를 로딩하지만, 크롬과 신형 엣지 브라우저는 마진 범위(뷰포트 테두리로부터의 거리)가 좀 더 넓어서 경우에 따라서는 여러 개의 이미지가 미리 로딩됩니다.

지연 로딩된 이미지가 뷰포트에 걸쳐지는 것으로 인식하는 마진 범위를 변경하거나, 이미지의 일부 영역이 뷰포트 안에 들어왔을 때 이미지가 로딩되도록 하려면 Intersection Observer API를 사용해야 합니다.

다음 압축 파일은 앞서의 지연 로딩 속성 소스 코드와 이미지 파일들입니다.

loadlazy.zip4.55MB

다운로드한 html 파일을 웹브라우저에서 연 후 개발자 도구를 열어서 화면을 스크롤하면 지연 로딩된 이미지들이 순차적으로 로딩되는 것을 확인할 수 있습니다.

지연 로딩된 이미지들이 순차적으로 로딩되는 모습

파이어폭스는 개발자 도구에 Initiator(이니셰이터 - 리소스를 호출한 모듈) 정보를 표시해주는 기능이 있습니다.

지연 로딩 속성(loading="lazy")으로 로딩한 이미지는 이니셰이터에 "lazy-img"라고 구분 표시를 해서 지연 로딩 태그 속성으로 로딩한 이미지인지 여부를 확인할 수 있습니다.

지연 로딩 속성으로 로딩한 이미지는 Initiator 탭에 "lazy-img" 속성 값이 표시됨.

Intersection Observer API로 지연 로딩 구현

Intersection Observer API를 사용한 지연 로딩은 이미지 외에도 아이프레임이나 다른 일반 태그에도 사용할 수 있습니다.

다만 여기서는 이미지 지연 로딩을 대상으로 설명하고 있기 때문에 이미지를 기준으로 지연 로딩을 구현합니다.

- 지연 로딩의 핵심 IntersectionObserver 객체

지연 로딩을 구현하는 핵심 객체는 IntersectionObserver 객체입니다.

대상 요소가 뷰포트 테두리와 교차를 하는지 실시간 감시를 하는 모니터링 객체입니다.

뷰포트 테두리와 교차를 했으면 객체를 생성할 때 첫 번째 인자로 넘겼던 콜백 함수가 실행되면서 함수 안의 처리 코드가 동작합니다.

IntersectionObserver의 두 번째 인자는 객체의 옵션 설정 값을 받습니다.

옵션 설정값은 객체로 표현해서 인자로 넘기게 되며, 사용할 수 있는 옵션 속성은 3개입니다.

속성 용도
root 지연 로딩된 이미지가 교차를 하는 기준이 되는 뷰포트 대상을 지정합니다. 반드시 지연 로딩된 요소의 부모 요소 이상을 지정해야 합니다. null 을 사용하면 현재 웹브라우저 뷰포트가 교차 테두리가 됩니다.
이미지 지연 로딩 구현에는 별도로 뷰포트 요소를 지정할 일이 없기 때문에 null을 사용하면 됩니다.
rootMargin 지연 로딩된 이미지가 뷰포트 테두리로 얼마나 가까이 접근했는지를 정하는 기준 값입니다. 이 값보다 작게 지연 로딩 이미지가 접근하면 이미지를 로딩합니다.

기본적으로 픽셀(px) 단위를 붙여서 테두리 영역을 확장하며 따옴표로 감싸서 문자열로 표현해야 합니다.
예를 들어 '500px' 로 표기하면, 화면이 스크롤되서 뷰포트 테두리와의 거리가 500px 이하가 되면 지연 로딩된 이미지가 로딩됩니다.
기본값은 0입니다.
루트마진 값은 퍼센트 값을 사용해서 뷰포트 크기를 기준으로 상대 크기로 정할 수도 있으며(비추천), CSS의 margin 속성처럼 4면을 각각 다르게 설정해서 '100px, 50px, 30px, 60px'과 같이 경계 테두리 범위 영역을 설정할 수도 있습니다.

빠른 스크롤을 할 때 지연 로딩 이미지가 다운로드되어 화면에 표시되는 시간 동안의 지연으로 잠시동안 이미지영역이 빈 공간으로 표시되는 현상을 막을 수 있기 때문에 실제 구현을 할 때는 적정선의 루트마진 값을 꼭 설정하는 것을 권장합니다.
threshold 0~1 사이의 소수점 값으로 표시합니다.
0이 기본값입니다.
실무에서는 이미지 지연 로딩을 구현할 때는 거의 사용되지 않습니다.

지연 로딩된 이미지 영역의 몇 퍼센트(0.25면 25%)가 뷰포트 안으로 들어왔을 때 콜백 함수를 호출하는지를 정하는 임계치입니다.
값이 0.25면 지연 로딩된 이미지 영역의 25%가 뷰포트 영역 안으로 들어오면 이미지를 로딩합니다.
0이면 1픽셀만 뷰포트 테두리와 교차해도 이미지가 로딩됩니다. 1은 이미지가 완전히 뷰포트 영역 안에 들어와야 로딩됩니다.

임계값을 배열로 표시해서 배열 요소 간격마다 콜백 함수를 호출하도록 할 수도 있습니다.
[0.25, 0.5, 0.75, 1]로 임계치를 표시하면 지연 로딩 이미지의 영역이 뷰포트 안으로 25%, 50%, 75%, 100% 들어올 때마다 1번씩 콜백 함수가 호출됩니다.

이미지 지연 로딩을 위해 옵션 객체는 다음과 같이 작성합니다.

const intersectionObserverOptions = {
    root: null,
    rootMargin: '500px', /* 뷰포트 바깥 근접 거리 */
    threshold: 0 /* 뷰포트 안쪽 표시 비율 */
};

그리고 작성한 옵션은 IntersectionObserver 객체를 생성할 때 다음과 같이 두 번째 인자로 넣게 됩니다.

첫 번째 인자 "callback"은 별도로 정의한 콜백 함수 이름입니다.

let observer = new IntersectionObserver(callback, intersectionObserverOptions);

생성된 옵저버 객체는 객체 메서드를 이용해 감시할 요소를 추가하거나 삭제해서 모니터링할 대상을 선택합니다.

쿼리 선택자로 선택한 요소를 observer() 메서드 인자로 넣어서 넘기면 모니터링이 시작됩니다.

let img = document.querySelector('#lazyImg');
observer.observe(img);

로딩 완료된 이미지는 더 이상 모니터링할 필요가 없으므로 모니터링 대상에서 제거해야 합니다.

뷰포트와 교차를 하면 교차 이벤트가 발생하고 콜백 함수가 실행됩니다.

콜백 함수에서 처리할 코드를 실행한 후 다음과 같이 unobserve() 메서드로 모니터링 대상에서 해당 요소를 제외할 수 있습니다.

observer.unobserve(img);

- 모니터링 대상에 이미지(들) 등록하기

모니터링 옵저버를 등록할 이미지 태그들은 다음과 같이 작성합니다.

앞서의 지연 로딩 태그 속성과 마찬가지로 이미지 높이는 반드시 부여해야 합니다.

그리고 가장 중요한 것은 이미지 태그의 이미지 경로를 표시하는 속성입니다. 이미지 URL 속성은 "src"를 사용하지만, 예제에서는 "data-src"로 "data-" 커스텀 속성으로 URL을 사용합니다. 속성은 의도에 따라 다른 속성명으로 사용할 수 있습니다.

"src" 속성이 아니므로 웹페이지 로딩 시점에는 이미지가 로딩되지 않습니다.

로딩 완료 후 웹페이지가 스크롤되면서 뷰포트와 교차하는 이미지가 발생하면 콜백 함수에서 "data-src" 속성의 URL을 "src" 속성으로 복사를 해서 이미지 로딩이 되도록 합니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        .spacer{
            height: 1200px;
            width: 100%;
            background-color: #f0f0f0;
        }
        img{
            width: auto;
            height: 900px;
            clear: both;
        }
    </style>
    <script type="text/javascript" src="./observer.js"></script>
</head>
<body>
    <div class="spacer"></div>
    <div><img data-src="./lazyimg1.jpg" id="lazyimg1"></div>
    <div><img data-src="./lazyimg2.jpg" id="lazyimg2"></div>
    <div><img data-src="./lazyimg3.jpg" id="lazyimg3"></div>
    <div><img data-src="./lazyimg4.jpg" id="lazyimg4"></div>
    <div><img data-src="./lazyimg5.jpg" id="lazyimg5"></div>
</body>
</html>

먼저 이미지 태그들을 모두 선택해서 모니터링 옵저버를 객체에 등록해야 합니다.

DOM 객체가 있어야 이미지 태그 선택이 가능하므로 DOM 객체 생성을 체크하는 이벤트 리스너 함수(document.addEventListener('DOMContentLoaded', function(){});) 안에 모니터링 옵저버 객체를 생성합니다.

모니터링 옵저버 객체 변수는 글로벌 변수여야 합니다. 이벤트 리스너 안에 변수를 선언하면 변수가 소멸되면서 모니터링 옵저버 객체도 소멸됩니다.

let observer;
document.addEventListener('DOMContentLoaded', function(){
    observer = new IntersectionObserver(callback, intersectionObserverOptions); // 모니터링 옵저버 객체 생성
    let imgs = document.querySelectorAll('img'); // 웹페이지의 모든 이미지 선택
    imgs.forEach((img)=>{observer.observe(img)}); // 이미지 요소를 모니터링 옵저버 객체에 등록
});

- 콜백 함수로 이미지 지연 로딩하기

뷰포트 테두리와 교차하는 이미지가 생기면 콜백 함수가 호출됩니다.

콜백 함수는 교차된 요소들의 목록을 첫 번째 인자로 받습니다. 두 번째 인자는 모니터링 옵저버 객체 자신을 인자로 넘겨서 모니터링 옵저버의 메서드들을 사용할 수 있도록 해줍니다.

루프 문을 돌며 첫 번째 인자로 받은 요소들 중에서 뷰포트 테두리와 교차한 요소(실제로는 이미지만 교차하므로 이미지)의 "data-src" 속성의 값을 "src" 속성으로 복사를 한 후 unobserve() 메서드로 모니터링을 해제합니다.

요소가 교차했는지를 체크하는 if() 조건문은 반드시 있어야 합니다.

모니터링 옵저버에 등록한 이미지는 실시간으로 교차 체크를 하기 때문에 화면 렌더링을 할 때마다 호출이 됩니다.

따라서 교체 체크를 하는 조건문이 없으면 초기 웹페이지 로딩 시점에 호출되는 콜백 함수에 의해서 모든 이미지가 한꺼번에 로딩됩니다.

let callback = (entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) { // 요소가 교차했는지 불리언 체크
            let elem = entry.target;
            elem.setAttribute('src', elem.getAttribute('data-src')); // 이미지 경로 복사
            observer.unobserve(elem); // 모니터링 해제
        }
    });
};
모니터링 옵저버로 지연 로딩된 이미지들을 로딩하는 화면

설명한 기능들은 다음 압축 파일을 다운로드하여 실행되는 HTML 페이지로 확인해볼 수 있습니다.

observer.zip4.55MB


지연 로딩 구현의 중복 적용

좋은 게 좋다고 지연 로딩 태그 속성과 모니터링 옵저버를 사용한 자바스크립트 구현을 한꺼번에 적용하면 더 좋지 않을까 싶지만, 지연 로딩 태그 속성도 내부적으로는 결국 모니터링 옵저버를 사용한 구현체입니다.

따라서 이벤트가 2번 발생하며, 이미지가 중복 로딩됩니다.

지연 로딩을 구현할 때는 태그 속성, 또는 자바스크립트를 이용한 모니터링 옵저버 구현중 한 가지 만을 사용해서 구현해야 합니다.

다음과 같이 HTML을 작성하고, 자바스크립트로 모니터링 옵저버를 구현해서 지연 로딩을 하면

<div><img src="./lazyimg1.jpg" data-src="./lazyimg1.jpg" id="lazyimg1" loading="lazy"></div>
<div><img src="./lazyimg2.jpg" data-src="./lazyimg2.jpg" id="lazyimg2" loading="lazy"></div>
<div><img src="./lazyimg3.jpg" data-src="./lazyimg3.jpg" id="lazyimg3" loading="lazy"></div>
<div><img src="./lazyimg4.jpg" data-src="./lazyimg4.jpg" id="lazyimg4" loading="lazy"></div>
<div><img src="./lazyimg5.jpg" data-src="./lazyimg5.jpg" id="lazyimg5" loading="lazy"></div>

다음처럼 이미지가 중복으로 지연 로딩되게 됩니다.

이미지가 중복으로 지연로딩됨

지연 로딩의 동작 조건

이미 한번 열었던 웹페이지는 웹브라우저가 로컬 저장소에 캐싱을 하고 있기 때문에 지연 로딩으로 인한 트래픽 감소나 반응성 개선 등의 속도상 이점이 전혀 없습니다.

따라서 웹브라우저는 캐시 된 웹페이지에 대해서는 지연 로딩을 하지 않습니다.

지연 로딩 기능 구현을 테스트하려면 웹페이지 캐시를 매번 지우고 확인해야 합니다.

또는 개발자 도구 상단의 기능 체크박스 중에서 "캐시 사용 중지"를 체크해서 켜면 개발자 도구를 열어놓은 동안은 웹페이지를 캐시 하지 않으므로 반복적으로 지연 로딩 동작 확인을 할 때는 이렇게 확인할 수 있습니다.

구글 크롬 개발자도구 캐시 사용 중지 체크 옵션

티스토리 블로그에 적용한 실전 이미지 지연 로딩 구현 방법은 다음 글을 참고하면 도움이 됩니다.

> 티스토리 오프스크린 이미지 지연 로딩(Lazy loading) 하기1 - lazysizes 라이브러리 사용

> 티스토리 오프스크린 이미지 지연 로딩(Lazy loading) 하기2 - 프로미스 비동기 객체 사용


임계값(threshold)을 이용한 주기적인 콜백 함수 호출

Intersection Observer API를 이용하는 모니터링 옵저버 기능은 이미지뿐만 아니라 영역을 차지하는 모든 태그에 사용할 수 있습니다.

부모 요소로 뷰포트 영역을 한정하고, 지연 로딩된 요소가 뷰포트 요소 테두리 안으로 들어온 정도에 따라 콜백 함수를 이용해서 특정 기능을 실행하도록 할 수 있습니다.

임계값(threshold)을 다음처럼 배열로 선언하면 지연 로딩된 요소가 뷰포트 안으로 들어온 크기를 일정 간격을 따라 콜백 함수를 호출할 수 있습니다.

const intersectionObserverOptions = {
    root: null,
    rootMargin: '0px', /* 뷰포트 바깥 근접 거리 */
    threshold: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] /* 뷰포트 안쪽 표시 비율 */
};

다음 예제는 화면을 스크롤하면 블록 요소 안에 뷰포트 안으로 들어온 크기 값을 표시해주는 데모입니다.

이미지 지연 로딩과 가장 크게 다른 점은 콜백 함수에서 모니터링 옵저버 기능을 삭제하지 않는 것입니다.

모니터링 옵저버를 삭제하면 처음 한 번만 콜백이 실행되기 때문에 임계값으로 정한 주기적인 콜백 함수 호출이 이루어지지 않습니다.

let callback = (entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) { // 요소가 교차했는지 불리언 체크
            let elem = entry.target;
            elem.innerHTML = Math.floor(entry.intersectionRatio * 100)+'%';
        }
    });
};
10% 단위로 콜백 함수 호출되는데 따라 뷰포트 안에 들어온 블록 영역에 들어온 크기가 표시되는 화면

threshold.zip0.00MB