이 글은 영문 Wikipedia의 글을 번역한 것입니다. 제가 공부하기 위한 목적으로 번역한 것이므로, 오류가 있을 수도 있습니다. 문제 있는 부분을 발견하시면 댓글로 남겨주시면 감사하겠습니다.
===
XMLHttpRequest(XHR)은 Javascript와 같은 웹브라우저 스크립트 언어에서 사용할 수 있는 API이다. XHR은 웹서버에 HTTP 혹은 HTTPs 요청을 전송하고 서버의 응답을 다시 스크립트로 불러오는데 사용된다. 모든 주류 웹브라우저의 개발버전에서는 http: 와 https: 이외의 URI 도 지원한다. 특히 blob:URL 이 지원된다.
XMLHttpRequest (XHR) is an API available to web browser scripting languages such as JavaScript. It is used to send HTTP or HTTPS requests to a web server and load the server response data back into the script. Development versions of all major browsers support URI schemes beyond http: and https:, in particular, blob: URLs are supported.
이 API는 호환성 확보를 위해 XMLHttpRequest라는 명칭으로 표준화되었다. 하지만 이 명칭은, XML 뿐만 아니라 임의의 텍스트도 전송받을 수 있다는 점에서 오해를 불러일으킬 소지가 있다. 데이터를 JSON, HTML 또는 일반 텍스트로 수신하는 경우도 많다. 응답받은 데이터를 이용하여 새로운 페이지를 불러들이지 않고 현재의 문서를 변경시킬 수 있다. 또한 응답 데이터를 클라이언트측 스크립트에서 평가할 수도 있다. 예를 들어, 웹서버에서 JSON 포맷으로 받았다면, 이를 클라이언트측에서 객체로 변환할 수 있다.
The name was standardized to XMLHttpRequest for compatibility. It may be misleading, in particular because any textual data may be received from the server, not just XML. Data are also commonly received as JSON, HTML, or as plain text. Data from the response can be used to alter the current document in the browser window without loading a new web page. The response data can also be evaluated by client-side scripting. For example, if it was formatted as JSON by the web server, it can be converted into a client-side data object for further use.
XMLHttpRequest 는 AJax 웹 개발 기법에서 중요한 역할을 담당하고 있으며, 많은 웹사이트에서 반응형 동적 웹을 구현하는데 사용되고 있다.
XMLHttpRequest has an important role in the Ajax web development technique. It is currently used by many websites to implement responsive and dynamic web applications.
XMLHttpRequest는 브라우저의 동일출처정책(same-origin policy)의 제한을 받는다. 즉, 보안을 이유로 원래의 웹페이지를 보낸 동일한 서버에 대한 요청만 가능하다.
XMLHttpRequest is subject to the browser's same-origin policy: for security reasons, requests will only succeed if they are made to the same server that served the original web page.
역사와 지원(History and Support)
XMLHttpRequest 객체의 개념은 원래 Outlook Web Access 개발자가 Microsoft Exchange Server 2000을 위하여 고안하였다. 이 개념을 사용하여 MSXML 라이브러리 버전 2에 IXMLHTTPRequest 라는 인터페이스가 개발 구현되었다. MSXML 라이브러리 버전 2는 1999년 3월 Internet Explorer 5.0 에 탑재되었는데, ActiveX를 통해, MSXML 라이브러리의 XMLHTTP wapper를 사용하여 IXMLHTTPRequest 인터페이스로 접근할 수 있었다.
The concept behind the XMLHttpRequest object was originally created by the developers of Outlook Web Access (by Microsoft) for Microsoft Exchange Server 2000.[6] An interface called IXMLHTTPRequest was developed and implemented into the second version of the MSXML library using this concept.[6][7] The second version of the MSXML library was shipped with Internet Explorer 5.0 in March 1999, allowing access, via ActiveX, to the IXMLHTTPRequest interface using the XMLHTTP wrapper of the MSXML library.
Mozilla 프로젝트에서는 Gecko 레이아웃 엔진에 nsIXMLHttpRequest라는 인터페이스를 개발 구현하였다. 이 인터페이스는 마이크로소프트의 IXMLHTTPRequest 인터페이스와 가능한 한 비슷하게 작동하도록 설계되었다. Mozilla는 자바스크립트 엔진을 통해 이 인터페이스를 사용할 수 있는 wrqpper를 만들어 이를
XMLHttpRequest 라고 하였다. XMLHttpRequest 객체는 2000년 12월 6일 출시된 Gecko 버전 0.6 부터 접근할 수 있었으나, 2002년 6월 5일 출시된 Gecko 1.0 버전이 나오면서부터 완전하게 작동되었다. XMLHttpRequest 객체는 기타 주요 웹 클라이언트에서 사실상의 표준이 되어, 2004년 2월 출시된 Safari 1.2, Konqueror, 2005년 4월 출시된 Opera 8.0, 2005sus 9월 출시된 iCab 3.0b352 등에서 구현되었다.
The Mozilla project developed and implemented an interface called nsIXMLHttpRequest into the Gecko layout engine. This interface was modeled to work as closely to Microsoft's IXMLHTTPRequest interface as possible. Mozilla created a wrapper to use this interface through a JavaScript object which they called XMLHttpRequest. The XMLHttpRequest object was accessible as early as Gecko version 0.6 released on December 6 of 2000, but it was not completely functional until as late as version 1.0 of Gecko released on June 5, 2002. The XMLHttpRequest object became a de facto standard in other major web clients, implemented in Safari 1.2 released in February 2004, Konqueror, Opera 8.0 released in April 2005, and iCab 3.0b352 released in September 2005.
W3C 컨소시움에서는 2006년 4월 5일, Opera Sottware의 Anne van Kesteren 과 W3C의 Dean Jackson이 편집한 XMLHttpRequest 객체 사양 초안(working draft)을 발행했다. 이 문서의 목적은 "기존의 구현을 기초로 상호 운영할 수 있는 최소한의 기능을 문서화함으로써, 웹 개발자들이 플랫폼에 독립적으로 사용할 수 있도록 하기 위한 것"이었다. XMLHttpRequest 객체 사양이 최후로 개정된 것은 2009년 11월 19일이었으며, 현재 마지막 초안(last call working draft)인 상태이다.
The World Wide Web Consortium published a Working Draft specification for the XMLHttpRequest object on April 5, 2006, edited by Anne van Kesteren of Opera Software and Dean Jackson of W3C.[17] Its goal is "to document a minimum set of interoperable features based on existing implementations, allowing Web developers to use these features without platform-specific code." The last revision to the XMLHttpRequest object specification was on November 19 of 2009, being a last call working draft.
마이크로소프트에서는 2006년 10월 발매된 Internet Explorer 7.0 용 스크립트언어에 XMLHttpRequest 객체 구별자를 추가하였다.
Microsoft added the XMLHttpRequest object identifier to its scripting languages in Internet Explorer 7.0 released in October 2006.
jQuery나 Prototype Javascript Framework와 같은 브라우저 독립적 자바스크립트 라이브러리가 출현하면서 개발자들은 API를 직접 코딩하지 않고도 XMLHttpRequest 기능을 호출할 수 있게 되었다. Prototype은 Ajax.Request라는 비동기 호출객체(requester object)를 제공한다. 이 객체는 브라우저의 구현을 포장하여 접근할 수 있도록 해준다. jQuery 객체는 현재의 클라이언트측 DOM으로부터 요소를 표현하거나 포장한다. 이들은 모두 .load() 메소드를 가지고 있어, URI 파라미터를 받아 해당 URI에 XMLHttpRequest 를 전송하고, 기본적으로 반환되는 HTML을 jQuery 객체로 표현되는 HTML 요소에 저장한다.
With the advent of cross-browser JavaScript libraries such as jQuery and the Prototype JavaScript Framework, developers can invoke XMLHttpRequest functionality without coding directly to the API. Prototype provides an asynchronous requester object called Ajax.Request that wraps the browser's underlying implementation and provides access to it. jQuery objects represent or wrap elements from the current client-side DOM. They all have a .load() method that takes a URI parameter and makes an XMLHttpRequest to that URI, then by default places any returned HTML into the HTML element represented by the jQuery object.
W3C는 그 이후 2008년 2월 25일에 "XMLHttpRequest Level 2"라고 하는, XMLHttpRequest 객체를 위한 또다른 사양 초안을 발표하였다. Level 2에는 progress 이벤트, 교차출처 요청의 지원, byte stream의 처리 등을 포함한 여러가지 기능이 추가되었다. XMLHttpRequest Level 2 의 최신버전은 2011년 8월 16일 발행되었으며 아직도 초안(working draft)인 상태이다.
The W3C has since published another Working Draft specification for the XMLHttpRequest object, "XMLHttpRequest Level 2", on February 25 of 2008.[23] Level 2 consists of extended functionality to the XMLHttpRequest object, including, but not currently limited to, progress events, support for cross-site requests, and the handling of byte streams. The latest revision of the XMLHttpRequest Level 2 specification is that of 16 August 2011, which is still a working draft.
2011년 12월 5일부로 XMLHttpRequest 버전 2는 XMLHttpRequest 사양에 통합되어, 이제 버전 1과 버전2는 존재하지 않는다.
As of 5 December 2011, XMLHttpRequest version 2 has been merged into the main XMLHttpRequest specification, and there is no longer a version 1 and a version 2.
HTTP 요청(HTTP Request)
아래 절은 XMLHttpRequest 객체를 사용한 요청이 W3C 초안에 따르는 브라우저 내에서 어떻게 기능하는지를 보여주는 예이다. XMLHttpRequest 객체에 대한 W3C 표준은 아직도 초안이므로, 웹브라우저가 W3C 에서 정의한 기능을 모두 준수하지 않을 수 있고, 아래의 내용은 언제든지 변경될 수 있다. 여러 웹브라우저에 대해 XMLHttpRuest 객체를 사용할 경우에는 각별히 주의를 기울여야 한다. 이 글은 주요 브라우저간의 불일치에 대해서도 가능한한 기술하고자 한다.
The following sections demonstrate how a request using the XMLHttpRequest object functions within a conforming user agent based on the W3C Working Draft. As the W3C standard for the XMLHttpRequest object is still a draft, user agents may not abide by all the functionings of the W3C definition and any of the following is subject to change. Extreme care should be taken into consideration when scripting with the XMLHttpRequest object across multiple user agents. This article will try to list the inconsistencies between the major user agents.
open 메소드
XMLHttpRequest 객체의 HTTP 및 HTTPS 요청은 반드시 open 메소드를 이용해 초기화해야 한다. 요청 메소드, URL, 요청에 사용되는 URI 사용자 정보등을 인증하고 해결하기 위해서 실제로 요청을 보내기 전에 반드시 이 메소드를 호출해야 한다. 이 메소드가 URL의 존재나 사용자 정보의 정확성을 보증하는 것은 아니다. 이 메소드는 최대 5개까지의 매개변수를 받을 수 있으나, 요청을 초기화하기 위해서는 2개의 매개변수만 필수이다.
The HTTP and HTTPS requests of the XMLHttpRequest object must be initialized through the open method. This method must be invoked prior to the actual sending of a request to validate and resolve the request method, URL, and URI user information to be used for the request. This method does not assure that the URL exists or the user information is correct. This method can accept up to five parameters, but requires only two, to initialize a request.
open( Method, URL, Asynchronous, UserName, Password )
처음 매개변수는 사용할 HTTP 요청을 나타내는 문자열이다. W3C 의 XMLHttpRequest 객체에 대한 표준 표준을 준수하는 웹 브라우저가 반드시 지원해야 하는 요청 방법은 현재 다음과 같다.
The first parameter of the method is a text string indicating the HTTP request method to use. The request methods that must be supported by a conforming user agent, defined by the W3C draft for the XMLHttpRequest object, are currently listed as the following.
- GET (Supported by Internet Explorer 7 (and later), Mozilla 1+)
- POST (Supported by Internet Explorer 7 (and later), Mozilla 1 (and later))
- HEAD (Supported by Internet Explorer 7 (and later))
- PUT
- DELETE
- OPTIONS (Supported by Internet Explorer 7 (and later))
그러나, 이 이외의 요청도 가능하다. W3C 초안에는 브라우저가 자신의 재량에 따라 추가 요청방법을 지원해도 좋다고 기술되어 있다.
However, request methods are not limited to the ones listed above. The W3C draft states that a browser may support additional request methods at their own discretion.
두번째 매개변수도 문자열로, HTTP 요청을 보낼 URL이다. W3C에서는 현재의 문서에서 포트번호가 다르거나 ihost URI 부분이 다를 경우 URL 에러를 발생시키고 URL 요청을 허용하지 말것을 권고하고 있다.
The second parameter of the method is another text string, this one indicating the URL of the HTTP request. The W3C recommends that browsers should raise an error and not allow the request of a URL with either a different port or ihost URI component from the current document.
세번째 매개변수는 동기/비동기인지를 나타내는 불리언 값으로, W3C 초안에서는 필수 매개변수가 아니다. 이 매개변수가 전달되지 않을 경우, 기본값은 true 이다. 비동기 요청("true")은 서버의 응답을 기다리지 않고 현재 스크립트의 실행을 계속한다. 그대신 요청에 따른 여러가지 단계별로 XMLHttpRequest 객체에 등록한 onreadystatechange 이벤트 리스너를 호출된다. 동기 요청("false")의 경우엔 요청이 완료될 때까지 현재의 스크립트의 수행이 정지된다. 따라서 onreadystatechange 이벤트리스너는 호출되지 않는다.
The third parameter, a boolean value indicating whether or not the request will be asynchronous, is not a required parameter by the W3C draft. The default value of this parameter should be assumed to be true by a W3C conforming user agent if it is not provided. An asynchronous request ("true") will not wait on a server response before continuing on with the execution of the current script. It will instead invoke the onreadystatechange event listener of the XMLHttpRequest object throughout the various stages of the request. A synchronous request ("false") however will block execution of the current script until the request has been completed, thus not invoking the onreadystatechange event listener.
네번째 다섯번째 매개변수는 username 과 password 이다. 이들 매개변수(혹은 username만)는 서버에서 인증목적으로 요구할 때 제공될 수 있다.
The fourth and fifth parameters are the username and password, respectively. These parameters, or just the username, may be provided for authentication and authorization if required by the server for this request.
setRequestHeader 메소드
요청을 성공적으로 초기화한 후, 요청과 함께 전송할 HTTP 헤더를 보내기 위해 XMLHttpRequest 객체의 setRequestHeaderMethod를 호출할 수 있다.
Upon successful initialization of a request, the setRequestHeader method of the XMLHttpRequest object can be invoked to send HTTP headers with the request.
setRequestHeader( Name, Value )
이 메소드의 첫번째 매개변수는 헤더를 가리키는 문자열이다. 두번째 매개변수는 문자열의 값이다. 이 메소드는 요청시 전송해야 하는 헤더별로 각각 호출해야 한다. 여기에서 첨부된 헤더는 W3C 표준을 따르는 브라우저에서 open 메소드가 다시 호출되면 삭제된다.
The first parameter of this method is the text string name of the header. The second parameter is the text string value. This method must be invoked for each header that needs to be sent with the request. Any headers attached here will be removed the next time the open method is invoked in a W3C conforming user agent.
send 메소드
HTTP 요청을 전송하려면 XMLHttpRequest 의 send 메소드를 호출해야 한다. 이 메소드는 요청할 내용을 담고 있는 하나의 매개변수가 필요하다.
To send an HTTP request, the send method of the XMLHttpRequest must be invoked. This method accepts a single parameter containing the content to be sent with the request.
send( Data )
보낼 내용이 없을 경우 이 매개변수는 생략할 수 있다. W3C 초안에 따르면 이 매개변수는 문자열로 변환될 수 있는 한 스크립트 언어가 지원하는 어떠한 타입도 무방하다. 단, DOM 문서 요소는 예외이다. 브라우저에서 매개변수를 시리얼화(serialize, 문자열 변환) 할 수 없다면 매개변수가 무시된다. Firefox 3.0.x 이전 버전의 경우, 매개변수가 없으면 예외가 발생한다.
This parameter may be omitted if no content needs to be sent. The W3C draft states that this parameter may be any type available to the scripting language as long as it can be turned into a text string, with the exception of the DOM document object. If a user agent cannot serialise the parameter, then the parameter should be ignored. Firefox 3.0.x and previous versions will however throw an exception if send is called without an argument.
매개변수가 DOM 문서 객체일 경우, 문서객체의 inputEncoding 프로퍼티에서 지정한 인코딩 방식을 사용하여 브라우저가 문서를 XML로 변환할 수 있어야 한다. setRequestHeader를 사용하여 Content-Type 헤더를 추가하지 않았을 경우, 브라우저가 "application/xml;charset=charset,"를 추가시켜야 한다. 여기에서 charset은 해당문서를 인코딩할때 사용된 인코딩이다.
If the parameter is a DOM document object, a user agent should assure the document is turned into well-formed XML using the encoding indicated by the inputEncoding property of the document object. If the Content-Type request header was not added through setRequestHeader yet, it should automatically be added by a conforming user agent as "application/xml;charset=charset," where charset is the encoding used to encode the document.
브라우저가 프록시 서버를 사용할 경우, XMLHttpRequest 객체는 받은 요청을 원래의 서버 대신 프록시로 연결되도록 적절히 변경하고, 설정된 바에 따라 프록시-인증(Proxy-Authorization)헤더를 전송한다.
If the user agent is configured to use a proxy server, then the XMLHttpRequest object will modify the request appropriately so as to connect to the proxy instead of the origin server, and send Proxy-Authorization headers as configured.
onreadystatechange 이벤트 리스너
If the open method of the XMLHttpRequest object was invoked with the third parameter set to true for an asynchronous request, the onreadystatechange event listener will be automatically invoked for each of the following actions that change the readyState property of the XMLHttpRequest object.
XMLHttpRequest 객체의 open 메소드가 비동기로 호출되었을 경우 (세번째 매개변수가 true로 설정), XMLHttpRequest 객체의 readyState 프로퍼티를 변경시키는 다음과 같은 상황이 발생될 때마다 onreadystatechange 이벤트 리스너가 자동적으로 호출된다.
- open 메소드가 성공적으로 호출되면, XMLHttpRequest의 readyState 프로퍼티가 1로 지정되어야 한다.
- send 메소드가 전송되고 HTTP 응답 헤더가 수신되면, XMLHttpRequest의 readyState 프로퍼티가 2로 지정되어야 한다.
- HTTP 응답 내용이 전송되기 시작하면, XMLHttpRequest의 readyState 프로퍼티가 3로 지정되어야 한다.
- HTTP 응답 내용 전송이 완료되면, XMLHttpRequest의 readyState 프로퍼티가 4로 지정되어야 한다.
- After the open method has been invoked successfully, the readyState property of the XMLHttpRequest object should be assigned a value of 1.
- After the send method has been invoked and the HTTP response headers have been received, the readyState property of the XMLHttpRequest object should be assigned a value of 2.
- Once the HTTP response content begins to load, the readyState property of the XMLHttpRequest object should be assigned a value of 3.
- Once the HTTP response content has finished loading, the readyState property of the XMLHttpRequest object should be assigned a value of 4.
리스너는 리스너가 정의된 후 일어난 상태변화에만 반응한다. 상태 1, 2을 감지려면 open 메소드가 호출되기 전에 리스너를 정의해야 한다. open 메소드는 반드시 send 메소드가 호출되기 전에 호출되어야 한다.
The listener will only respond to state changes which occur after the listener is defined. To detect states 1 and 2, the listener must be defined before the open method is invoked. The open method must be invoked before the send method is invoked.
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4){
alert(xmlhttp.readyState);
}
};
xmlhttp.open('GET', 'somepage.xml', true);
// 서버에 ajax 목적으로 이 호출이 이루어짐을 알림.
// jQuery/Prototype/Dojo 등의 대부분의 라이브러리가 이를 수행함.
// Tells server that this call is made for ajax purposes.
// Most libraries like jQuery/Prototype/Dojo do this
xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xmlhttp.send(null); // No data need to send along with the request.
abort 메소드
이 메소드는 XMLHttpRequest 객체의 readyState 가 아직 4로 되지 않았다면 요청을 취소한다. abort 메소드는 콜백핸들러가 비동기 요청으로 호출되지 않았다는 것을 보증한다.??
This method aborts the request if the readyState of the XMLHttpRequest object has not yet become 4. The abort method ensures that the callback handler does not get invoked in an asynchronous request.
abort ()
일부 AJAX 라이브러리는 잘못된 요청이나 중복 요청을 취소하기 위해 abort 메소드를 사용한다.
Some AJAX libraries use the abort method to cancel potential duplicate or out-of-order requests.
HTTP 응답
XMLHttpRequest의 send 메소드가 성공적으로 호출이 완료된 후, 서버 응답이 적법한 XML이고, 서버에서 송신한 Content-type 헤더를 브라우저가 XML의 인터넷 미디어 타입으로 이해할 수 있을 경우, XMLHttpRequest 객체의 responseXML 프로퍼티는 DOM 문서 객체를 담고있게 된다. 또 다른 프로퍼티인 responseText에는 서버 응답을 (XML로 이해할 수 있든 아니든) 일반 문자열로 담고 있게 된다.
After a successful and completed call to the send method of the XMLHttpRequest, if the server response was valid XML and the Content-Type header sent by the server is understood by the user agent as an Internet media type for XML, the responseXML property of the XMLHttpRequest object will contain a DOM document object. Another property, responseText will contain the response of the server in plain text by a conforming user agent, regardless of whether or not it was understood as XML.
교차 도메인 요청(Cross-domain requests)
인터넷 초기에 자바스크립트를 사용하여, 어떤 웹사이트의 정보를 평판이 나쁜 사이트의 정보로 교체함으로써 사용자 보안을 무력화시키는 게 가능하다는 것이 발견되었다. 따라서 모든 최신 브라우저는 cross-site scripting과 같은 공격을 막을 수 있는 동일출처정책(same-origin policy)을 구현하고 있다. XMLHttpRequest 데이터도 이러한 보안 정책의 영향을 받지만, 의도적으로 이러한 제한을 우회하는 방법이 필요하다. 예를 들어 여러개의 서브도메인을 합법적으로 사용할 경우, foo.example.com 에서 생성한 페이지로부터 bar.example.com에 있는 정보를 XMLHttpRequest로 호출하려는 시도는 실패하게 된다.
In the early development of the World Wide Web, it was found possible to breach users' security by the use of JavaScript to exchange information from one web site with that from another less reputable one. All modern browsers therefore implement a same origin policy that prevents many such attacks, such as cross-site scripting. XMLHttpRequest data is subject to this security policy, but sometimes web developers want intentionally to circumvent its restrictions. This is sometimes due to the legitimate use of subdomains as, for example, making an XMLHttpRequest from a page created by foo.example.com for information from bar.example.com will normally fail.
이러한 보안 기능을 우회하기 위한 방법은 JSONP, 교차출처 자원공유(CORS: Cross-Origin Resource Sharing)를 사용하거나, Flash/Silverlight 등의 플러그인을 사용하는 등 여러가지가 있다. 교차출처 XMLHttpRequest는 W3C XMLHttpRequest Level2 사양에 정의되어 있으며, 모든 최신 브라우저(모바일 및 데이크탑)가 지원한다.
Various alternatives exist to circumvent this security feature, including using JSONP, Cross-Origin Resource Sharing (CORS) or alternatives with plugins such as Flash or Silverlight. Cross-origin XMLHttpRequest is specified in W3C's XMLHttpRequest Level 2 specification[32] and it is supported by all modern browsers (desktop and mobile).
Internet Explorer는 버전 10까지 CORS를 구현하지 않았다. 이전의 8 및 9 버전에서는 XDomainRequest API를 통해 비슷한 기능을 제공하였다. 이 API는 요청 헤더 설정거부, 쿠키의 생략을 비롯한 여러가지 제한이 있다. 아울러 GET 및 POST 요청만 지원되었다. 하지만 대부분의 서버측 프레임워크에서는 Content-type 요청헤더가 "application/x-www-urlencoded"가 필요함에도 XDomainRequest의 POST 메소드는 "text/plain" 만 허용하기 때문에 거의 활용하기 힘들었다.
Internet Explorer did not implement CORS until version 10. The two previous versions (8 and 9) offered similar functionality through the XDomainRequest API. This API has several restrictions, including but not limited to: denial of setting custom request headers and omission of cookies. Further, only the GET and POST request methods are supported. In practice, the POST method is barely useful, because the only allowed value for the Content-Type request header is "text/plain", while many server-side frameworks require "application/x-www-urlencoded" to function properly.
====