Ajax에서 서버와의 통신을 위한 핵심 요소인 XMLHttp는
IE7과 모질라 계열 브라우저에서는 native XMLHttpRequest를 사용.
그리고 IE6 이하 버전에서는 Microsoft.XMLHttp를 ActiveXObject로 object 생성.
[ IE에서 생성할 수 있는 XMLHttp object ]
- Microsoft.XMLHttp
- MSXML2.XMLHttp
- MSXML2.XMLHttp.3.0
- MSXML2.XMLHttp.4.0
- MSXML2.XMLHttp.5.0
[ Cross-Browser 를 위한 XMLHttp object 메소드 생성 예 ]
function CreateXMLHttp()
{
if (window.XMLHttpRequest)
{
return new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
var aVersions = [ "MSXML2.XMLHttp.5.0"
,"MSXML2.XMLHttp.4.0"
,"MSXML2.XMLHttp.3.0"
,"MSXML2.XMLHttp"
,"Microsoft.XMLHttp"
];
for (var i = 0; i < aVersions.length; i++)
{
try
{
var oXmlHttp = new ActiveXObject(aVersions[i]);
return oXmlHttp;
}
catch (oError)
{
}
}
}
}
[XMLHttp의 메소드 , 프로퍼티 및 이벤트]
1. 메소드
- abort( ) : 요청을 취소
- getAllResponseHeaders( ) : 모든 응답 헤더를 수신
- getResponseHeader(header) : 특정 응답 헤더 수신
- open(RequestType, url, async) : 통신 연결(nativ XMLHttpRequest는 Cross-domain을 제한함.)
- RequestType : Get or Post
- url : 서버 주소
- async : true(비동기 방식 통신), false(동기 방식)
- send(content) : 서버로 요청을 보냄. content는 null 을 포함함.
- setHeader(header, value) : 헤더의 키와 값의 쌍을 설정
2. 프로퍼티 / 이벤트 핸들러
- onreadystatechange : readyState가 변경 시 실행될 함수 등록
- readyState : 요청 및 처리 상태
- 0 (Uninitialized) : 아직 open() 메소드를 호출 하지 않은 상태
- 1 (Loading) : open() 메소드를 호출한 상태(아직 send는 하지 않은 시점)
- 2 (Loaded) : 요청을 서보로 보낸 상태( send() )
- 3 (Interactive) : 일부만 응답 받은 상태
- 4 (Complete): 모든 데이터를 받고 연결이 끊어진 상태
- responseText : 서버로 부터 받은 결과값의 스트링 반환
- responseXML : 서버로 부터 받은 결과값의 XML 형식
- status : 서버로 부터 응답 받은 상태 코드 (200 (OK) or 404 (Not Found) 등)
- statusText : status 코드에 대한 의미 명기
[ 서버 전송 예 ]
function sendRequest()
{
var content = getRequestBody();
var oXmlHttp = createXMLHttp();
oXmlHttp.open("post", "http://www.text.com/testForm.aspx", true);
oXmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//서버로 호출이 성공 하였을 경우 처리할 CallBack 함수 등록
oXmlHttp.onreadystatechange = function ()
{
if (oXmlHttp.readyState == 4)
{
if (oXmlHttp.status == 200)
{
saveResult(oXmlHttp.responseText);
}
else
{
saveResult("An error occurred: "+ oXmlHttp.statusText);
}
}
};
oXmlHttp.send(content);
}
----------------------- 에이작스 한글깨짐 -----------------------------
JavaScript --> PHP
encodeURIComponent( string ) --> iconv( "UTF-8", "CP949", rawurldecode($string ) )
PHP --> JavaScript
rawurlencode( iconv( "CP949", "UTF-8", $string ) ) --> decodeURIComponent( string )
Ajax는 기본적으로 UTF-8 만으로 통신을 한다고 보면된다. 그 이외의 Encoding을 지원하는 인코딩 함수가 없기 때문에 EUC-KR로 데이터를 전송하려는 꿈은 접어야만 한다.
헌데, 아직 우리나라는 EUC-KR 인코딩으로 된 웹 어플리케이션이 압도적으로 많은 상황이다(어서 빨리 UTF-8로 옮겨가길 바라마지 않는다).
거기다가 보통 JSP/Servlet 웹 어플리케이션은 Servlet 스펙 2.3이후부터 문자 인코딩 서블릿 필터를 사용해 모든 요청에 대해 일관된 문자 인코딩을 사용하는 것이 보편적인 방법으로 자리잡았다.
서블릿 필터는 일관성있게 모든 요청을 EUC-KR로 받아들이게 했는데, 몇몇 Ajax관련 요청만 UTF-8로 받아들여야만 하는 것이다.
필터를 적용할 URL-Pattern을 따로 줘보려 했으나, 너무 복잡해졌다.
그래서 HTTP 요청의 헤더를 이용해서 해결 했다.
아.. 한가지 더. 현재 한글 문제는 "XMLHttpRequest 요청 -> JSP/Servlet" 이 상황에서만 발생하는 것이다.
"JSP/Servlet -> XMLHttpRequest"의 상황(서버에서 클라이언트로 값을 리턴)에서는 이 문제가 발생하지 않는다.
서버가 리턴하는 문자열은 간단하게 다음처럼 하면 WAS가 자동으로 UTF-8로 값을 변경해서 전달하기 때문이다.
<%@ page contentType="text/plain; charset=utf-8" pageEncoding="EUC-KR"%>
contentType에서 text/plain은 텍스트나 JSON으로 값을 리턴할 때이다. XML로 리턴할 때는 text/xml.
아래는 Ajax 요청을 처리하기 위해서 만들어본 간단한 Encoding Filter 이다.
package ajax.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 어플리케이션 전체에 적용되는 필터이다.
*
* <ul>
* <li>encoding 파라미터 : encoding 파라미터를 설정하면 request 객체에
* setCharacterEncoding(encoding)을 실행한다.</li>
* <li>ajaxFlag 파라미터 : Ajax요청임을 나타내는 HTTP 파라미터 이름이다. ajaxFilter로 지정한 HTTP 파라미터의
* 값이 true 로 설정되면 인코딩을 무조건 UTF-8로 설정한다.</li>
* </ul>
*
* @author 손권남(kwon37xi@yahoo.co.kr)
*
*/
public class EncodingFilter implements Filter {
private Log log = LogFactory.getLog(this.getClass());
/** HTTP 요청 문자 인코딩 */
private String encoding = null;
/** Ajax 요청임을 나타내는 플래그 파라미터 이름 */
private String ajaxFlag = null;
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (ajaxFlag != null
&& "true".equals(((HttpServletRequest) request)
.getHeader(ajaxFlag))) {
// Ajax 처리 요청일 경우 무조건 UTF-8 지정.
request.setCharacterEncoding("UTF-8");
if (log.isDebugEnabled()) {
log.debug("요청 헤더에 " + ajaxFlag + "가 "
+ ((HttpServletRequest) request).getHeader(ajaxFlag)
+ "로 설정되어 있어 문자 인코딩에 UTF-8을 사용합니다.");
}
} else if (encoding != null) {
// Ajax 플래그가 true가 아니면, 기본적인 인코딩을 적용한다.
request.setCharacterEncoding(encoding);
if (log.isDebugEnabled()) {
log.debug("문자 인코딩에 " + encoding + "을 사용합니다.");
}
}
chain.doFilter(request, response);
}
public void init(FilterConfig config) throws ServletException {
encoding = config.getInitParameter("encoding");
ajaxFlag = config.getInitParameter("ajaxFlag");
if (log.isDebugEnabled()) {
log.info("encoding : " + encoding + ", ajaxFlag : " + ajaxFlag);
}
}
public void destroy() {
}
}
이 필터를 적용하고서, web.xml에 다음 내용을 추가하면 필터가 작동한다.
<filter>
<description>이중 인코딩 필터</description>
<filter-name>EncodingFilter</filter-name>
<filter-class>ajax.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>euc-kr</param-value>
</init-param>
<init-param>
<param-name>ajaxFlag</param-name>
<param-value>Ajax</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
여 기 내용을 보면, 기본적인 인코딩은 EUC-KR이고, 요청 헤더에 "Ajax" 헤더의 값이 "true"일 경우에는 강제로 UTF-8을 지정하라고 한 것이다. "ajaxFlag"의 값을 변경하면 헤더의 키을 "Ajax"가 아닌 다른 값으로도 지정할 수 있다. 하지만 아무튼 해당 헤더의 값을 "true"로 지정하면 Ajax로 인식하게 되는 것이다.
이를 위해서는 XMLHttpRequest에도 한가지 처리를 더 보태야 한다.