'ProgressBar'에 해당되는 글 1건

  1. 2006.04.11 | progress bar 기능 구현하기

progress bar 기능 구현하기

WEB2.0/ajax | 2006. 4. 11. 17:32
Posted by 시반

웹 프로그램의 경우 요청에 대한 응답이 제대로 오지 않거나 너무 많은 시간이 걸린다면 사용자는 불평을 하면서 다른 싸이트로 가버리고 다시는 그 싸이트를 이용하지 않을 것이다. 혹은 금전적인 문제가 걸려있다면 서비스 콜센터로 항의 전화를 할 것이다.

 

2년전 국내 모 은행 인터넷 뱅킹을 개발하면서 로그인 기능을 구현해 놓을 것을 살펴보고 놀라지 않을 수 없었다. 로그인을 하는데 자그마치 30초가 걸렸다. 웹 프로그램에서 30초라...어떻게 생각하는가? 당연히 설계가 잘못됬다. 고객에게 이런 불편을 초래하는 싸이트라면 경쟁 인터넷뱅킹 은행에게 모든 고객을 빼앗길 것이다.

 

 몇년전의 통계수치라 지금은 기억이 잘 나지 않지만, 인터넷 이용자가 응답정보를 기다리다 인내심을 더이상 참지 못하고 다른 싸이트로 가버리는 시간은 7~8초 였던 것으로 기억한다. 하지만 지금은 좀더 짧아지지 않았을까 생각한다.

 

30초는 정말 말도 안되는 시간이지만 5~6초정도의 시간이면 사용자에게 현재 서버의 작업 진행상태를 표시해주면 사용자는 안도감을 느끼면서 좀 더 기다려줄 확률은 높아질 수 있다. 이것은 일종의 서비스 차원의 아이디어일뿐이지, 사실 서버의 프로그램을 수정해서 최대한 프로세스를 단축하는 것이 가장 좋은 해결책이라 하겠다.

 

로그인 하는데 30초 걸렸던 그 프로젝트에서는 할 수 없이 서버의 상태바를 이미지로 붙여 놓았다. 이런 이미지는 사실 의미가 없는것이 현재 서버의 상태를 실시간으로 보여주는 것이 아니라 반복적인 이미지로 하여금 고객을 짜증나게 할 수도 있다. 실제 서버의 작업 진척도와 현재 브라우저에서 보여주는 정보가 일치해야 진정한 상태바 프로그램이라 할 수 있겠다.

 

상태바 프로그램을 위해서는 자원의 소모라는 손해를 감수해야만 한다. 서버의 비지니스 로직이 현재 얼마나 진행됬는지 별도로 체크해야 하는 코딩이 추가되어야 한다. 가뜩이나 시간이 오래걸리는 작업인데 그 작업이 얼마나 진행됬는지 확인하는 로직이 추가된다면 자원의 소모가 그만큼 더 많아지게 되고 시간도 더 지연되는 것이다. 장점이 있다면 단점이 있기 마련이다. 장점을 더욱 부각시키고 단점을 줄이는 방향으로 생각을 전환하자.

 

