이번 페이지에서는 Ajax에 대해서 좀 정리해 보겠습니다.
※ 아래에 기술되는 내용의 출처 : http://ko.wikipedia.org/wiki/Ajax
- 표현 정보를 위한 HTML (또는 XHTML) 과 CSS
- 동적인 화면 출력 및 표시 정보와의 상호작용을 위한 DOM, 자바스크립트
- 웹 서버와 비동기적으로 데이터를 교환하고 조작하기 위한 XML, XSLT, XMLHttpRequest (Ajax 애플리케이션은 XML/XSLT 대신 미리 정의된 HTML 이나 일반 텍스트, JSON, JSON-RPC를 이용할 수 있다).
※ 기존 기술과의 차이점
기존의 웹 애플리케이션은 브라우저에서 폼을 채우고 이를 웹 서버로 제출(submit)을 하면 하나의 요청으로 웹 서버에 전달 된다. 웹 서버는 요청된 내용에 따라서 데이터를 가공하여 새로운 웹 페이지를 작성하고 응답으로 되돌려준다. 이때 최초에 폼을 가지고 있던 페이지와 사용자가 이 폼을 채워 결과물로서 되돌려 받은 페이지는 일반적으로 유사한 내용을 가지고 있는 경우가 많다. 결과적으로 중복되는 HTML 코드를 다시 한번 전송 받게 됨으로써 많은 대역폭을 낭비하게 된다. 대역폭의 낭비는 금전적 손실을 야기할 수 있으며 사용자와 대화(상호 반응)하는 서비스를 만들기 어렵게도 한다. 반면에 Ajax 애플리케이션은 필요한 데이터만을 웹서버에 요청해서 받은 후 클라이언트에서 데이터에 대한 처리를 할 수 있다. 보통 SOAP이나 XML 기반의 웹 서비스 프로토콜이 사용되며, 웹 서버의 응답을 처리하기 위해 클라이언트 쪽에서는 자바스크립트를 쓴다. 웹 서버에서 전적으로 처리되던 데이터 처리의 일부분이 클라이언트 쪽에서 처리 되므로 웹 브라우저와 웹 서버 사이에 교환되는 데이터량과 웹서버의 데이터 처리량도 줄어들기 때문에 애플리케이션의 응답성이 좋아진다. 또한 웹서버의 데이터 처리에 대한 부하를 줄여주는 일이 요청을 주는 수많은 컴퓨터에 대해서 일어나기 때문에 전체적인 웹 서버 처리량도 줄어들게 된다.
장점
- 페이지 이동없이 고속으로 화면을 전환할 수 있다.
- 서버 처리를 기다리지 않고, 비동기 요청이 가능하다.
- 수신하는 데이터 량을 줄일 수 있고, 클라이언트에게 처리를 위임할 수도 있다.
- Ajax를 쓸 수 없는 브라우저에 대한 문제가 있다.
- Http클라이언트의 기능이 한정되어 있다.
- 페이지 이동없는 통신으로 인한 보안상의 문제
- 지원하는 Charset이 한정되어 있다.
- 스크립트로 작성되므로 Debugging이 용이하지 않다.
- 요청을 남발하면 역으로 서버 부하가 늘 수 있음.
※ Ajax의 보급
이것은 이미 존재하던 기술이었지만, 2005년 초에 있었던 몇 가지 사례 이후로 인기를 끌기 시작했다. 먼저 구글이 구글 그룹스를 포함한 훌륭한 대화형 애플리케이션의 기반을 위해 비동기식 통신을 이용한 것이다. 두 번째로는 Ajax라는 용어가 AJAX: A new approach for a new application[2] 기사에서 등장한 것으로, 이후 빠르게 대중화되어 이 기법의 보급에 도움이 되었다.
현재 대화형 웹 페이지를 위한 도구로서 Ajax를 이용하는 애플리케이션들이 급격히 늘어나고 있으며, 이는 부분적으로 이용할 수 있는 애플리케이션 툴킷(예: Ruby on Rails, DWR)이 늘어나 프로그래머들이 구현하기가 쉬워진 때문이다.
대한민국에서도 네이버와 다음등을 비롯한 포털 업체에서 이 기술을 도입하고 있다.
※ 아래에 기술되는 내용의 출처 : http://mainia.tistory.com/314
비동기 자바스크립트와 XML (Asynchronous Javascript and XML) 를 의미하며 기술이라기 보다 기술자들이 개발자가 좀더 쉽게 접근할수 있도록 인터페이스를 만든 방법론이라고 할수있다.
그리고 웹에 존재하는 DHTML, CSS, XML, XMLHttpRequest등의 기술들을 합친 새로운 기술이라고 할수있다.
2. AJAX 사용이유
AJAX를 사용하는 가장 큰 이유는 웹에서 액티브X, 플래시 또는 자바 애플릿 등에 의존했던 사용성, 접근성, 응답성의 향상이다. 네트워크 인프라가 발전하여 네트워크 속도가 아무리 발라진다고 하더라도 새로운 컨텐츠를 보여주기 위해서 웹 페이지 전체가 매번 리로딩되는 것은 사용성, 응답성의 한계로 이어질 수밖에는 없다.
액티브X, 자바 애플릿, 플래시 등이 그 대안이 될 수 있다.
하지만 그러한 기술들 대신에 AJAX가 가질 수 있는 경쟁력을 얘기하자면 플러그인을 사용하지 않고 브라우저만으로 바로 이용할 수 있다는 것과 새로운 것을 배우지 않고 DHTML, 자바스크립트, CSS등의 기존 웹 기술들을 그대로 이용할 수 있다는 것이다.
이러한 장점들은 지금도 널리 사용되고 있는 액티브X, 자바 애플릿, 플래시 등의 기술에 대한 대안으로 AJAX에 관심을 가져볼만한 충분한 이유를 준다.
3. AJAX 구성요소들 UML
기존웹은 응답이 올 때 까지 기다리지만 AJAX 를 이용한 사용자는 진행중이라는 값과 결과값을 진행중이나 진행후에 받게 된다.
※ XMLHTTPRequest 객체
- Method
Method |
Description |
abort() |
|
getAllResponseHeaders() |
|
getResponseHeader( headerName ) |
|
open( method, URL ) open( method, URL, async ) open( method, URL, async, userName ) open( method, URL, async, userName, password ) |
|
send( content ) |
|
setRequestHeader( label, value ) |
|
Property |
Description |
onreadystatechange |
XMLHTTPRequest 객체의 상태가 변할 때 실행할 핸들러를 지정한다. |
readyState |
XMLHTTPRequest 객체의 상태가 변할 때 각 상태값을 반환한다. 0 = uninitialized 1 = loading 2 = loaded 3 = interactive 4 = complete |
responseText |
HTTP 요청결과를 문자열 형태로 반환한다. |
responseXML |
HTTP 요청결과를 XMLDocument 오브젝트로 반환한다. |
responseBody |
|
status |
HTTP 응답코드를 반환한다. 성공일 경우 200 |
statusText |
HTTP 응답문자열을 반환한다. 성공인 경우 OK |
4. 전체적인 예제
GET 방식일때는 send 함수 첫번째 파라미터에 "GET" 이라고 입력한다.
헤더값을 셋팅하는데 charset=UTF-8 인코더 해서 보내면된다.
자기가 원하는 인코더 값을 넣어서 보내도 된다. 그러면 디코더 할 때 같은 값으로 해야될것이다.
마지막으로 GET 방식이므로 send 함수에 파라미터 값은 null 이 된다.
// GET 전송요청
function startRequest()
{
var form = document.frmAdd;
createXMLHttpRequest();
xmlHttp.open("GET", url, true);
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form- urlencoded;charset=UTF-8");
xmlHttp.setRequestHeader("Cache-Control",
"no-cache, must-revalidate");
xmlHttp.setRequestHeader("Pragma", "no-cache");
xmlHttp.onreadystatechange = handleStateChange;
xmlHttp.send(null);
}
위의 함수에서보면 onreadystatechange 에 함수명을 넘기는데 이것을 callback 함수라고 한다.
Ajax 의 기본동작은 비동기인데 넘기고 나서 그 결과를 함수에 전달하게 되는데 내용은
다음과 같다.
// callback함수
function handleStateChange()
{
if (xmlHttp.readyState == 4)
{
if (xmlHttp.status == 200)
{
updateSecondMenu();
}
else if (xmlHttp.status == 400){
alert("404 Error : " + xmlHttp.responseText);
}
}
}
xmlHttp.status == 200 일때 (응답이 성공적일 때) 실행하는 함수인데 화면에서 id selSecondMenu를 가진 select 에 option 요소를 받아온 내용만큼 집어넣는 내용이다.
function updateSecondMenu()
{
// 모든 데이타를 없애고 초기화 한다.
clearModeList();
var selSecondMenu = document.getElementById("selSecondMenu");
var results = xmlHttp.responseXML.getElementsByTagName("model");
var option = null;
for(int i=0; i<results.length; i++)
{
option = document.createElement("option");
option.appendChild(document.createTextNode(results[i].firstChild.nodeValue));
selSecondMenu.appendChild(option);
}
}
Option 태그를 집어넣기 전에 select 내용을 모두 청소해준다.
function clearModelsList()
{
var models = document.getElementById("selSecondMenu");
while(models.childNodes.length > 0)
{
models.removeChild(models.childNodes[0]);
}
}
Html 의 내용은 다음과 같다.
<select id="selSecondMenu" name="selSecondMenu">
#if ($lstCommInfo.size() > 0)
#foreach($list in $lstSecondMenu)
<option value="$!{list.SORT_NO}">$!{list.SORT_NAME}</option>
#end
#else
<option value="0">첫번째메뉴선택</option>
#end
</select>
서버 java 파일의 내용이다. 내용의 핵심은 xml 로 내용을 구성하는 것이며, 그 구성요소명을
<model> 로 했다. 이 이름은 클라이언트 함수에서 엑세스 할 때 다음과 같이 쓰인다.
var results = xmlHttp.responseXML.getElementsByTagName("model");
List availableModel = new ArrayList();
StringBuffer results = new StringBuffer("<models>");
MakeModelYear makeModelYear; // 사용자정의 bean
for (Iterator it = availableModel.iterator(); it.hasNext();)
{
makeModelYear = (MakeModelYear)it.next();
results.append("<model>");
results.append(makeModelYear.getModel());
results.append("</model>");
}
results.append("</models>");
response.setContentType("text/xml;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
PrintWriter out = response.getWriter();
out.println(results.toString());
out.close();
(2) POST 방식으로 데이터 전송
POST 로 전송하기 위해서는 전송데이터를 구성해서 보내야하는데 그 구성요소는 [이름] = [값]&[이름] = [값]… 의 반복으로 이루어진다.
그러면 서버에선 request.getParameter 받을 수가 있다.
POST 로 전송하기 위해서 파싱하는 함수는 다음과 같다.
함수의 내용을 보면 알겠지만 각 element 값을 가져와 이름=값 으로 구성하는 것을 볼수있다.
// POST 전송을 위한 Ajax 셋팅
function setQueryString(form)
{
var queryString = "";
var obj = form;
var numberElements = obj.elements.length - 1;
for (var i=0; i < numberElements; i++)
{
if ( i < numberElements - 1)
{
queryString += obj.elements[i].name + "=" +
escape(obj.elements[i].value) + "&";
}
else
{
queryString += obj.elements[i].name + "=" +
escape(obj.elements[i].value);
}
}
return queryString;
}
위의 startRequest 와 대부분 내용이 같지만 xmlHttp.send 파라미터 값으로 setQueryString 함수에서 추출한 화면상의 데이터를 구성한 문자열을 넘기는게 차이다.
var form = document.frmAdd;
createXMLHttpRequest();
xmlHttp.open("GET", url, true);
xmlHttp.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
xmlHttp.setRequestHeader("Cache-Control",
"no-cache, must-revalidate");
xmlHttp.setRequestHeader("Pragma", "no-cache");
xmlHttp.onreadystatechange = handleStateChange;
var params = setQueryString(form);
xmlHttp.send(params);
(3) xml 방식과 text 방식
xml 방식은 서버 java 에서 response 객체에 text/xml 셋팅을 하고 넘기면
response.setContentType("text/xml;charset=UTF-8");
control 페이지에서 xmlHttp.responseXML 써서 값을 읽어들이면 된다.
xml 은 element 로 구성이 되어있고 그것을 분리하여 사용해야 되므로 getElementsByTagName 같은 함수를 써서 객체를 반환받은후 적절하게 사용하면된다.
text 방식은 서버 java 에서 response 객체에 text/html 셋팅을 하고 넘기면
response.setContentType("text/html;charset=UTF-8");
control 페이지에서 xmlHttp.responseText 써서 값을 읽어들이면 된다.