여기서는 실제적인 Callback 구현에 필요한 각 부품들에 대한 소개와 그 조립 방법들을 전달한다.
일단 Callback을 수행하기 위한 Javascript를 구성하도록 한다.
Callback을 구현할 때 서버 내에서 동작하는 코드와 클라이언트 내에서 동작하는 코드로 나누어 구성한다. 물론 실제 구현 할 때는 대부분 서버 내에서 추가할 수 있지만, 실제 동작은 각기 나뉘어 동작하게 된다.
Callback의 시작과 종료 모두 Javascript를 이용하게 되기 때문에, 어느정도 Javascript에 대한 이해가 필요하다. (물론 고 난이도까지는 아니지만...)
자세한 내용은 아래의 more..를 클릭한다.
먼저 ASPX 페이지 내에서 Callback이 되려면, ICallbackEventHandler 라는 인터페이스가 페이지 내에 구현되어야 한다. ( 만일 WebPart 라면 WebPart 클래스 내에 구현한다.)
먼저 class 설정에서 ICallbackEventHandler 를 상속 받는다.
이 인터페이스가 속한 네임스페이스는 System.Web.UI 이다.
using System.Web.UI;
public partial class FrmCreateTeamSite : Page, ICallbackEventHandler
{
.........
}
위와 같이 포함 시키면 된다. 그런데, 중요한건 ICallbackEventHandler 는 인터페이스 이기 때문에, 클래스 내부에 구현코드를 넣어야 한다. 구현되어야 하는 Method는 두개 인데, 그 두개는 ICallbackEventHandler.RaiseCallbackEvent 와 ICallbackEventHandler.GetCallbackResult이다.
ICallbackEventHandler.RaiseCallbackEvent
이 RaiseCallbackEvent 는 클라이언트(브라우저)에서 서버로 호출할 때 수행되는 로직이다.
보통 웹 페이지 호출의 순서는 브라우저내 URL 입력 -> URL에 해당하는 자원을 서버에서 처리 -> 서버에서 내려주는 그림(HTML, GIF, ActiveX 등등)을 표시 이다. 이 Callback이 실행되는 시점은 위의 작업이 다 끝난 뒤 Javascript 상에서 실행을 시작한다. 즉 그림 그릴 것 다 그리고 Javascript로 서버에 호출하게 되는 것이다. 이 때 서버에서 그 호출을 처리하는 부분이 바로 이 RaiseCallbackEvent 이며, 실제 Callback으로 인해 실행되어야 하는 로직은 여기에 넣도록 한다.
ICallbackEventHandler.GetCallbackResult
서버에서 Callback 처리 한 뒤 특정 결과 값을 클라이언트(브라우저)에 내려 보내야 할 때, 여기서 처리하게 된다. 이 함수를 구현하면 자동으로 string 값으로 돌려주도록 되어 있다는 것을 확인할 수 있다.
string ICallbackEventHandler.GetCallbackResult()
{
return string.Empty;
}
간혹 이 함수 내에서 클라이언트에 값을 돌려주므로 여기에 실제 Callback 연산 때 필요한 값을 넣으면 되지 않을까 생각하시는 분이 있을지도 모른다. 그런데, 개인적인 경험의 결과로 보면, GetCallbackResult 에서는 단순히 return 처리를 하는 로직만 넣는 것을 권장한다. 복잡한 로직이나, 여러 단계로 실행되어 실행 시간이 소요되는 로직이 들어가는 경우 Callback 실행이 중지되어 버린다. 그래서 가급적 RaiseCallbackEvent 에서 모든 서버 처리를 수행한 뒤, GetCallbackResult 에서는 return 처리만 할 수 있도록 구성한다.
using System.Web.UI;
public partial class FrmCreateTeamSite : Page, ICallbackEventHandler
{
string sResult = string.Empty;
void ICallbackEventHandler.RaiseCallbackEvent(string eventArg)
{
sResult = SomethingRun();
}
string ICallbackEventHandler.GetCallbackResult()
{
return sResult;
}
string SomethingRun()
{
// Callback으로 무언가 실행
// 결과를 돌려줌
return "OK";
}
}
지금까지 구성내용은 서버에서 동작되어야 되는 코드들을 넣어 보았다. 아래에서는 클라이언트(브라우저)에서 동작될 코드들에 대해서 정리해 보도록 하겠다.
클라이언트에서 동작하기 위해서는 Callback을 실행시켜 줄 Javascript 문장과, 서버에서 돌려주는 결과값을 받을 문장으로 구분되어 진다. 먼저 Callback을 발생시키는 Javascript 문장은 아래와 같다.
javascript:WebForm_DoCallback('[서버컨트롤ID]', [인수값변수이름], [CALLBACK결과를 받을 함수이름],[실행컨텍스트구분용 변수이름], [에러처리용 함수이름], [비동기 처리?])
위의 각 한글 이름들에 각각의 값들을 넣으면 된다.
예를 들어 Callback이 발생되는 서버 컨트롤이 Page 이고, 클라이언트에서 서버로 건네줄 때 쓰는 변수가 arg이고, 실행 완료시 실행되는 Javascript 함수 이름이 JobDone 이며, 실행 컨텍스트 구분용 변수 이름이 context이고, 오류 처리용 스크립트 함수는 없으며 비동기로 실행되어야 되는 경우 아래와 같이 넣으면 된다.
javascript:WebForm_DoCallback('__Page',arg,JobDone,context,null,true)
자 그럼 각 파라미터에 대한 설명은 아래와 같다.
서버 컨트롤 ID : Callback이 실행되는 주체가 되는 서버 컨트롤 개체 ID를 넣으면 된다. 만일 Callback이 ASPX 페이지 자체에서 발생되는 것이면 해당 Page의 ID가 들어가면 되고, 만일 Button 인 경우에는 해당 Button의 컨트롤 ID가 들어가면 된다.
인수 값 변수 이름 : 클라이언트에서 서버로 값을 넘겨 줄 때 사용되는 인수 값을 의미한다. 이 때 넘겨 받을 때 문자열로 받기 때문에, 대부분의 영숫자 뿐만 아니라, 특수문자까지 넘겨 줄 수 있다. 그러나 많은 양의 데이터는 전달할 수 없으며, 간단한 신호적인 의미를 담는게 보통이다.
CALLBACK 결과를 받을 함수 이름 : 앞서 설명한 함수 에서 GetCallbackResult 문자열을 받을 때 사용되는 함수. 이 함수는 Javascript로 구현되어 있어야 하며, 최소한 value를 받아주는 파라미터가 있어야 한다. 만일 실행 컨텍스트 까지 정의되어 있으면 Context라는 파라미터도 있어야 한다. 위의 예제를 근거로 만든다면 아래와 같은 코드로 작성된 함수가 있어야 한다.
function JobDone(val, context)
{
// 서버에서 받는 값은 val 임. val 값을 가지고 처리해야 되는 javascript를 구현
document.getElementById('TextBox1').value = val;
return;
}
실행 컨텍스트 구분용 변수 이름 : 만일 실행 결과의 유형이 여러가지 인 경우 그 구분을 위해 넣는 변수. 보통은 서버 -> 클라이언트 결과 값으로 대충 해결 할 수도 있지만, arg 값은 서버에 전달 되면 끝이기 때문에, 서버 -> 클라이언트로 넘겨지는 값에 일일히 명시 해주어야 한다. 이를 보다 편하게 할 수 있도록 클라이언트 -> 서버 -> 클라이언트 동작 중에 변하지 않는 값이 바로 이 값으로 이 값을 응용 하면, CALLBACK 결과를 받는 함수 하나로 여러가지의 처리가 가능하다. 그 예제가 아래와 같으 코드이다. 보면 context라는 변수가 있는데, 오로지 그 변수 값에 각 Step에 해당하는 값을 넣어 3단계에 걸친 처리를 수행할 수 있다.
function DoJob(arg, context)
{
WebForm_DoCallback('__Page',arg,JobDone,context,null,true)
}function JobDone(val, context)
{
var step;
if(context == 'FirstStep')
{
// 1단계
setTimeout("JobStart('somevalue', 'SecondStep')",5);
return;
}
if(context == 'SecondStep')
{
// 2단계
setTimeout("JobStart('somevalue', 'LastStep')",5);
return;
}
if(context == 'LastStep')
{
// 3단계
return;
}
}
setTimeout("JobStart('somevalue', 'FirstStep')",1);
에러처리용 함수이름 : Callback 실행도중 에러가 발생했을 때 그 처리를 수행할 때 이용하는 스크립트 함수 이름이다. Callback이 클라이언트 단에서 에러가 나는 경우에는 바로 사용자가 보여지도록 Javascript에서 처리할 수 있지만, 서버에서 실행이 오류가 나는 경우 그에 해당하는 처리가 쉽지는 않다. 이 경우 처리해 줄 때 사용한다. 이 에러처리용 함수는 인터페이스 중 RaiseCallbackEvent Method에서 Exception이 발생하는 경우 불려지게 되는데, 이에 적당한 처리를 하는 Javascript를 구현한다. 만일 RaiseCallbackEvent 인터페이스에서 try ~ catch로 모든 Exception을 처리한다면 이 부분이 영원히 불릴일은 없을 것이다.
비동기 여부 : Callback 처리가 순차적으로 동작해야 되는지 여부를 결정하는 부분이다. 만일 이곳이 false인 경우 이 Callback이 처리될 때 까지 클라이언트 쪽 화면은 그대로 얼어 있게 된다. 트랜젝션상 성공/실패가 명확한 처리가 있는 경우에는 이 부분을 false로 하고, 아니면 true로 변경한다.
일단 Callback에서 가장 제일 중요하다고 생각되는 부분만을 정리해서 담아 보았다. 다음 3편에서는 실전에서 어떻게 쓰이는지 어떻게 활용할 수 있는지를 다시 둘러보는 시간을 갖도록 한다.
하인도1
[하인드/하인도/인도짱 의 홈페이지] 저만의 공간입니다. 다양한 소재들을 나열하는 아주 단순 무식한 홈페이지 입니다. 다양한 문서 자료도 있겠지만, 저의 푸념들도 있답니다.