글 작성자: 택시 운전사
반응형

웹 어플리케이션의 사용성은 데스크톱 어플리케이션에 비해 현저히 떨어져있었다.

고전적인 웹 어플리케이션

  1. 유저가 폼 영역을 채우고 폼을 제출한다.
  2. 브라우저가 서버에게 보낼 요청을 생성한다.
  3. 서버가 브라우저가 렌더할 정확한 페이지를 포함한 응답을 생성하고 보낸다.
  4. 브라우저가 새로운 페이지를 로드하고, 잠시 브라우저의 윈도우가 깜빡거린다.
  5. 클라이언트는 서버의 답을 기다리고 전체 페이지를 새로운 데이터로 다시 로드한다

동기적인 요청이 서버에서 처리되는 동안, 유저는 클라이언트 웹 브라우저와 상호작용할 수 없다. 동기적 모델은 하이퍼텍스트 문서들의 웹을 위해 고안되었다.

Ajax 웹 어플리케이션

Ajax 어플리케이션에서, 유저는 페이지와 상호작용한다.

  1. 클라이언트는 요청을 처리하기 위해 XMLHttpRequest라는 객체를 생성한다.
  2. XMLHttpRequest 객체는 요청을 서버에 보내고 서버로부터 응답을 기다린다.
  3. 요청들은 비동기적이다. 즉, 서버가 동시에 요청을 처리하면서 유저는 계속해서 어플리케이션과 상호작용할 수 있게 한다.
  4. 서버가 응답하면, 요청을 했던 XMLHttpRequest 객체에서 콜백 함수를 작동시킨다. 이를 통해 반환된 데이터가 다시 로딩하는 일없이 전체 페이지가 아닌 부분적인 페이지를 업데이트한다.
    콜백 함수는 페이지의 지정된 부분만 업데이트한다. 부분적 페이지 업데이트는 웹 어플리케이션을 더욱 반응성있게 보이게하고, 더욱 데스크톱 어플리케이션처럼 보이게한다.

RIAs(Rich Internet Application)

외관과 사용성이 데스크톱 어플리케이션과 거의 비슷한 웹 어플리케이션으로 성능과 다양한 GUI라는 속성을 가지고 있다. 또한 이런 RIA 성능은 클라이언트 부분의 웹 어플리케이션을 더욱 반응성있게 만들어주는 스크립팅인 Ajax(Asynchronous JavaScript and XML)의 덕이다.

Ajax

Ajax는 Asynchronous JavaScript and XML의 약자로 빠르고 동적인 웹 페이지를 만들기 위한 기술이다. Ajax는 클라이언트 부분의 유저 상호작용과 서버 의사소통을 분리하고 서버 부분의 작동에서 생기는 지연을 유저에게 더욱 투명하게 보여주면서 이 둘을 동시에 진행시킨다. 날 것의 Ajax는 자바스크립트를 서버에 비동기적 요청을 보내는 데 사용하고, 해당 페이지를 DOM을 이용하여 수정한다.

XMLHttpRequest 객체

모든 현대 브라우저들은 XMLHttpRequest 객체를 지원한다. XMLHttpRequest는 안 보이는 곳에서 서버간의 데이터를 교환하기 위해 사용되었다. 이는 다시 로딩하는 일 없이 전체가 아닌 웹 페이지의 일부분을 업데이트할 수 있음을 의미한다.

var xmlhttp = new XMLHttpRequest();

onreadystatechange 이벤트

서버로 요청이 보내졌을 때, 우리는 응답에 기반한 어떠한 동작이 있기를 바란다. onreadystatechange 이벤트는 매시간 readyState가 변할 때마다 작동된다. 즉, readyState값은 XMLHttpRequest의 상태를 가지고 있다. onreadystatechange 이벤트에서 서버의 응답이 처리될 준비가 되었을 때, 우리는 어떤것이 일어나는 지 확인할 수 있다. readyState의 값이 4이고 status가 200일 때, 응답할 준비가 된 것이다.

xmlhttp.onreadystatechange=function(){
    if(xmlhttp.readyState==4 && xmlhttp.status==200){
        document.getElementById("foo").innerHTML = xmlhttp.responseText;
    }
}

예시

// /ajax_form.html
<html>

<head>
    <script>
        function showHint(str) {
            index_element = document.getElementById("index");
            name_element = document.getElementById("name");
            if (str.length == 0) {
                index_element.innerHTML = "";
                name_element = "";
                return;
            } else {
                var xmlhttp = new XMLHttpRequest();
                xmlhttp.onreadystatechange = function () {
                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                        console.log(xmlhttp.responseText);
                        json = JSON.parse(xmlhttp.responseText);
                        json.forEach((el, idx) => {
                            index_element.innerHTML += el.index;
                            name_element.innerHTML += el.name;
                            if (idx !== json.length - 1) {
                                index_element.innerHTML += ", ";
                                name_element.innerHTML += ", ";
                            }
                        });
                    }
                };
                xmlhttp.open("GET",
                    "cgi-bin/ajax_search.php?q=" + str, true);
                xmlhttp.send();
            }
        }
    </script>
</head>

<body>

    <p><b>Start typing a name in the input field below:</b></p>
    <form>
        Name: <input type="text" onkeyup="showHint(this.value)">
    </form>
    <p>Suggestion Index: <span id="index"></span></p>
    <p>Suggestion Name: <span id="name"></span></p>
</body>

</html>
// ./cgi-big/ajax_search.php
<?php
// Array with names
$a[] = "Anna";
$a[] = "Brittany";
$a[] = "Cinderella";
$a[] = "Diana";
$a[] = "Eva";
$a[] = "Fiona";
$a[] = "Gunda";
$a[] = "Hege";
$a[] = "Inga";
$a[] = "Johanna";
$a[] = "Kitty";
$a[] = "Linda";
$a[] = "Nina";
$a[] = "Ophelia";
$a[] = "Petunia";
$a[] = "Amanda";
$a[] = "Raquel";
$a[] = "Cindy";
$a[] = "Doris";
$a[] = "Eve";
$a[] = "Evita";
$a[] = "Sunniva";
$a[] = "Tove";
$a[] = "Unni";
$a[] = "Violet";
$a[] = "Liza";
$a[] = "Elizabeth";
$a[] = "Ellen";
$a[] = "Wenche";
$a[] = "Vicky";

// get the q parameter from URL
$q = $_REQUEST["q"];

$hint = array();

// lookup all hints from array if $q is different from "" 
if ($q !== "") {
    $q = strtolower($q);
    $len = strlen($q);
    foreach ($a as $name) {
        if (stristr($q, substr($name, 0, $len))) {
            if ($hint === "") {
                $obj = array();
                $idx = array_search($name, $a);
                $obj['index'] = $idx;
                $obj['name'] = $a[$idx];
                array_push($hint, $obj);
            } else {
                $obj = array();
                $idx = array_search($name, $a);
                $obj['index'] = $idx;
                $obj['name'] = $a[$idx];
                array_push($hint, $obj);
            }
        }
    }
}
// Output "no suggestion" if no hint was found or output correct values 
echo $hint === null ? "no suggestion" : json_encode($hint);
반응형