2011. 9. 26. 19:00

jQuery - Ajax - crossdomain 이슈 #2

이전에 이야기 했던 JSONP 방법과는 다르게 좀더 정석적인 방법으로 jQuery를 다뤄 Crossdomain을 해결한 것은 검색이라는 삽질과 수많은 테스트 코드를 낳고서야 해결점이 보이기 시작했다.(물론 결국 찾아낸건 회사 차장님의 덕택이었지만)

일단 몇가지 문서들을 봐야만 했는데  jQuery.ajaxPrefilter() 부분이었다. 이 ajaxPrefilter() 메서드는 ajax의 low-level 메서드로 jQuery를 통해 ajax통신을 하게 될때 콜백함수로 호출되어 통신을 위한 밑작업들을 수행하게 되는데 cross-domain또한 이 메서드 중간에서 차단하여 막는것도 여기서 처리하게된다. 이 사실을 어떻게 알았냐면 Extending Ajax: Prefilters, Converters, and Transports 라는 문서를 보고 나서 알게 되었다.

이 문서에 따르면 이 기능(?)들은 jQuery 1.5 .$ 버젼부터 지원하기 시작한 것으로 ajax 요청의 "보내기", "받기", 그리고 "관리하기"에 관련된 내용을 담당한다고 설명되어있다.


일단 여러가지로 우리가 봐야할 것은 보낼 때 cross-domain을 막는 부분을 해결해야 하므로 보내는 쪽 담당인 Prefilters 부분을 살펴보도록 하자.
Prefilters는 ajax의 옵션처리, 호출등을 담당하는데 실제 소스 코드를 확인해보면 다음과 같다.
 

$.ajaxPrefilter( function( options, originalOptions, jqXHR )
{
  // Modify options, control originalOptions, store jqXHR, etc
});

 
각 파라미터의 설명들이 있는데 내용은 다음과 같다.
  • options : 요청을 보내는 옵션들  
  • originalOptions : ajaxSettings에서 기본적으로 수정되어지지 않는 ajax 메서드에서 제공되는 옵션들. 
  • jqXHR : jQuery HTTP Request
이렇게 되며 이 메서드를 Extending해주면 ajax통신을 manual 하게 셋팅할 수 있는데 그 내용중에서 아래의 내용을 확인해 볼 것.
Prefilters can also be used to modify existing options. For example, the following proxies cross-domain requests through http://mydomain.net/proxy/:
이 이야기는 무슨 이야기냐 하면 기존의 옵션을 수정할 수 있다면서 프록시서버를 통해 크로스도메인 요청을 보낼수 있다는 이야기를 하며 아래의 코드를 소개해 놓았다.
$.ajaxPrefilter( function( options )
{
  if ( options.crossDomain )
 {
    options.url = "http://mydomain.net/proxy/" + encodeURIComponent( options.url );
    options.crossDomain = false;
  }
});
그럼 우리가 유추해볼 수 있는건 다음과 같다.
  1. 통신을 하기전엔 무조건 $.ajaxPrefilter()를 거친다.
  2. ajaxPrefilter() 내부를 변조해 처리하면 cross-domain도 통과할 수 있다. 
라는 것인데 그래서 여태껏 "jQuery ajax crossdomain" 이라는 검색어로 검색하던 것을 "jQuery ajaxPrefilter crossdomain"으로 바꿔 검색해봤다. 그랬더니 서광처럼 등장한 "http://craveytrain.com/posts/cors" 페이지.
여기에 등장한 소스 코드는 

$.ajaxPrefilter('json', function(options, orig, jqXHR) {
    if (options.crossDomain && !$.support.cors) return 'jsonp'
});

이것인데 이 소스를 적용해 테스트 해봤더니 인터넷 익스플로러에선 되고 크롬에선 안되고 하는 크로스브라우징 문제가 발생했는데 이걸 어쩐다.. 하고 고민하다가 어차피 그냥 통신 자체를 'jsonp'로 속여서 내보내면 해결될 문제라고 생각해 아래와 같이 수정했다.
$.ajaxPrefilter('json', function(options, orig, jqXHR) {
    return 'jsonp'
});

이렇게 테스트 해보니 잘된다.
테스트 코드는 아래와 같이.

 
$(document).ready(function(){
	loadData();
});
	 
function loadData()
{
	var data ={};
	data.q = 'test';
	data.apikey = '947f96c9d2518613faae766eed75bca030ad67d7';
	data.result = '10';
	data.output = 'json';

	$.ajaxPrefilter('json', function(options, orig, jqXHR) {
		return 'jsonp';
	});
 
	$.ajax({
		url: "http://apis.daum.net/search/image"
		, crossDomain: true
		, dataType: "json"
		, type: 'GET'
		, data: data
		, success: function( data, textStatus, jqXHR )
		{
			alert("sccess : " + data.channel.item.length );
		}
		, error: function( jqXHR, textStatus, errorThrown )
		{
			alert( textStatus + ", " + errorThrown );
		}
	});
}

이렇게 ajax 통신하기 전에 ajaxPrefilter를 수정해주면 해결이 된다.
 


위의 테스트 결과는 크롬, 사파리, 인터넷 익스플로러, 오페라까지 테스트한 결과로 현재 테스트 해볼 수 있는 브라우저에서는 다 해본 결과다. 결국 jQuery를 extending해야 해결할 수 있는 이슈라니.. 어지간한 파워유저가 아니고서는 해결보기 힘든 이슈일듯 하다.

다음엔 저런 결과물로 jQuery Template를 이용해 화면에 뿌려주는 작업을 진행해 보자. 

'HTML/Javascript' 카테고리의 다른 글

속성 alt와 title의 차이  (2) 2012.02.20
jQuery Template  (0) 2011.09.27
jQuery - Ajax - crossdomain 이슈  (1) 2011.09.17
Jquery Conference개최  (0) 2011.08.04