Ajax 로딩 프로그래스바 구현하기(Javascript / jQuery)

Ajax 로딩 프로그래스바 구현하기

웹 애플리케이션의 사용자 경험을 향상시키는 데 있어 Ajax(Asynchronous JavaScript and XML)는 중요한 역할을 합니다. 데이터를 비동기적으로 불러오면서 페이지를 새로 고치지 않고도 동적인 콘텐츠를 제공할 수 있기 때문입니다. 그런데, 사용자가 어떤 동작을 수행할 때 시간이 걸릴 수 있으므로 로딩 이미지를 통해 진행 상태를 시각적으로 나타내는 것은 좋은 아이디어입니다.

이 글에서는 Ajax 로딩 이미지를 구현하는 소스 코드를 자바스크립트 및 jQuery를 이용하여 제공하고자 합니다.

1. HTML 마크업

테스트의 판단을 용이하게 위해 조금 큰 용량의 이미지를 준비합니다. 저는 5MB이상의 이미지를 3장 준비하였습니다.
버튼을 넣어 버튼 클릭시 이미지가 로딩되는 형태로 작성하였습니다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로딩 아이콘, 다운중 표현하기 사용하기</title>
</head>
<body>
<h1>로딩 아이콘, 다운중 표현하기 사용하기</h1>
<button id="bt">이미지 보기</button>
<ul id="contents">
    <li>
        <img data-src="sample.jpg" alt="다운로드 이미지" loading="lazy">
        <div class="progress-bar"><span>0%</span></div>
    </li>
    <li>
        <img data-src="sample2.jpg" alt="다운로드 이미지" loading="lazy">
        <div class="progress-bar"><span>0%</span></div>
    </li>
    <li>
        <img data-src="sample3.jpg" alt="다운로드 이미지" loading="lazy">
        <div class="progress-bar"><span>0%</span></div>
    </li>
</ul>
<script>
    // JavaScript 코드가 이어집니다.
</script>
</body>
</html>

마크업 작성시에는 언제 이미지를 로딩할지를 필요에 맞게 작성해야 합니다.
저는 이미지 목록이 처음부터 뜨는 형태가 아닌 이미지 로딩이 내가 원하는 이벤트에 적용하고자 합니다. 이는 페이지 로딩 속도를 극대화하고 필요한 경우에만 다운로드를 함으로서 렌더링 속도를 극대화 하기 위함입니다. 이런 경우 다음의 설정이 필요합니다.

  • CSS 렌더링 차단 리소스 설정
    화면상의 이미지가 많거나 큰 경우에는 loading=’lazy’ 속성으로 보이지 않는 이미지에 대해 로딩을 하지 않도록 설정합니다.
  • 이벤트 제어를 위한 설정
    img 요소의 src 속성 대시 data-src 속성을 이용함으로 모든 이벤트에서 원하지 않는 로딩이 되지 않도록 합니다.
  • 이벤트 적용
    이미지를 화면에 보여주고 싶을 때 Ajax 기법으로 이미지를 로딩하고 보여줍니다.

2. 스타일링

간단히 본인에게 필요한 디자인을 입혀줍니다.

