여기서는 AJAX의 기본을 익힐수 있도록 해주며, 두 가지 간단한 훈련용 예제를 제공합니다.
AJAX란?
AJAX란 비동기 JavaScript와 XML을 말합니다. 간단히 말하면, 서버측 Scripts와 통신하기 위한 XMLHttpRequest객체를 사용하는 것을 말합니다. 서버측으로 다양한 형식(JSON, XML, HTML 및 일반 텍스트 형식 등)의 정보를 주고 받을 수 있습니다. AJAX의 강력한 특징은 페이지 전체를 리프레쉬 하지 않고서도 수행 되는 "비동기성"입니다. 이러한 비동기성을 통해 사용자의 Event가 있으면 전체 페이지가 아닌 일부분만을 업데이트 할 수 있게 해줍니다.
다시 말해 아래와 같이 두가지로 정리됩니다.
- 페이지 일부분을 업데이트 하기 위한 정보를 서버에 요청할 수 있다.
- 서버로부터 받은 데이터로 작업을 한다.
1단계 – HTTP request만들기
JavaScript를 이용하여 서버로 보내는 HTTP
request를 만들기 위해서는 이런 기능을 제공하는 클래스 인스턴스가 필요하다. 이런 클래스는 Internet Explorer에서는 XMLHTTP라고 불리는 ActivX object를 말한다. 그러면 Mozzlia, Safari나 다른 브라우저는 Microsoft의 ActiveX객체의 method와 property를 지원하기 위해 XMLHttpRequest
클래스를 구현 하고 있습니다.
따라서, 다음과 같이 하면 모든 브라우저에서 사용할 수 있는 인스턴스를 만들 수 있습니다.
var httpRequest; if (window.XMLHttpRequest) { // 모질라, 사파리등 그외 브라우저, ... httpRequest = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE 8 이상 httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); }
다음으로는, 위에서 만들어서 서버로 보낸 요청(request)에 대한 응답을 받았을때 어떤 동작을 할 것인지에 대한 사항을 정해야 합니다. 이 단계에서는 단순하게 위에 생성된 httpRequest의 onreadystatechange
property를 통해 어떤 함수가 그 동작을 수행 할 것인지 아래와 같이 할당하면 됩니다.
httpRequest.onreadystatechange = nameOfTheFunction;
주목할 사항으로는 위에서는 해당 함수를 수행하는 것이 아니라 단순하게 어떤 함수가 불릴 것인지만 지정한다는 점입니다. 단순하게 그 함수를 지정하는 것이므로 그 함수로 어떠한 변수도 전달하지 않습니다. 또한 단순하게 함수를 연결하면 되기 때문에 아래와 같이 JavaScript에서 사용되는 "임의 함수(anonymous functions)"방법으로 직접적인 함수 본체를 기입해도 됩니다.
httpRequest.onreadystatechange = function(){ // process the server response };
다음으로, 위와 같이 서버로 부터 응답을 받은 후의 동작을 결정 한 후에는 실질적으로 요청(request)를 하는 것 입니다. 요청(request)을 하기 위해서는 HTTP request class의 open()과 send()를 아래와 같이 호출하여야 합나다.
httpRequest.open('GET', 'https://www.example.org/some.file', true); httpRequest.send(null);
open()
메소드의 첫번째 파라미터는 HTTP 요구 방식(request method) - GET, POST, HEAD 중의 하나이거나 당신의 서버에서 지원하는 다른 방식- 입니다. 이 파라미터는 HTTP 표준에 따라 모두 대문자로 표기하십시오; 그렇지 않으면 (파이어폭스와 같은) 특정 브라우저는 이 요구를 처리하지 않을 수도 있습니다. 가능한 HTTP 요구 방식에 대한 정보는 W3C 명세를 참고하기 바랍니다.- 두번째 파라미터는 요구할 페이지의 URL 입니다. 보안을 위해 서드 파티 도메인 상의 페이지를 호출할 수는 없습니다. 요구하는 모든 페이지에 정확한 도메인 네임을 사용하십시오. 그렇지 않으면
open()
메소드를 호출할 때 'permission denied' 에러가 발생할 수 있습니다. 일반적인 오류는 당신의 사이트에 domain.tld 와 같은 형태로 접근하는 것 입니다. 이러한 경우 www.domain.tld 와 같은 형태로 페이지를 요구하기 바랍니다. - 세번째 파라미터는 요구가 비동기식(Asynchronous)으로 수행될 지를 결정합니다. 만약 이 파라미터가
TRUE
로 설정된 경우에는 자바스크립트 함수의 수행은 서버로부터 응답을 받기 전에도 계속 진행됩니다. 여기까지가 AJAX 의 기본입니다.
send()
메소드의 파라미터는 POST 방식으로 요구한 경우 서버로 보내고 싶은 어떠한 데이터라도 가능합니다. 데이터는 서버에서 쉽게 parse할 수 있는 형식(format)이어야 합니다. 예를 들자면 아래와 같습니다.
"name=value&anothername="+encodeURIComponent(myVar)+"&so=on"
또는 JSON, SOAP등과 같은 다른 형식으로도 가능합니다.
만약 "POST" type을 보내려 한다면, 요청(request)에 MINE type을 설정 해야 합니다. 예를 들자면 send()를 호출 하기 전에 아래와 같은 형태로 send()로 보낼 쿼리를 이용해야 합니다.
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
2단계 – 서버 응답에 대한 처리
요구(request)를 보냈을 때 이미 응답을 처리하기 위한 자바스크립트 함수의 이름을 지정했었다는 것을 기억하기 바랍니다.
http_request.onreadystatechange = nameOfTheFunction;
이제 이 함수가 어떤 일을 하는지 보기로 합시다. 먼저, 해당 함수에서는 요구의 상태값을 검사할 필요가 있습니다. 만약 상태값이 4 라면, 서버로부터 모든 응답을 받았으며 이를 처리할 준비가 되었다는 것을 뜻합니다.
if (http_request.readyState == 4) { // 이상 없음, 응답 받았음 } else { // 아직 준비되지 않음 }
readyState
가 가질 수 있는 모든 값의 목록은 아래와 같습니다:
- 0 (uninitialized)
- 1 (loading)
- 2 (loaded)
- 3 (interactive)
- 4 (complete)
(원문)
다음으로 검사할 것은 HTTP 서버 응답의 상태 코드입니다. 가능한 모든 코드 값의 목록은 W3C 사이트에서 확인할 수 있습니다. 여기서는 단지 정상적으로 처리된 상태를 나타내는 200 의 경우 만을 검사합니다.
if (http_request.status == 200) { // 이상 없음! } else { // 요구를 처리하는 과정에서 문제가 발생되었음 // 예를 들어 응답 상태 코드는 404 (Not Found) 이거나 // 혹은 500 (Internal Server Error) 이 될 수 있음 }
이제 요구와 그에 대한 응답에 대한 상태 코드를 검사했으므로, 서버에서 받은 데이터를 통해 원하는 작업을 수행할 수 있다. 그리고 위의 응답 데이터에 접근하기 위한 2 가지 옵션이 아래와 같이 있습니다.
http_request.responseText
– 서버의 응답을 텍스트 문자열로 반환할 것이다.http_request.responseXML
– 서버의 응답을XMLDocument
객체로 반환하며 당신은 자바스크립트의 DOM 함수들을 통해 이 객체를 다룰 수 있을 것이다.
위의 단계는 비동기식 요구(asynchronous request)를 사용했을 경우에 대한 설명입니다(즉, send()의 세번째 변수가 "true"일경우). 동기식(Synchronous) 요구(request)를 사용한다면 함수를 명시할 필요 없이 send()를 호출에 의해 반환되는 data를 바로 사용 할 수 있습니다. 이는 스크립트가 send()를 호출할때 멈춰지며 서버의 응답이 완료 될때까지 기다립니다.
3단계 – 간단한 예제
이제 이들을 한데 모아서 간단한 HTTP 요구를 수행해보겠습니다. 우리가 작성할 자바스크립트는 "I'm a test." 라는 문장이 적힌 test.html
이라는 HTML 문서를 요구해서 문서의 내용을 파라미터로 alert()
함수를 호출할 것입니다.
<span id="ajaxButton" style="cursor: pointer; text-decoration: underline"> Make a request </span> <script type="text/javascript"> (function() { var httpRequest; document.getElementById("ajaxButton").onclick = function() { makeRequest('test.html'); }; function makeRequest(url) { if (window.XMLHttpRequest) { // Mozilla, Safari, ... httpRequest = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE try { httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (!httpRequest) { alert('Giving up :( Cannot create an XMLHTTP instance'); return false; } httpRequest.onreadystatechange = alertContents; httpRequest.open('GET', url); httpRequest.send(); } function alertContents() { if (httpRequest.readyState === 4) { if (httpRequest.status === 200) { alert(httpRequest.responseText); } else { alert('There was a problem with the request.'); } } } })(); </script>
이 예제에서:
- 사용자는 브라우저 상의 "Make a request" 라는 링크를 클릭합니다;
- 그러면 같은 디렉토리 내의 HTML 파일의 이름인
test.html
를 파라미터로 하여makeRequest()
함수를 호출합니다; - 브라우저는 서버로 요구를 보내고
onreadystatechange
에 설정된alertContents()
함수가 수행됩니다; alertContents()
함수는 서버로부터 응답을 받았는지와 정상적으로 처리된 응답인지를 검사하여 그 경우test.html
파일의 내용을 파라미터로alert()
함수를 호출합니다.
주 1: Internet Explorer에서 동작하는 page를 만들 경우에는 Mozilla용에서 추가적으로 다음과 같은 작업이 필요합니다. 정적 XML 파일이 아니라, XML을 받기 위한 request를 보낼 때, 몇가지 응답 헤더를 설정해야 합니다. 헤더에 “Content-Type: application/xml”설정을 하지 않을 경우, IE는 접근하고자 하는 XML 요소 다음라인을 수행 한 직후 “Object Expected” JavaScript error를 발생시킬 것입니다.
주 2: 헤더에 “Cache-Control: no-cache”를 설정 하지 않는다면, 브라우저는 debugging "challenging."으로 만들고 해당 응답을 유지하며, 다시는 요청을 받지 않을 것입니다. 물론 항상 달라지는 “GET”의 추가 인자(시간정보나, 랜덤 넘버)를 추가 하여 cache되지 않도록 작업을 할 수도 있습니다.( bypassing the cache를 참고하세요)
주 3: 만약 http_request 변수가 전역적으로 사용되면, makeRequest() 함수를 호출하는 여러 함수들 사이에서 경쟁 상태가 발생할 수 있으며, 이 경우 다른 데이터를 덮어쓰게 됩니다. 이를 방지하기 위해서는 http_request 변수를 함수 내의 지역 변수로 선언하여 alertContent() 함수에 넘겨야 합니다.
주 4: 브라우저가 멈춰버리는 통신 에러 이벤트에서, “status” field를 접근하려 할때는 onreadystatechange메소드에서 예외에러를 발생 시킬 것입니다. Try…catch구문 안의 If..then statement를 잘 감싸져 있는지 확인하세요.
function alertContents(httpRequest) { try { if (httpRequest.readyState === 4) { if (httpRequest.status === 200) { alert(httpRequest.responseText); } else { alert('There was a problem with the request.'); } } } catch( e ) { alert('Caught Exception: ' + e.description); } }
4단계 – "The X-Files" or Working with the XML Response
앞의 예제에서 HTTP 요구(request)에 대한 응답을 받은후에 리퀘스트 오브젝트(request object) 중 reponseText
프로퍼티를 사용했습니다. 그리고 reponseText
은 test.html
파일의 내용을 가지고 있습니다. 이제 responseXML
를 사용해 봅시다.
첫째로, 나중에 서버에 요구할 수 있는 유효한 XML문서를 만들어 봅시다. 이 문서(test.xml)은 아래와 같은 내용을 담고 있습니다. :
<?xml version="1.0" ?> <root> I'm a test. </root>
실행 스크립트에서 서버에 대해 요청하는 라인을 아래와 같이 바꿔줘야 합니다. :
... onclick="makeRequest('test.xml')"> ...
그 다음에 alertContents()
함수에서, alert()
함수를 실행하는 라인, 즉, alert(http_request.responseText);
을 아래와 같이 바꿔줘야 합니다. :
var xmldoc = http_request.responseXML; var root_node = xmldoc.getElementsByTagName('root').item(0); alert(root_node.firstChild.data);
이 방법은 responseXML
에 의한 XMLDocument
오브젝트를 가져왔습니다. 그리고 XML문서에 포함된 데이터를 가져오기 위해서 DOM methods를 사용했습니다. test.xml
는 여기에서 볼 수 있으며 갱신된 테스트 스크립트는 여기에서 볼 수 있습니다.
DOM methods에 대한 더 자세한 사항은 Mozilla's DOM implementation 문서를 확인하십시오.