dojo와 더불어서 jQuery는 요즈음 웹 상에서 널리 사용되고 인기도가 높은 자바스크립트 프레임워크들 중 하나입니다. 작은 Foot-print를 유지하면서 무엇하나 모자람이 없는 기능을 제공하고 있고, 또한 ASP.NET 개발자들 사이에서는 ASP.NET MVC에서 공식 채택하기 이전부터 널리 사용되어온 자바스크립트 프레임워크입니다.
jQuery는 AJAX 기능 뿐만 아니라 비동기적으로 자바스크립트를 로드하고, 직렬화된 JSON 컨텐츠를 복원하여 메모리 상에 되살려놓을 수 있는 기능까지 내장하고 있습니다. 하지만 딱 한 가지 아쉬운 점이 있었는데 그 점은 바로 WCF가 노출하는 Contract들 중에서 POST 방식으로 호출해야 할 때 사용이 불편하다는 점입니다.
REST (GET) 방식으로 호출하는 방법은 대개 유용합니다. URL을 이용하여 호출하는 것이므로 프로그래밍하기에는 훨씬 간단한 방법일 수 있습니다. 하지만 경우에 따라서 전달해야 하는 매개 변수의 수가 많거나 복잡한 자료 구조를 전달해야 하는 경우 적절하지 않을 수 있습니다.
이 Article에서는 jQuery를 이용하여 POST 방식의 WCF 서비스를 호출하는 방법을 다뤄보기로 하겠습니다. 이 Article에서 사용하는 Code의 원본은 http://www.west-wind.com/weblog/posts/324917.aspx 에서 가져온 것임을 밝혀둡니다.
public static void NoCaching(WebOperationContext context)
{
if (context == null)
return;
context.OutgoingResponse.Headers["Pragma"] = "no-cache";
context.OutgoingResponse.Headers["Cache-Control"] = "no-cache";
}
[OperationContract]
[WebInvoke(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public int CreateArticle(int boardID, string title, string contents)
{
NoCaching(WebOperationContext.Current);
if (!Security.IsLoggedOn)
return (-1);
int? newArticleID = null;
this.dataContext.CreateArticle(
(int?)boardID,
title,
(int?)Security.CurrentUserID,
contents,
ref newArticleID);
return newArticleID.HasValue ? newArticleID.Value : (-1);
}
위의 코드는 Internet Explorer가 내장하는 XMLHttpRequest의 캐싱 기능을 사용하지 않도록 응답을 내보내는 POST 방식의 WCF Contract 코드 예제입니다. [WebGet] 대신 [WebInvoke]가 사용된 것을 확인하면 됩니다. 그리고 입력과 출력 형식을 모두 JSON으로 지정하였습니다.
이제 아래의 코드를 별도의 JavaScript 파일로 저장합니다.
jQuery.invokeWcf = function(serviceUri, method, data, callback, error, bare) {
var json = JSON.stringify(data);
var url = serviceUri + '/' + method;
$.ajax({
url: url,
data: json,
type: 'POST',
processData: false,
contentType: 'application/json',
timeout: 10000,
dataType: 'text',
success: function(rawResult) {
if (!callback) {
return;
}
var result = JSON.parse(rawResult);
if (bare) {
callback(result);
return;
}
for (var eachProperty in result) {
callback(result[eachProperty]);
break;
}
},
error: function(xmlHttpRequest) {
if (!xmlHttpRequest) {
return;
}
if (xmlHttpRequest.responseText) {
var errorMessage = JSON.parse(xmlHttpRequest.responseText);
if (errorMessage) {
error(errorMessage);
} else {
error({ Message: 'Unknown server error found.' });
}
}
return;
}
});
};
그리고 위의 코드를 사용하기 위하여 JSON2.js 파일이 별도로 필요합니다. JSON2.js는 http://www.json.org/js.html 페이지에서 다운로드할 수 있습니다. 마지막으로, jQuery 플러그인으로 개발된 위의 코드를 사용하기 위하여 jQuery를 추가해야 합니다. 위의 코드는 1.3.2 버전에서 테스트하였습니다.
이제 위의 코드를 호출해보기로 하겠습니다.
var data = {
boardID: parseInt(boardID),
title: $('#' + '<%= this.articleTitle.ClientID %>').attr('value'),
contents: editorInstance.GetXHTML()
};
$.invokeWcf('Board.svc', 'CreateArticle', data, function(result) {
result = result.toString();
if (result == '-1') {
window.alert('글 쓰기 도중 오류가 발생하였습니다.');
return;
}
if ($('#fileQueue > .uploadifyQueueItem').size() > 0) {
$('#fileUploads').uploadifySettings('script', 'UploadHandler.ashx?ID=' + result.toString());
$('#fileUploads').bind('uploadifyAllComplete', function(event, data) {
window.location.replace('ViewArticle.aspx?ID=' + result.toString());
});
$('#fileUploads').uploadifyUpload();
} else {
window.location.replace('ViewArticle.aspx?ID=' + result.toString());
}
}, function(result) { window.alert(result); });
실제 WCF가 제공하거나 입력시 필요로 하는 JSON 코드의 경우 jQuery가 내장하는 getJSON 함수로 다루기에는 까다로운 부분이 많았습니다. 하지만 위의 코드에서처럼 매개 변수를 동적으로 프로그래밍하고 함수 인자를 전달하는 것 만으로 모든 처리가 이루어지게 됩니다.
많은 도움이 되었기를 바라며 글을 마무리합니다.
ps. jQuery를 활용하는 RIA 기반 File Upload 솔루션을 찾고 있다면 uploadify (http://www.uploadify.com) 의 소스 코드를 활용해 보실 것을 권합니다. 무료로 사용 가능하며 약간의 테스트와 개발을 통하여 손쉽게 적용할 수 있습니다.