<style>
    * {margin:0; padding:0}
    body {width: 100%; min-height: 100vh; padding:20px; box-sizing: border-box}
    h1 {text-align:center; padding: 30px}

    #bt {margin: 10px 0; display: block; cursor: pointer; font-weight:bold; padding:10px 20px;}
    #contents { border: 1px dashed #ccc; padding: 10px; display: flex; justify-content: center; align-items: center; gap: 10px; flex-wrap: wrap}
    #contents li {width: 300px; aspect-ratio: 3/2; padding: 10px; display: flex; justify-content: center; align-items: center; background: #eee; position: relative}
    #contents img {width: 100%; height: 100%; object-fit: cover; display: none; transition: ease all .3s; opacity: 0; position: relative; z-index:100}
    .progress-bar {background: #eee; width: 150px; height: 5px; border-radius: 5px; overflow: hidden; position: absolute; bottom:50%; left: 50%; transform: translate(-50%,-50%)}
    .progress-bar span {display: block; background: #666; height: 100%; text-indent: -999px; width: 0}
</style>
Ajax 로딩 프로그래스바 구현 - 스타일링

3. 동작구현

<script>
    var button = document.getElementById("bt");

    // 버튼 클릭 시 이미지 로딩 및 진행 상황 표시 동작을 실행합니다.
    button.addEventListener("click", function () {
        // 이미지와 진행 상황 표시 요소를 가져옵니다.
        var imageElements = document.querySelectorAll("#contents img");
        var progressBars = document.querySelectorAll(".progress-bar span");
        var imageUrls = Array.from(imageElements).map(function (img) {
            return img.getAttribute("data-src");
        });

        imageUrls.forEach(function (imageUrl, index) {
            // 이미지 로드를 시작하고 진행 상황을 업데이트합니다.
            var xhr = new XMLHttpRequest();
            xhr.open("GET", imageUrl, true);
            xhr.responseType = "blob";

            xhr.onprogress = function (e) {
                if (e.lengthComputable) {
                    var percentComplete = (e.loaded / e.total) * 100;
                    progressBars[index].textContent = percentComplete.toFixed(2) + "%";
                    progressBars[index].style.width = percentComplete + "%";
                }
            };

            xhr.onload = function () {
                if (xhr.status === 200) {
                    // 이미지 다운로드가 완료되면 이미지를 표시합니다.
                    var blob = xhr.response;
                    var reader = new FileReader();

                    reader.onload = function () {
                        var dataURL = reader.result;
                        imageElements[index].src = dataURL;
                        imageElements[index].style.display = "block";
                        setTimeout(function(){
                            imageElements[index].style.opacity = 1;
                        },10)
                    };

                    reader.readAsDataURL(blob);
                } else {
                    // 이미지 다운로드에 실패한 경우 오류 메시지를 표시합니다.
                    progressBars[index].textContent = "다운로드 실패";
                    progressBars[index].style.width = "100%";
                    progressBars[index].style.background = "red";
                }
            };

            xhr.send();
        });
    });
</script>

이 코드는 이미지를 로딩하고 진행 상황을 표시하는 예제로, 버튼을 클릭하면 Ajax를 사용하여 이미지를 다운로드하고 진행 상황을 보여주는 동작을 수행합니다. 페이지를 불러올 때 이미지는 초기에 숨겨져 있으며, 버튼을 클릭하면 이미지가 다운로드되고 나타납니다. 이미지 다운로드 진행 상황은 진행 막대로 표현되고 있고 숫자로 %를 표현하고자 하는 경우엔 percentComplete 값을 사용하면 됩니다.

jQuery로 같은 로딩 프로그래스바 구현하기

<script>
$(document).ready(function() {
    var button = $("#bt");

    button.click(function() {
        var imageElements = $("#contents img");
        var progressBars = $(".progress-bar span");

        imageElements.each(function(index) {
            var imageUrl = $(this).attr("data-src");

            $.ajax({
                url: imageUrl,
                xhr: function() {
                    var xhr = new window.XMLHttpRequest();
                    xhr.addEventListener("progress", function(e) {
                        if (e.lengthComputable) {
                            var percentComplete = (e.loaded / e.total) * 100;
                            progressBars.eq(index).text(percentComplete.toFixed(2) + "%");
                            progressBars.eq(index).width(percentComplete + "%");
                        }
                    });
                    return xhr;
                },
                success: function(data) {
                    var reader = new FileReader();
                    reader.onloadend = function() {
                        $(imageElements[index]).attr("src", reader.result);
                        $(imageElements[index]).css("display", "block");
                        setTimeout(function() {
                            $(imageElements[index]).css("opacity", 1);
                        }, 10);
                    };
                    reader.readAsDataURL(data);
                },
                error: function() {
                    progressBars.eq(index).text("다운로드 실패");
                    progressBars.eq(index).width("100%");
                    progressBars.eq(index).css("background", "red");
                }
            });
        });
    });
});
</script>

이 코드는 jQuery를 사용하여 동일한 동작을 수행합니다. 버튼이 클릭되면 각 이미지의 다운로드 진행 상황을 표시하고 이미지를 화면에 나타냅니다.

결론

로딩 이미지는 웹 애플리케이션의 사용자 경험을 향상시키는 중요한 요소 중 하나입니다. Ajax 요청이나 데이터 로딩 시에는 로딩 이미지를 통해 사용자에게 진행 상태를 시각적으로 알려주는 것이 좋습니다. 위의 예제 코드를 참고하여 웹 애플리케이션에 로딩 이미지를 적용하여 사용자에게 더 나은 경험을 제공해보세요.

4. 자주 묻는 질문 (FAQs)

로딩 이미지의 디자인을 변경하려면 어떻게 해야 하나요?

로딩 이미지의 디자인은 CSS 스타일을 수정하여 변경할 수 있습니다. 예를 들어, 배경 색상, 높이, 애니메이션 속도 등을 조절할 수 있습니다.

여러 개의 Ajax 요청이 동시에 진행될 때 로딩 이미지를 어떻게 관리해야 하나요?

여러 개의 Ajax 요청이 진행 중일 때에는 각 요청마다 별도의 로딩 이미지를 관리하거나, 요청이 완료될 때마다 진행 상태를 업데이트하는 로직을 추가해야 합니다.

로딩 이미지의 애니메이션을 추가하려면 어떻게 해야 하나요?

로딩 이미지에 애니메이션을 추가하려면 CSS3 트랜지션을 사용하여 속성 값에 변화를 주면 됩니다. 예를 들어, 너비(width) 속성의 변화에 트랜지션을 적용하여 부드러운 애니메이션을 만들 수 있습니다.

로딩 이미지가 모바일 환경에서도 동작하나요?

네, 로딩 이미지는 모바일 환경에서도 동작합니다. 모바일 브라우저에서 자바스크립트 및 jQuery를 지원하므로 위의 예제 코드는 모바일에서도 사용할 수 있습니다.

로딩 이미지를 추가하는 데 서드파티 라이브러리를 사용할 수 있나요?

네, 로딩 이미지를 추가하는 데는 다양한 서드파티 라이브러리가 있습니다. 예를 들어, NProgress, Spin.js 등의 라이브러리를 활용하여 더 다양한 로딩 이미지를 구현할 수 있습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다