XMLHttpRequest란
XMLHttpRequest 객체는 Ajax의 핵심이며, 클라이언트와 서버 간의 통신을 담당하는 객체다. 또한 클라이언트와 서버 간에 통신할 때 가장 먼저 생생해야 하는 객체다.
XMLHttpRequest 객체 생성 코드
window.onload = function()
{
//1. 브라우저에 따른 XMLHttpRequest 생성
var xmlHttp = createXMLHTTPObject();
}
//1. 브라우저에 따른 XMLHttpRequest 생성
function createXMLHTTPObject()
{
var xhr = null;
if(window.XMLHttpRequest)
{
//IE7+, 크롬, 사파리, 파이어폭스, 오페라는 XMLHttpRequest 객체를 제공한다.
xhr = new XMLHttpRequest();
}
else
{
//IE5,6 버전에서는 다음과 같은 방법으로 XMLHttpRequest 객체를 생성한다.
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
return xhr;
}
대부분의 브라우저에서 XMLHttpRequest 객체를 제공하고 있으며, IE 5,6 버전을 사용하지 않는 추세이고 해당 프로젝트에서 IE6이하는 고려하지 않는다면 위와 같은 코드로 작성하지 않아도 된다. 위의 부분은 거의 공식처럼 사용되며 jQuery Ajax 내부에도 이와 같은 방식으로 XMLHttpRequest 객체를 생성한다. jQuery Ajax에는 바로 위와 같은 작업이 모두 포장되어 있어 더 쉽게 사용이 가능하다.
주요 메서드
메서드명 |
설명 |
매개 변수 |
반환값 |
open(method,url,[async:true]) |
요청 매개변수를 초기화하는 메서드로써 URL에 지정한 서버의 페이지에 어떤 내용을 요청하는데 데이터는 GET/POST 방식으로 보낼 것이며 응답은 동기/비동기로 받을 것이므로 XMLHttpRequest 객체를 준비하라는 것과 같다. |
- method : 데이터 전송방식(GET/POST) - url : 요청대상 URL - async : 요청에 대한 응답을 기다리는 방식, 비동기(true:기본값), 동기(false) |
없음 |
send(data) |
HTTP 요청을 실제로 실행하는 메서드다. 이 메서드가 실행되어야 요청이 서버에 전달되기 시작한다. |
- data : POST 방식으로 보낼 데이터 |
없음 |
주요 프로퍼티
프로퍼티 |
설명 |
readyState |
요청상태를 나타내며, 이 프로퍼티를 이용하면 클라이언트와 서버 간의 데이터 통신이 현재 어디까지 진행되고 있는지 확인 할 수 있다.
0 : 초기화 되지 않은 상태 1 : 로드되지 않은 상태(즉, send() 메서드가 호출되지 않은 상태) 2 : 로드된 상태, 헤더와 상태는 받았으나 아직 응답을 받지 못한 상태 3 : 상호작용 상태, 데이터의 일부분만 받은 상태 4 : 완료 상태, 모든 데이터를 받아서 완료된 상태 |
onreadystatechange |
요청상태가 변경될 때 발생하는 이벤트 |
responseText |
서버 응답에 반환된 본문 콘텐츠 |
responseXML |
서버 응답이 XML인 겨웅 이 프로퍼티에 XML 본문 콘텐츠가 채워진다. |
status |
서버 응답 상태 200 : 성공 404 : 페이지를 찾을 수 없음 |
statusText |
응답으로 반환된 상태 메세지 |
응답 이벤트 처리(요청에 대한 응답처리 이벤트 리스너 등록)
XMLHttpRequest 객체의 onreadystatechange 이벤트는 클라이언트와 서버 간의 데이터 전송 상태가 바뀔 때마다 발생하는 이벤트다. 즉, 서버가 클라이언트가 요청한 응답으로 보내는 데이터를 얻으려면 이 이벤트를 사용해야 한다. 이를 위해 먼저 실제 데이터 전송이 이루어지기 전 다음과 같은 이벤트 리스너를 등록해야 한다.
// 요청에 대한 응답 처리 이벤트 리스너 등록
xmlHttp.onreadystatechange = on_ReadyStateChange;
이후에 연결 요청 준비단계(open() 메서드)와 실제 데이터 전송(send() 메서드)이 이루어지면 앞의 코드, 이벤트 리스너로 등록한 on_ReadyStateChange() 리스너 함수가 실행되고 데이터를 주고받는 과정에서 통신이 정상적으로 이루어졌다면 언제인지 알아내면 된다.
통신 시점의 상태를 알아내는 코드
//응답처리
function on_ReadyStateChange()
{
/*
0 : 초기화 전
1 : 로딩 중
2 : 로딩 됨
3 : 대화 상태
4 : 데이터 전송완료
*/
//4 : 데이터 전송완료
if(xmlHttp.readyState == 4)
{
//200은 에러 없음을 의미(404 : 페이지가 존재하지 않음)
if(xmlHttp.status == 200)
{
/*
이 영역에서 서버에 보낸 데이터를
타입(XML, JSON, CSV)에 따라 처리
*/
}
else
{
alert('처리 중 에러가 발생했습니다.');
}
}
}
정상적으로 서버와의 통신이 이루어졌다면 이때 서버에서 보내온 데이터가 담긴 responseText와 responseXML 프로퍼티를 사용하면 된다.
GET 방식, POST 방식
GET과 POST는 HTTP 메서드의 한 종류이며, HTTP 메서드는 클라이언트 데이터(매개변수)를 서버로 보내는 방식을 의미한다. HTTP 메서드로는 GET, POST 이외에 PUT, TRACE와 같은 메서드가 있으며 대표적으로 GET, POST 방식을 많이 사용한다.
GET 방식
서버로 보낼 클라이언트의 데이터를 URL에 포함시켜서 보내는 방법을 GET 방식이라고 한다.
ex) http://주소?매개변수=값&매개변수=값...
ex) http://erum.com/index.jsp?name=dream&pw=1234
위와 같은 GET 방식으로 서버에 데이터를 보내는 경우는 주소 다음에 "?"를 넣은 후 매개변수=값을 넣어준다. 데이터가 여러 개인 경우는 구분자로 "&"를 사용한다.
GET 방식으로는 보낼 수 있는 데이터의 양이 정해져 있기 때문에 간단한 데이터를 보낼 때 주로 사용한다. 또한 URL에 데이터를 포함시켜 보내다 보니 전송하는 내용이 모두 눈에 보이기 때문에 중요한 데이터 내용이 포함된 경우는 GET 방식으로는 보내지 않는 편이 바람직하다.
적용방법 : XMLHttpRequest의 open() 메서드의 첫번째 매개변수로 "GET"을 넣어주고, 두번째 매개변수는 서버로 보낼 데이터가 있는 경우 요청 URL에 데이터를 문자열로 넣어준다.
var data = 'id=eroom&pw=1234';
xmlHttp.open('GET','index.jsp?'+data,true);
//서버로 보낼 데이터가 없는 경우 요청 URL만 작성
xmlHttp.open('GET', 'index.jsp?', true);
마지막으로 xmlHttp.send(null) 메서드를 실행하면 통신이 시작된다. 세번째 매개변수 true는 비동기를 뜻한다.
POST 방식
GET 방식과는 달리 POST 방식은 많은 양의 데이터를 한꺼번에 보낼 때 유용하다. 일반적으로 POST 방식은 폼(Form) 태그 안에 입력한 사용자 정보를 보낼 때 주로 사용한다. 만약 GET 방식으로 보낸다면 전송해야 할 내용을 모두 문자열로 만들어야 하기 때문에 번거로운 작업을 거쳐야한다. POST 방식은 폼 태그 내부에 정보를 매우 쉽게 한번에 전송할 수 있다. Ajax에서는 POST 방식으로 데이터를 보낼 때 폼 태그에 실어서 보내는 것이 아니라 약간의 작업이 필요하다.
적용방법 : XMLHttpRequest의 open() 메서드의 첫번째 매개변수로 "POST"를 넣어주고, 두번째 매개변수는 서버로 보낼 데이터를 뺀 요청할 URL만 지정한다. 그리고 세번째 매개변수는 대부분 비동기로 응답을 받기 때문에 true를 지정한다.
xmlHttp.open('POST','index.jsp',true);
xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
그리고 POST 방식에서는 위와 같이 setRequestHeader에 콘텐츠 타입이 form-urlencode임을 지정해야 한다.
GET방 방식에서는 send() 메서드에 null을 지정했던 것과 달리 POST 방식에서는 send() 메서드의 매개변수 값으로 서버에 보낼 데이터를 넣어서 실행하면 통신이 시작된다.
xmlHttp.send('id=hj&pw=1234')
서버 응답 방식 설정 - 동기(Synchronous) 방식
window.onload = function()
{
//1. 요청 객체 생성 : 웹 표준 지원 브라우저 일 경우
var xmlHttp = new XMLHttpRequest();
//2. 요청에 대한 응답 처리 이벤트 리스너 등록
xmlHttp.onreadystatechange = on_ReadyStateChange;
//3. 서버로 보낼 매개변수 생성
var strParam = 'id=HJ&pw=1234'
//4. 클라이언트와 서버 간의 연결 요청 준비(open() 메서드 이용)
xmlHttp.open('GET', 'test.jsp?' + strParam, false);
//5. 실제 데이터 전송(send() 메서드 이용)
xmlHttp.send('id=HJ&pw=1234');
//Transmit ::: 동기/비동기 실행 테스트
alert('전송시작');
};
//6. 응답처리
function on_ReadyStateChange()
{
/*
0 : 초기화 전
1 : 로딩 중
2 : 로딩 됨
3 : 대화 상태
4 : 데이터 전송완료
*/
//4 : 데이터 전송완료
if(xmlHttp.readyState == 4)
{
//200은 에러 없음(404 : 페이지가 존재하지 않음)
if(xmlHttp.status == 200)
{
//7. 데이터 처리
/*
이 영역에서 서버에서 보낸 데이터를 타입(XML, JSON, CSV)에 따라 처리
*/
console.log('이 부분에서 데이터를 처리한다.');
}
else
{
console.log('처리 중 에러가 발생했습니다.');
}
}
}
동기 방식에서는 send() 메서드에 의해 서버 통신이 시작되면 send() 이후의 5. 실제 데이터 전송, 6. 응답 처리, 7. CSV, XML, JSON에 따른 데이터 처리, Transmit 부분에서 5,6,7의 단계를 실행하고 클라이언트와 서버 간의 요청과 응답이 모두 끝나면 Transmit 부분의 내용이 실행된다. 다시 말해 5단계의 send() 메서드에 의해 실제 데이터 통신, 전송이 이루어지면 잠시 후에 클라이언트에 대한 요청 응답이 정상적으로 이루어진 경우 on_ReadyjStateChange() 메서드 내부의 7단계의 구문이 실행된다. 이와 관련된 모든 처리가 끝나면 비로소 Transmit 단계 부분의 구문이 실행된다.
동기 방식은 특성상 요청에 대한 응답이 언제 올지 모르기 때문에 다른 일들을 아무것도 처리하지 못한 채 기다려야한다. 따라서 특별한 경우를 제외하고 거의 사용하지 않는다.
서버 응답 방식 설정 - 비동기(Asynchronous) 방식
비동기 방식은 동기 방식의 반대로 서버 요청에 대한 응답을 무작정 기다리는 것이 아니라 응답을 보낸 후 바로 다음 작업을 진행할 수 있다. 비동기 방식에서는 open() 메서드의 세 번째 매개변수로 false 대신 true를 지정하기만 하면 비동기로 응답 받을 수 있다.
window.onload = function()
{
//1. 요청 객체 생성 : 웹 표준 지원 브라우저 일 경우
var xmlHttp = new XMLHttpRequest();
//2. 요청에 대한 응답 처리 이벤트 리스너 등록
xmlHttp.onreadystatechange = on_ReadyStateChange;
//3. 서버로 보낼 매개변수 생성
var strParam = 'id=HJ&pw=1234'
//4. 클라이언트와 서버 간의 연결 요청 준비(open() 메서드 이용)
xmlHttp.open('GET', 'test.jsp?' + strParam, true);
//5. 실제 데이터 전송(send() 메서드 이용)
xmlHttp.send('id=HJ&pw=1234');
//Transmit ::: 동기/비동기 실행 테스트
alert('전송시작');
};
//6. 응답처리
function on_ReadyStateChange()
{
//4 : 데이터 전송완료
if(xmlHttp.readyState == 4)
{
//200은 에러 없음(404는 페이지가 존재하지 않음)
if(xmlHttp.status == 200)
{
//7 : 데이터 처리
//이 영역에서 서버에서 보낸 데이터를 타입(XML, JSON, CSV)에 따라 처리
console.log('이 부분에서 데이터를 처리합니다.');
}
else
{
console.log('처리 중 에러가 발생했습니다.');
}
}
}
비동기 방식에서는 5단계의 send() 메서드에 의해 데이터가 전송되면 Transmit 단계에서 해당하는 구분이 아무런 기다림 없이 바로 실행된다. 그리고 이 후 클라이언트에 대한 요청이 모두 정상적으로 이루어지면 7번에 해당하는 구문이 실행된다.
즉, 동기 방식과 비동기 방식의 가장 큰 차이점은 send() 메서드를 실행하여 클라이언트 요청을 서버로 보낸 후에 응답이 올 때까지 다음 구문인 Transmit 영역을 실행하지 않고 그자리에서 다른 일을 아무것도 하지 않은 채 기다릴지(동기), 아니면 기다리지 않고 바로 이어서 그 다음 구문을 실행할 것(비동기)인지다.
응답형식
send() 함수가 실행되면 요청이 서버로 전송되고 그 이후 서버는 요청에 대한 응답으로 데이터를 보내주는데, 이때 서버에서는 주로 CSV, XML, JSON이라는 세 가지 데이터 타입 중의 하나를 선택한 후 타입에 맞게 데이터를 가공해서 보내주게 된다. 그리고 클라이언트에서는 이렇게 받은 응답 데이터를 형식에 맞게 변환하여 사용한다.
CSV(Comma Separated Value)
CSV는 세가지 타입 중에 가장 단순하면서 평범한 텍스트 형식이다. CSV 풀네임에서도 알 수 있듯이 서버 측 응답 내용을 특정 구분자를 추가해서 하나의 문자열로 보내는 방식이다. 구분자로는 콤마(Comma) 말고도 사용자가 원하는 문자를 사용할 수 있다. 서버에서는 다음과 같이 클라이언트 요청에 대한 결과 값을 특정 구분자로 묶어 하나의 긴 문자열로 만들어 응답으로 보낸다.
/*
사용된 구분자 = ","
"hanjin,1234"
사용된 구분자 = "||"
"id=hanjin||pw=1234"
사용된 구분자 = "&"
"id=hanjin&pw=1234"
*/
//클라이언트는 서버에서 사용한 구분자를 토대로 결과값을 분리해서 데이터를 처리
var aryData = xmlHttp.responseText.split('||');
var objResult = {};
for(var i = 0; i < aryData.length; i++)
{
var keyValue = aryData[i].split('=');
objResult[keyValue[0]] = keyValue[1];
}
XML
서버에서는 다음과 같은 형태로 응답을 XML 형식으로 클라이언트에 보내준다.
header('Content-Type:text/xml; charset=utf-8');
<result>
<success>1</success>
<id>hanjin</id>
<pw>1234</pw>
</result>
그러면 클라이언트에서 다음과 같은 식으로 XML을 파싱해서 데이터를 처리한다.
var xmlHttp = new XMLHttpRequest();
//JavaScript DOM
var xmlInfo = xmlHttp.responseXML;
var id = xmlInfo.getElementsByTagName('id')[0];
var pw = xmlInfo.getElementsByTagName('pw')[0];
console.log('id=' + id.firstChild.nodeValue);
console.log('pw=' + pw.firstChild.nodeValue);
//jQuery DOM
$xmlInfo = $(xmlHttp.responseXML);
var id = $xmlInfo.find('id').text();
var pw = $xmlInfo.find('pw').text();
console.log('id='+id);
console.log('pw='+pw);
JSON(JavaScript Object Notation)
JSON도 CSV와 마찬가지로 특정 규칙에 정해진 형식으로써 자바스크립트 객체 구조를 지닌 문자열이다.
다음은 객체 리터럴 방식으로 정의한 자바스크립트의 객체다.
{
id : 'hanjin',
pw : '1234'
}
위의 객체를 그대로 문자열로 표현하면 다음과 같다.
var str = '{';
str += ' "id" : "hanjin",';
str += ' "pw" : "1234",';
str += '}';
바로 이런 스타일을 JSON 형식이라고 한다.
서버에서는 아래와 같이 응답을 JSON 형식 문자열로 클라이언트에게 보낸다.
$result = '{';
$result. = ' "id" : "hanjin",';
$result. = ' "pw" : "1234",';
$result. = '}';
echo($result);
그러면 클라이언트에서는 응답받은 JSON 형식 문자열을 자바스크립트 객체로 만들어 처리한다.
var xmlHttp = new XMLHttpRequest();
var objResult = eval('(' + xmlHttp.responseText + ')');
alert('id = ' + objResult.id);
alert('pw = ' + objResult.pw);