이런 복잡한 문제에서 벗어나 지금은 상태바에 대한 구현 자체가 목적이므로 단순한 예제를 통해서 살펴보기로 하자.


 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
  <head>
    <title>Ajax Progress Bar</title>
    <script type="text/javascript">
        var xmlHttp;
        var key;
        var bar_color = 'gray';
        var span_id = "block";
        var clear = "&nbsp;&nbsp;&nbsp;"

        function createXMLHttpRequest() {
            if (window.ActiveXObject) {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            else if (window.XMLHttpRequest) {
                xmlHttp = new XMLHttpRequest();               
            }
        }

        function go() {
            createXMLHttpRequest();
            checkDiv();
            var url = "ProgressBarServlet?task=create";
            var button = document.getElementById("go");
            button.disabled = true;
            xmlHttp.open("GET", url, true);
            xmlHttp.onreadystatechange = goCallback;
            xmlHttp.send(null);
        }

        function goCallback() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
                    setTimeout("pollServer()", 1000);
                }
            }
        }
       
        function pollServer() {
            createXMLHttpRequest();
            var url = "ProgressBarServlet?task=poll";
            xmlHttp.open("GET", url, true);
            xmlHttp.onreadystatechange = pollCallback;
            xmlHttp.send(null);
        }
       
        function pollCallback() {
            if (xmlHttp.readyState == 4) {
                if (xmlHttp.status == 200) {
                    var percent_complete = xmlHttp.responseXML.getElementsByTagName("percent")[0].firstChild.data;
                   
                    var index = processResult(percent_complete);
                    for (var i = 1; i <= index; i++) {
                        var elem = document.getElementById("block" + i);
                        elem.innerHTML = clear;

                        elem.style.backgroundColor = bar_color;
                        var next_cell = i + 1;
                        if (next_cell > index && next_cell <= 9) {
                            document.getElementById("block" + next_cell).innerHTML = percent_complete + "%";
                        }
                    }
                    if (index < 9) {
                        setTimeout("pollServer()", 1000);
                    } else {
                        document.getElementById("complete").innerHTML = "Complete!";
                        document.getElementById("go").disabled = false;
                    }
                }
            }
        }
       
        function processResult(percent_complete) {
            var ind;
            if (percent_complete.length == 1) {
                ind = 1;
            } else if (percent_complete.length == 2) {
                ind = percent_complete.substring(0, 1);
            } else {
                ind = 9;
            }
            return ind;
        }

        function checkDiv() {
            var progress_bar = document.getElementById("progressBar");
            if (progress_bar.style.visibility == "visible") {
                clearBar();
                document.getElementById("complete").innerHTML = "";
            } else {
                progress_bar.style.visibility = "visible"
            }
        }
       
        function clearBar() {
            for (var i = 1; i < 10; i++) {
                var elem = document.getElementById("block" + i);
                elem.innerHTML = clear;
                elem.style.backgroundColor = "white";
            }
        }
    </script>
  </head>
  <body>
    <h1>Ajax Progress Bar Example</h1>
    Launch long-running process: <input type="button" value="Launch" id="go" onclick="go();"/>
    <p>
    <table align="center">
        <tbody>
            <tr><td>
                <div id="progressBar" style="padding:2px;border:solid black 2px;visibility:hidden">
                    <span id="block1">&nbsp;&nbsp;&nbsp;</span>
                    <span id="block2">&nbsp;&nbsp;&nbsp;</span>
                    <span id="block3">&nbsp;&nbsp;&nbsp;</span>
                    <span id="block4">&nbsp;&nbsp;&nbsp;</span>
                    <span id="block5">&nbsp;&nbsp;&nbsp;</span>
                    <span id="block6">&nbsp;&nbsp;&nbsp;</span>
                    <span id="block7">&nbsp;&nbsp;&nbsp;</span>
                    <span id="block8">&nbsp;&nbsp;&nbsp;</span>
                    <span id="block9">&nbsp;&nbsp;&nbsp;</span>
                </div>
            </td></tr>
            <tr><td align="center" id="complete"></td></tr>
        </tbody>
    </table>
  </body>
</html>

<progressBar.html 의 전체 소스 코드>



package ajaxbook.chap4;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

/**
 *
 * @author nate
 * @version
 */
public class ProgressBarServlet extends HttpServlet {
    private int counter = 1;
   
    /** Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        String task = request.getParameter("task");
        String res = "";
       
        if (task.equals("create")) {
            res = "<key>1</key>";
            counter = 1;
        }
        else {
            String percent = "";
            switch (counter) {
                case 1: percent = "10"; break;
                case 2: percent = "23"; break;
                case 3: percent = "35"; break;
                case 4: percent = "51"; break;
                case 5: percent = "64"; break;
                case 6: percent = "73"; break;
                case 7: percent = "89"; break;
                case 8: percent = "100"; break;
            }
            counter++;
               
            res = "<percent>" + percent + "</percent>";
        }
       
        PrintWriter out = response.getWriter();
        response.setContentType("text/xml");
        response.setHeader("Cache-Control", "no-cache");
        out.println("<response>");
        out.println(res);
        out.println("</response>");
        out.close();
    }
   
    /** Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        doGet(request, response);
    }
   
    /** Returns a short description of the servlet.
     */
    public String getServletInfo() {
        return "Short description";
    }
}


<ProgressBarServlet.java 의 전체 소스 코드>

우선 실행 결과 화면을 먼저 살펴보자.

 



위 그림에서 Launch 버튼을 클릭하면 아래와 같은 상태바 결과를 확인 할 수 있다.


이런 상태바 프로그램을 작성하는데에는 ajax 가 정말 적합하다고 생각한다. 물론 자바스크립트 코드가 많아져서 이해하는데 어려움이 있을 수도 있지만 ajax 을 사용하지 않고 다른 방식으로 구현한다고 했을때 가능은 하겠지만 이때에도 역시 스크립팅 코드가 없을 수 만은 없다.

 

소스 코드는 이전예제와 별로 크게 다르지 않으므로 설명은 생략한다.

 

'WEB2.0 > ajax' 카테고리의 다른 글

웹서비스 접근하기  (0) 2006.04.12
툴팁 구현하기  (0) 2006.04.12
Auto Refresh 기능 구현하기  (0) 2006.04.11
동적으로 리스트박스 구성하기  (0) 2006.04.11
응답 헤더정보 다루기  (0) 2006.04.11
 
블로그 이미지

시반

시반(詩伴)이란 함께 시를 짓는 벗이란 뜻을 가지고 있습니다. 함께 나눌수 있는 그런 공간이길 바라며...

카테고리

분류 전체보기 (233)
개발 이야기 (73)
WEB2.0 (57)
DB2 (24)
MySQL (6)
오라클 (26)
기타 (44)
취미 (0)
잡담 (2)