ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 이미지 프리로딩(Image Preloading)
    Web/Optimization 2021. 9. 23. 19:38
    반응형

    갤러리와 같은 형태의 페이지, 즉 이미지가 많이 필요한 페이지의 경우에는

    종종 이미지 최적화가 곧 해당 페이지의 성능 최적화 그 자체인 경우가 많다.

    이번에 프로젝트로 진행한 Babble 웹페이지도 마찬가지.

    babble.gg 웹사이트

    이런 경우에 이미지 로딩을 최적화하기 위해 자주 사용되는 방법 중에 하나가 바로 Image Preloading이다.

    Image Preloading은 유저가 이미지를 요청하기 전에 미리 이미지를 다운받아 캐시에 저장하고,

    필요할 때 캐시에서 바로바로 꺼내쓰는 것을 의미한다.

    브라우저가 해당 페이지에서 요청한 이미지, CSS, JS 등을 캐싱하여 사용한다는 특징을 이용한 테크닉이다.

     

    초기 페이지에 보여질 이미지 로딩과 관련된 테크닉은 아닌 것 같고, 

    유저가 특정 버튼을 클릭하거나 다른 페이지로 갈 때 보여질 이미지들을 미리 불러와서 캐시에 저장해놓고

    그 행동이 발생했을 때 이미지를 캐시에서 바로 꺼내쓰는 식으로 UX를 개선하는 방법인 듯 하다.

     

    #1. Preloading with CSS + Javascript

    #preload1 { background: url(http://example.com/image1.png) no-repeat -9999px -9999px; }
    #preload2 { background: url(http://example.com/image2.png) no-repeat -9999px -9999px; }
    #preload3 { background: url(http://example.com/image3.png) no-repeat -9999px -9999px; }

    이미지를 화면 바깥의 어딘가에서 로딩을 해서 캐시에 저장해놓고,

    다음에 다른 곳에서 이 이미지가 필요한 경우에는 바로바로 캐시에서 이미지를 꺼내쓰게 된다.

    근데 preloading을 이렇게만 구현해놓으면 지금 당장 보여지지도 않을 이 이미지들을 함께 로딩하느라

    지금 당장 보여져야하는 현재 페이지의 컨텐츠들의 로딩이 느려지게 된다.

     

    그래서 onload 이벤트가 발생한 후에 이미지가 로딩되도록 구현해주면 된다.

    const preloader = () => {
        document.getElementById("preload1").style.background = "url(http://example.com/image1.png) no-repeat -9999px -9999px";
        document.getElementById("preload2").style.background = "url(http://example.com/image2.png) no-repeat -9999px -9999px";
        document.getElementById("preload3").style.background = "url(http://example.com/image3.png) no-repeat -9999px -9999px";
    };
    
    const addLoadEvent = (func) => {
        const onloadEvent = window.onload;
        if (typeof window.onload != 'function') {
            window.onload = func;
        } else {
            window.onload = () => {
                if (onloadEvent) {
                    onloadEvent();
                }
                func();
            }
        }
    };
    
    addLoadEvent(preloader);

     

    #2. Preloading with Javascript Only

    const images = [
        "http://example.com/image1.png",
        "http://example.com/image2.png",
        "http://example.com/image3.png"
    ];
    
    const preload = (images) => {
        images.forEach((image) => {
            const img = new Image();
            img.src = image;
        });
    };
    
    preload(images);

     

    물론, 여기에도 addLoadEvent를 붙여서 preload 시점을 미뤄줄 수 있다.

    const images = [
        "http://example.com/image1.png",
        "http://example.com/image2.png",
        "http://example.com/image3.png"
    ];
    
    const preload = (images) => () => {
        images.forEach((image) => {
            const img = new Image();
            img.src = image;
        });
    };
    
    const addLoadEvent = (func) => {
        const onloadEvent = window.onload;
        if (typeof window.onload != 'function') {
            window.onload = func;
        } else {
            window.onload = function() {
                if (onloadEvent) {
                    onloadEvent();
                }
                func();
            }
        }
    }
    
    addLoadEvent(preload(images));

    이미지가 로딩되고나서 해야 할 일이 있다면 이미지 자체에 onload나 onerror를 걸어줄 수도 있다.

    단, 이 경우 반드시 onload를 달아준 후에 src를 명시해줘야 로딩 이후 onload 이벤트가 정상적으로 실행된다고 한다.

    https://stackoverflow.com/questions/66648402/how-to-write-a-preload-function-in-javascript

     

    참고

     

    3+ Ways to Preload Images Using CSS, JavaScript, or Ajax | Perishable Press

    Preloading images is a great way to improve the user experience. When images are preloaded in the browser, the visitor can surf around your site and enjoy extremely faster loading times. This is especially beneficial for photo galleries and other image-hea

    perishablepress.com

     

    #3. Synchronous Preloading

    참고로, 위의 preloading 방법들은 이미지를 로딩할 때 병렬적으로 로딩함으로써

    브라우저의 이미지 로딩 속도를 최대한으로 끌어올리려는 목적을 가지고 있다.

    하지만 고화질 이미지들로 가득한 웹사이트에서, 특히나 유저의 행동을 명확히 예측할 수 있는 경우에는

    이러한 병렬 이미지 로딩이 마냥 최선의 방법은 아닐 수 있다.

     

    브라우저는 critical resource들을 모두 로딩한 후에야 페이지를 렌더링할 수 있기 때문에

    그런 리소스들(HTML, CSS, JS 등등)같은 경우에는 병렬 다운로드가 전체 로딩 시간을 줄여주므로 효과적이겠다.

    하지만 이미지에 관해서는 또 얘기가 달라지는 것.

     

    병렬적으로 이미지를 다운받으면 브라우저는 가능한 최대 갯수만큼의 이미지를 동시에 로딩하게 될텐데,

    이렇게 하면 총 로딩 시간은 줄어들지만 개별 이미지의 로딩 시간으로 보면 더 느려지기 때문이다.

    (동시에 로딩되는 이미지들이 대역폭을 공유하기 때문)

    고로, 어떤 이미지 파일이 먼저 보여질지와 같은 우선 순위를 미리 예측할 수 있는 상태에서는

    전체적인 preloading 시간이 약간 늦어지더라도 이미지를 순차적으로 다운받는 것이 더 유리할 수도 있다.

    위에서 살짝 언급했던 image.onload 이벤트를 이용하면 순차적 이미지 로딩을 구현할 수 있다.

    const images = [
        "http://example.com/image1.png",
        "http://example.com/image2.png",
        "http://example.com/image3.png"
    ];
    
    const preload = (imageArray, index) => {
        index = index || 0;
        if (imageArray && imageArray.length > index) {
            const img = new Image();
            img.onload = () => {
                preload(imageArray, index + 1);
            }
            img.src = imageArray[index];
        }
    }
    
    preload(images);

     

    유저가 선택할 수 있는 행동의 갈래가 두 개로 갈라진다면,

    (ex. 갤러리 페이지에 접속해서 선택할 수 있는 링크가 'Previous image'와 'Next image'인 경우)

    이미지 두 개를 동시에 받는 정도는 약간의 로딩 지체만 발생시키기 때문에 충분히 감수할 만하다고 한다.

     

    위에서 언급했던 addLoadEvent 함수는 기존에 onload 이벤트가 이미 존재하는 경우에,

    해당 onload 이벤트를 덮어쓰지 않고 함께 실행해주기 위해 만든 함수이다.

    그래서 기존에 등록된 onload 이벤트가 없다면 그냥 window.onload 에다가 preloading 로직을 넣어주면 된다.

     

    참고

     

    A better way to preload images for web galleries

    by Mark Meyer February 09, 2015 --> Photographer’s websites are often image-heavy, which can make them unreasonably sluggish, especially for people on mobile or other low-bandwidth connections. Finding the perfect balance between image size, image qualit

    www.photo-mark.com

     

     

    반응형

    'Web > Optimization' 카테고리의 다른 글

    렌더링 성능 최적화 수업 정리  (0) 2021.09.24
    로딩 성능 최적화 수업 정리  (0) 2021.09.22
    프론트엔드 웹 로딩 최적화  (2) 2021.08.16

    댓글

Designed by Tistory.