2011년 8월 5일 금요일

jQuery ajax에서 dataType을 json으로 설정...

원본 소스: http://www.ibm.com/developerworks/kr/library/wa-aj-jsonp1/

0jQuery.getJSON( url, [data,] [success(data, textStatus, jqXHR)] ) 는 아래의 코드와 동일하다.

$.ajax({
url: url,
dataType: 'json',
data: data,
success: callback
});

dataType을 'json'으로 설정하고 스프링 컨트롤러에서 객체를 JSON 스트링으로 변환하여 서블릿의 outputStream에 쓰면 그걸로 되는 줄 알았다.
근데 자꾸 success 콜백이 호출되는 것이 아니구 error 콜백이 호출되는 것이다.

이래저래 문서를 찾아 보니 JSONP(JSON with Padding)과 관련이 있다는 걸 우연히 알고 문서를 좀 찾아 봤다.

JSONP에 대해 따로 포스트를 작성할 계획이 있는 건 아니라서 간단히 살펴보기로 한다.
브라우저의 보안 정책 중에 same-origin policy라는 게 있다. XMLHttpRequest는 같은 도메인으로만 요청을 할 수 있다는 제약이다. 이걸 해결하기 위해서 아래의 3가지 방법을 사용한다.
1. Proxy - third-party server로 요청을 보내기 위해서 같은 도메인에 프록시 서버를 개발한다.
2. IFrame - 요청을 보이지 않는 iframe을 이용해서 호출한다. 실행은 그럭저럭 하더라도 값을 가져오는 것은 역시 보안에 위배된다.
3. 동적 스크립트 삽입 - 자바스크립트는 same-origin policy 정책이 적용되지 않는다.

JSONP는 동적 스크립트 삽입 기능을 이용한다.

jQuery.ajax에서 dataType을 'json'으로 설정하면 jquery는 callback이라는 파라미터를 Timestamp를 이용하여 중복되지 않은 함수명으로 만들어 request의 파라미터로 전달한다.

서버쪽에서는 아래의 두가지를 작업 해 주어야한다.
1. contentType을 text/javascript 로 설정한다.
2. request의 파라미터로 전달된 callback 함수를 호출한다. 함수의 파라미터로 json 객체를 전달한다. 아마도 하나만 전달할 수 있을 것 같다(이건 확인 해야 하는데... success의 콜백에서 첫번째 파라미터가 서버로부터 리턴되는 데이터 객체이니깐 아마도 그럴거라고 믿고 있다.)

서버 측 소스 코드는 아래와 같다.

response.setContentType("text/javascript");
String result = callback + "(" + sb.toString() + ")"; // sb에는 json을 표현하는 문자열
PrintWriter pw = response.getWriter();
pw.print(result);


클라이언트 소스는 아래와 같다.
success 콜백으로 전달되는 data는 자바스크립트 객체다.

$.ajax({
type: 'post',
url: "${ctx}/myController.sh?method=getAdminJson",
data: "adminId=" + f.adminId.value,
dataType : "json",
error:function(){alert("Error");},
success:function(data){
var ospData = data;
if( ospData.returnVal == "Y"){
alert("Success");
}
}
});

만약에 서버측에서 JSONP 형식으로 javascript callback 메서드를 호출하는 방식이 아니라
JSON 문자열을 서블릿 응답 바디에 쓰는 방식으로 호출한다면 클라이언트 소스를 아래와 같이 호출하면 된다.

dataType을 'text'로 변경하고 success 메서드의 파라미터로 전달되는 data는 단순 문자열이기 때문에
javascript 개체로 변경하기 위해서는 eval( '(' + jsonString + ')' ) 메서드로 변환해야 한다.

$.ajax({
type: 'post',
url: "${ctx}/myController.sh?method=getAdminJson",
data: "adminId=" + f.adminId.value,
dataType : "text",
error:function(){alert("Error");},
success:function(data){
var ospData = eval( '(' + data + ')' );
if( ospData.returnVal == "Y"){
alert("Success");
}
}
});

Have a nice day.

댓글 2개:

  1. 아 좋은정보 감사합니다.
    jquery 쓰면서 dataType 을 json 으로 설정했더니 뭔가 잘 안되더군요;
    검색해보니 이런 부분이 있었군요 덕분에 알게되었습니다.. 감사합니다.

    jquery 말고 그냥 ajax 쓸때는 responseText 를 eval 함수 사용해서 javascript 객체로 변환해서 썼었는데 jquery ajax 는 뭔가 더 편한게 있을 줄 알았는데;;
    서버단에 저렇게 처리를 해줘야 한다면 차라리 그냥 text 로 받고
    eval 함수 쓰는게 더 편하겠네요ㅠ 덕분에 알아갑니다 감사합니다

    답글삭제
  2. 이틀 동안 헤매다가 이 글 보고 해결했네요. 감사합니다^^

    답글삭제