-
XMLHttpRequest 객체Full-Stack/Front-end 2008. 8. 2. 00:10
XMLHttpRequest?
HXMLHttpRequest객체는 본래 ActiveX의 구성요소 중 하나로 인터넷 익스플로러 5에서 처음 구현되었다. 최근에 모질라(Mozilla) 1.0과 사파리(Safari) 1.2에서 사실상의 표준으로 채택되기 전까지는 XMLHttpRequest가 인터넷 익스플로러에서만 제대로 작동한다는 사실 때문에 대부분의 개발자들은 이에 대한 사용을 꺼려왔다. 새로 나온 스펙(DOM 레벨3 로드와 저장)에서 많은 부분을 지원하기는 하지만 어쨌든 XMLHttpRequest가 W3C의 표준이 아니라는 사실을 기억하고 있어야 한다. 대부분의 브라우저에서 XMLHttpRequest의 메소드와 프로퍼티를 대부분 지원하고는 있지만 표준이 아니기 때문에 브라우저가 바뀌면 동작이 약간씩 달라질 수 있다. 현재는 파이어폭스(Firefox), 사파리(Safari), 오페라(Opera), 콘커러(Konqueror), 인터넷 익스플로러(Internet Explorer) 등의 브라우저만 XMLHttpRequest 객체가 동일하게 작동한다.
따라서 대다수 사용자가 아직도 예전의 브라우저를 통해 사이트나 프로그램에 접근하고 있다면 이들을 위해 몇 가지 대책을 세워놓아야 한다. Ajax 기법을 사용하고자 한다면 브라우저의 버전에 맞춘 또 다른 사이트를 구축하거나 프로그램이 눈에 띄지 않게 낮은 사양에 맞춰지도록 해야 한다. 대부분의 통계자료에 의하면 오늘날 XMLHttpRequest를 지원하지 않는 브라우저는 극소수에 불과하므로 이것이 문제가 될 가능성은 아주 낮다고 볼 수 있다. 어찌 됐든 개발자들은 웹 로그를 지속적으로 확인하여 사용자들이 어떤 클라이언트를 통해서 사이트에 접속하는지를 알아둘 필요가 있다.
1.XMLHttpRequest 객체 생성
XMLHttpRequest는 표준이 아니므로 객체의 인스턴스를 생성하는 데 있어서 몇 가지 방식으로 자바스크립트가 사용될 수 있다. 인터넷 익스플로러는 이것을 ActiveX 객체로 구현하였으나 파이어폭스(Firefox), 사파리(Safari), 오페라(Opera) 등의 브라우저에서는 순수 자바스크립트 객체로 구현하고 있다. 이러한 차이 때문에 자바스크립트 코드 내부에는 XMLHttpRequest 객체의 인스턴스를 생성하는 데 ActiveX를 이용하거나 자바스크립트 객체를 이용하는 로직이 반드시 들어 있어야 한다.
//Ex1:
var xmlHttp;
function createXMLHttpRequest() {
if(window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} else if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpReqeust();
}
보시다시피 XMLHttpRequest 객체를 만드는 일은 단순하다. 먼저 객체에 대한 참조값을 넣어둘 수 있는 xmlHttp라는 이름의 전역변수를 선언한다. createXMLHttpRequest 함수는 실제로 XMLHttpRequest의 인스턴스를 생성하는 일을 한다. 이 함수에는 객체를 만드는 방법을 결정하기 위한 간단한 분기 로직(branching logic)이 있다. window.ActiveXObject를 호출하면 객체를 반환하거나 null을 반환하게 되는데 이것이 if문에 의하여 true나 false값을 취하게 된다. 이는 브라우저가 ActiveX 컨트롤을 지원하는지 그러니까 결국 브라우저가 인터넷 익스플로러인지 여부를 결정하게 된다. 인터넷 익스플로러인 경우에는 생성하고자 하는 ActiveX 객체의 유형을 지정하는 문자열과 함께 ActiveXObject의 새로운 인스턴스를 생성함으로써 XMLHttpRequest 객체를 만들어내게 된다. 여기서는 XMLHttpRequest의 인스턴스를 만들고자 하는 것이므로 Microsoft.XMLHTTP를 생성자에 전달하였다.
window.ActiveXObject가 null이면 else문으로 가서 브라우저가 XMLHttpRequest를 자바스크립트 객체로 구현하였는지 확인한다. 이 때 window.XMLHttpRequest가 존재하면 XMLHttpRequest의 인스턴스가 생성된다.
동적으로 타입이 결정되는 자바스크립트의 특성과 여러 종류의 브라우저에서 XMLHttpRequest에 대한 구현이 호환성을 지님에 따라 인스턴스를 생성할 때 사용했던 메소드에 상관없이 XMLHttpRequest 인스턴스의 프로퍼티와 메소드를 동일하게 사용할 수 있다. 이런 점 때문에 개발과정이 상당 부분 간단해지고 자바스크립트가 특정 브라우저에 종속적이지 않게 되었다.
2.메소드와 프로퍼티
[List1: XMLHttpRequest의 표준 함수]
abort()
현재의 요청.
getAllResponseHeaders()
HTTP 요청에 대한 모든 응답 헤더를 키/값으로 된 한 쌍의 데이터값으로 반환.
getResponseHeader("header")
명시된 헤더의 문자열값을 반환.
open("method", "url")
서버에 대한 호출의 단계를 설정. method 아규먼트는 GET이나 POST 혹은 PUT 중의 하나이고 url 아규먼트는 상대적 혹은 절대적 경로가 된다. 이 메소드는 세 가지의 선택 아규먼트가 있다.
send(content)
요청을 서버로 보낸다.
setRequestHeader("header", "value")
명시된 값으로 헤더를 설정. 헤더에 값을 설정하기 전에는 반드시 open() 메소드를 호출해야 함.
ⅰ.void open(string method, string url, boolean asynch, string username, string password):
이 메소드는 서버로 전달될 사용자 호출을 초기화하는 역할을 한다. 이것은 스크립트에서 유일하게 요청을 초기화하는 함수이다. 두 개의 필수 아규먼트와 세 개의 선택 아규먼트를 필요로 하는데 필수 항목 두 가지는 실행시키고자 하는 메소드의 종류와(GET, POST, PUT 중의 하나) 호출하고자 하는 자원의 URL이다. 선택 항목 첫 번째는 호출이 비동기인지 여부를 지정하는 불린값(boolean, true가 기본적으로 설정되는 값으로 이는 요청이 비동기적이란 의미이다)이다. 만약 false라면 서버로부터 응답이 올 때까지 모든 처리를 미루게 된다. Ajax를 사용하는 가장 큰 이득 중 하나가 요청을 비동기로 할 수 있다는 것이므로 이 파라미터를 false로 설정한다는 것은 XMLHttpRequest 객체를 사용하는 목적을 다소 무색하게 만드는 것이다. 이러한 사실을 감안하면, 페이지를 진행하기 전에 사용자의 입력값을 검증하는 것과 같은 특정한 경우에는 이렇게(동기적으로) 사용하는 것이 유용할 수도 있겠다. 마지막 두 가지 파라미터는 이름에서도 알 수 있듯이 특정한 사용자명과 비밀번호를 설정할 수 있도록 해주는 것이다.
ⅱ.void send(content):
실질적으로 서버에 요청을 하는 함수이다. 요청을 비동기로 선언하였다면 이 함수는 즉시 반환되고, 그렇지 않고 동기로 선언하였다면 응답을 얻을 때까지 기다린다. DOM 객체의 인스턴스나 입력 스트림 혹은 문자열을 선택 아규먼트로 선언할 수 있다. 이 메소드에 전달된 내용은 요청 본문의 일부로 전달된다.
ⅲ.void setRequestHeader(string header, string value):
HTTP요청에 있는 주어진 헤더의 값을 설정하는 메소드이다. 헤더를 나타내는 문자열과 헤더에 설정될 값을 나타내는 문자열 두 가지를 아규먼트로 취한다. 여기서 알아두어야 할 사실은 이 메소드 전에 반드시 open() 메소드를 호출해야 한다는 것이다. 메소드들 중에서 가장 많이 사용하는 것이 바로 이 open()과 send()이다. XMLHttpRequest객체는 그 자체로 Ajax 인터페이스를 설계하는 데 유용하게 사용될 수 있는 수많은 프로퍼티를 소유하고 있다.
ⅳ.void abort():
그 이름에서 알 수 있듯이 요청을 중단하는 함수이다.
ⅴ.string getAllResponseHeaders():
웹 어플리케이션 개발자라면 이 메소드가 제공하는 중심기능에 대해서는 이미 익숙하게 알고 있을 것이다. 이 메소드는 HTTP요청으로부터 응답 헤더를 포함하는 문자열을 반환한다. 헤더에는 Content-Length, Date, URI 등이 들어 있다.
ⅵ.string getResponseHeader(string header):
이것은 특정 헤더값을 나타내는 아규먼트를 가진다는 것만 제외하면 getAllResponseHeaders()와 거의 유사하다. 이 값을 문자열로 반환한다.
[List2: XMLHttpRequest의 표준 프로퍼티]
onreadystatechange
상태에 변경이 있을 때마다 시작되는 이벤트 핸들러로 보통은 자바스크립트 함수를 호출한다.
readystate
요청의 상태를 나타내며 5가지의 값을 가진다. 0=초기화 안 됨, 1=로드중, 2=로드됨, 3=처리중, 4=완료됨.
responseText
문자열로 된 서버의 응답.
responseXML
XML 형식으로 된 서버의 응답. 이 객체는 파싱이 가능하며 DOM 객체로 처리된다.
status
서버로부터 받는 HTTP 상태 코드. 200(정상), 404(서버를 찾지 못한 경우) 등.
statusText
HTTP 상태 코드의 텍스트 버전.
3.통신 예
ⅰ.클라이언트측의 이벤트가 Ajax 이벤트를 촉발시킨다. 단순한 onchange 이벤트에서부터 몇 가지 특정한 사용자 액션까지 어떠한 것도 Ajax 이벤트를 발생시킬 수 있다.
...
<input type="text" id="email" name="email" onblur="validateEmail();">
...
ⅱ.XMLHttpRequest 객체의 인스턴스가 생성된다. open() 메소드를 통해 호출이 성립되는데, URL은 특정 HTTP메소드(보통 GET이나 POST)와 함께 설정된다. send() 메소드를 호출함으로써 비로소 요청이 발생한다. 아래에 이와 관련된 코드 예제가 나와 있다.
...
var xmlHttp;
function validateEmail() {
var email = document.getElementById("email");
var url = "validate?email=" + escape(email.value);
if(window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} else if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
xmlHttp.open("GET", url);
xmlHttp.onreadystatechange = callback;
xmlHttp.send(null);
}
...
ⅲ.요청이 서버로 전달된다. 서블릿이나 CGI 스크립트 등 서버측 프로그램을 호출할 것이다.
ⅳ.요청을 받은 서버는 데이터 저장소나 타 시스템에 접근하는 것을 포함하여 원하는 일을 하게 된다.
ⅴ.요청이 브라우저로 되돌아온다. Content-Type이 text/xml 형식으로 지정되었기 때문에 XMLHttpRequest 객체는 text/html 유형의 결과만을 처리할 수 있다. 자바스크립트나 DOM을 처리하는 로직 혹은 다른 관련 기술들이 응답에 포함되는 복잡한 경우도 있다. 브라우저가 결과값을 캐쉬하는 일이 없도록 헤더를 설정해야 한다는 사실을 유념하도록 한다.
...
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
...
※Pragma와 Cache-Control은 같은 일을 한다. Pragma는 이전 버전과의 호환(backward compatibility)을 위해 정의된 것이다.
ⅵ.예제에서는 응답이 반환되면 callback() 함수를 부르게끔 XMLHttpRequest를 구성하였다. 이 함수는 XMLHttpRequest 객체의 readyState 프로퍼티를 검사하여 서버로부터 반환된 상태 코드를 찾는다. 예정대로 모든 값이 들어오게 되면 callback() 함수가 일을 하게 된다. 일반적인 콜백 함수의 코드는 다음과 같다.
...
function callback() {
if(xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
//do something interesting here
}
}
}
...
보시다시피 이것은 보통의 요청/응답의 범례와는 상이하지만 그렇다고 웹 개발자들에게 생소한 방식은 아니다. XMLHttpRequest 객체를 생성하고 값을 설정할 때 그리고 '콜백(callback)'중에 상태와 조건을 확인하는 작업을 할 때, 이 때에는 확실히 뭔가 좀 더 해주어야 할 일이 있는 법이다. 일반적으로 이들 표준 호출은 전체 어플리케이션이나 웹에서 재사용할 수 있도록 라이브러리 형태로 만들어놓게 된다. 이 분야는 새롭지만 오픈 소스 진영에서는 이에 대한 상당히 많은 움직임들이 있다.
보통 웹에서 사용할 수 있는 여러 가지 프레임워크나 툴킷들은 기본적인 통신과 브라우저에 대한 추상화 그리고 약간 추가된 사용자 인터페이스 등을 제공한다. 이들 중 일부는 순수 클라이언트 기반이고 일부는 서버상에서 작업을 한다. 이제 막 개발에 돌입했거나 배포된 지 얼마 안 된 것들이 대다수이다. 이 새로운 라이브러리들과 규칙적으로 배포되는 다양한 제품들로 인하여 이미 환경은 점점 변화하고 있다. 시장이 성숙할수록 어느 것이 가장 우수한 솔루션인지 드러날 것이다.
4.GET vs. POST
GET과 POST에는 어떤 차이점이 있는지, 그리고 이들 중 언제 GET을 쓰고 언제 POST를 써야 하는지 궁금할 것이다. 이론적으로는 여러 개의 요청이 동일한 결과를 반환하는 경우에 GET을 쓴다. 그러나 요청에 의해 서버의 상태가 바뀔 경우는 상황이 달라진다. 즉 현실적으로는 전달하는 데이터의 크기가 다를 때, 브라우저와 서버는 데이터를 서버로 보낼 때 쓰는 URL의 길이에 제한을 두고 있다. 그래서 이런 길이 제한에 제약을 받는 GET을 사용하는 것은 무리가 있다. 그러나 통산 서버로부터 데이터를 읽어올 때는 GET을 사용한다. 이 때(GET을 호출할 때는) 서버에서의 상태를 변화시키지 않도록 한다.
서버에서의 상태를 변경하고자 할 때는 항상 POST 메소드를 쓴다. GET과 달리 XMLHttpRequest 객체의 Content-Type 헤더를 설정해야만 하는데, 코드는 아래와 같다.
...
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
...
POST는 GET처럼 서버로 보내는 데이터의 크기를 제한하지도 않으며 다중 요청에 대하여 동일한 결과값을 반환하는 성질을 보장하지도 않는다.
5.원격 스크립팅
원격 스크립팅은 기본적으로 원격 프로시저 호출의 한 유형이다. 마치 일반적인 웹 어플리케이션을 다루는 것과 똑같이 서버와 소통하지만 전체 페이지를 갱신하지는 않는다. Ajax의 경우와 마찬가지로 요청을 접수하고 처리하여 결과값을 반환하는데 서버측에서는 어떠한 기술을 적용해도 무방하다. 서버측에서만 그런 것이 아니라 원격 스크립팅을 구현하는 데 있어서는 클라이언트측에서도 사용할 수 있는 다수의 기술들이 존재한다. 플래시 애니메이션이나 자바 애플릿 혹은 ActiveX 컴포넌트 등을 어플리케이션에 끼워 넣을 수도 있다. 더 나아가 XML-RPC도 사용할 수 있지만 이들 기술에 대한 경험이 없는 경우에는 기술의 복잡성으로 인해 생각만큼 자주 사용되지는 않는다. 자주 사용하는 원격 스크립팅의 예는 IFRAME과(숨겨진 것이든 아니든) 스크립트를 결합하여 서버가 자바스크립트를 반환하도록 하는 것으로, 반환된 자바스크립트는 브라우저에서 실행된다.
6.간단한 요청을 보내는 방법
XMLHttpRequest 객체를 통해 요청을 보내는 기본 순서는 아래와 같다.
ⅰ.XMLHttpRequest 객체의 인스턴스에 대한 참조값을 얻는다. 방법은 새로운 인스턴스를 생성하거나 이미 XMLHttpRequest 인스턴스를 포함하고 있는 변수에 접근하는 것이다.
ⅱ.XMLHttpRequest 객체의 상태 변화를 처리하게 될 함수를 알려준다. 객체의 onreadystatechange 프로퍼티를 자바스크립트 함수에 대한 포인터로 설정하면 된다.
ⅲ.요청의 프로퍼티를 설정한다. XMLHttpRequest 객체의 open() 메소드를 이용하여 처리하게 될 요청을 지정한다. open() 메소드에는 세 개의 파라미터가 필요하데 메소드를 지정하는(보통 GET이나 POST) 문자열, 목적지 URL을 나타내는 문자열, 요청이 비동기로 이루어지는 여부를 가리는 불린값(boolean) 등이다.
ⅳ.요청을 서버로 보낸다. XMLHttpRequest 객체의 send() 메소드를 통해 요청을 지정된 목적지로 전달하게 된다. send() 메소드는 하나의 파라미터를 가지는데 보통 문자열 아니면 DOM 객체이다. 이 파라미터는 요청 본문의 일부로 목적지 URL까지 보내진다. send() 메소드에 파라미터를 넣을 때는 반드시 open() 함수에 할당된 메소드가 POST이어야 한다. 요청 본문에 넣어 보낼 데이터가 없을 때는 null을 쓴다.
이러한 과정은 상당히 직관적이다. 일단 XMLHttpRequest 객체가 있어야 하고, 객체의 상태에 변화가 생겼을 때 어떻게 해야 하는지 알려준다. 그리고 요청을 어디로 어떻게 보내야 하는지 알려주고 마지막으로 XMLHttpRequest 객체에게 요청을 전달하라고 지시한다. 그렇다 하더라도 C나 C++ 경험이 없다면 함수 포인터(function pointer)라는 용어가 낯설게 들릴 것이다.
함수 포인터란 문자열이나 숫자 혹은 객체의 인스턴스처럼 데이터를 가리키는 것이 아니라 함수를 가리킨다는 사실만 제외하면 여느 변수와 똑같다. 자바스크립트에서는 모든 함수가 메모리에 등록되어 있고 함수명으로 참조될 수 있다. 이것은 다른 함수에 함수 포인터를 파라미터로 넘기거나 객체의 프로퍼티로 저장하는 등의 유연성을 제공할 수 있음을 의미한다.
XMLHttpRequest 객체의 경우에는 onreadystatechange 프로퍼티가 콜백 함수에 대한 포인터를 가지고 있다. 콜백 함수는 XMLHttpRequest 객체의 내부 상태에 변경이 발생했을 때 호출된다. 호출이 비동기적일 때는 요청이 전달되고 스크립트는 곧장 처리를 계속한다. 즉, 요청이 완료될 때까지 스크립트가 진행을 기다릴 필요가 없다. 일단 요청이 나가면 객체의 readyState 프로퍼티는 여러 번의 변경을 겪게 되는데, 어떠한 상태값에 대해서든 처리를 하겠지만 보통은 서버가 응답을 보냈음을 알리는 상태에 가장 많은 신경을 쓴다. 콜백 함수를 설정해 놓음으로써 XMLHttpRequest 객체로 하여금 서버의 응답이 도착할 때마다 이를 처리할 함수를 호출하는 일을 효과적으로 할 수 있다.
<!-- Ex2: simpleRequest.html -->
<!DOCUMENT html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns= "http://www.w3.org/1999/xhtml">
<head>
<title>Simple XMLHttpRequest</title>
<script type="text/javascript">
var xmlHttp;
function createXMLHttpRequest() {
if(window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
} else if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
}
function startRequest() {
createXMLHttpRequest();
xmlHttp.readystatechange = handleStateChange;
xmlHttp.open("GET", "simpleResponse.xml", true);
xmlHttp.send(null);
}
function handleStateChange() {
if(xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
alert("The server replied with: " + xmlHttp.responseText);
}
}
}
</script>
</head>
<body>
<form action="#">
<input type="button" value="Start Basic Asynchronous Request" onclick="startRequest();" />
</form>
</body>
</html>
요청이 비동기로 전달되었기 때문에 브라우저는 백그라운드로 서버의 응답을 기다리는 와중에도 사용자의 입력에 대해 응답할 수 있다. 만약 요청을 동기로 보냈는데 서버의 응답이 도달하는데 수 초가 걸린다면 브라우저는 그 기다리는 시간 동안 사용자의 입력에 대하여 응답할 수 없는 상태에 있게 된다. 비동기인 경우에는 일단 겉으로 브라우저가 입력에 대하여 반응 없이 서 있는 모습을 찾아볼 수 없기 때문에 사용자의 만족을 눈에 띄게 향상시킨다. 이로써 사용자는 서버가 먼저 들어온 요청을 뒤에서 처리하는 동안 계속해서 작업할 수 있다.
사용자의 작업에 의한 단절 없이 지속적으로 서버와 통신할 수 있게 하는 능력은 어플리케이션에 대한 사용자 경험을 향상시키는 수많은 기법을 낳게 하였다. 한 예로 사용자 입력을 검증하는 프로그램을 들 수 있겠다. 사용자가 입력 폼을 채우는 동안 브라우저는 사용자가 다른 필드를 입력하더라도 단절 없이 입력된 값을 정기적으로 서버에 전달하여 검증하게 한다. 만약 검증규칙에 어긋나게 되면 폼을 처리하기 위해 실제로 서버로 보내기 전에 사용자에게 즉시 이를 알려준다. 잘못된 폼을 전송했다가 또다시 폼의 내용을 구축할 필요가 없어지므로 사용자의 시간도 절약되고 서버의 부하도 줄게 된다(비록 사용자의 입력 내용을 임시로 저장하여 전송이 실패한 경우 다시 보여주는 여러 방법이 있긴 하지만).
7.보안에 관한 이야기
브라우저에 기반한 어떠한 기술도 보안(security)을 빼놓고는 완전하다 할 수 없다. XMLHttpRequest 객체는 브라우저의 '샌드박스(sandbox)' 모델을 따르고 있다. XMLHttpRequest 객체가 요청한 모든 자원은 이를 호출한 스크립트가 발생한 곳과 동일한 도메인의 내부에 위치해야 한다. XMLHttpRequest 객체는 스크립트가 본래 제공된 도메인의 외부에 있는 요청 자원으로부터 격리되어 있어야 한다는 것이 보안의 제약사항이다.
브라우저에 따라 URL 외부에 있는 자원을 요청할 수 있도록 약간의 자바스크립트 트릭을 제공하긴 한다. 그렇다 하더라도 이러한 방법은 워낙 브라우저에 따라 다르기 때문에 사용하지 않는 것이 최선이다. XMLHttpRequest를 사용할 때는 URL을 벗어난 곳에 대한 접근은 피하도록 하는 것이 상책이다.
8.DOM
계속해서 DOM에 대하여 좀더 이야기해 보자. 만약 클라이언트측에 대한 경험이 부족하다면 DOM이 무엇인지 모를 수도 있다. DOM은 플랫폼과 언어에 독립적인 방식으로 문서의 구조와 내용에 접근하고 이를 수정하기 위해 고안한 W3C의 스펙이다. 다시 말해 이것은 HTML과 XML 문서를 표현하고 조작하는 표준적인 방식이다.
DOM의 설계가 OMG(Object Management Group)의 스펙을 기초로 하였기 때문에 어떤 언어와 함께 사용해도 된다는 사실이 중요하다. 원래는 자바스크립트를 여러 브라우저에서 사용할 수 있도록 하기 위한 것으로 받아들여졌으나 그것을 넘어서 지속적으로 그 사용범위를 확대해 왔다.
DOM은 객체 지향적인 관점에서 볼 때 진정한 객체 모델이다. DOM은 문서를 표현하고 수정하기 위해 필요한 객체를 정의하고 이들 객체의 행동과 특성 그리고 이들 객체간의 관계를 정의한다. DOM을 페이지상의 데이터와 구조를 표현하는 하나의 트리로 생각할 수 있지만 실제로 그렇게 구현되지 않을 수도 있다.
[출처] [본문스크랩] XMLHttpRequest 객체|작성자 화니
댓글