분류 전체보기 (328)
.NET (111)
S/W tip (35)
etc (63)
DB (34)
HOT item~! (48)
Disign pettens (4)
UX (6)
나의 S/W (2)
개발관련 이슈 (16)
Diary (1)
웹플러스 (1)
calendar
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
tags
archive
link
ColorSwitch 00 01 02
ScriptManager를 통해 웹 응용 프로그램에서 AJAX 사용
Ben Rush

이 기사에서 다루는 내용:
  • ASP.NET AJAX에서 ScriptManager의 역할
  • ScriptManager의 암시적 또는 명시적인 사용
  • ASP.NET AJAX의 웹 서비스 지원
  • ASP.NET AJAX 페이지 수명 주기
이 기사에서 사용하는 기술:
ASP.NET AJAX
근래에는 웹 사이트를 방문하는 소비자가 웹 사이트의 콘텐츠, 발전 방향, 그리고 게시자의 성공을 좌우합니다. 쉴 새 없이 등장하는 이러한 새로운 스타일의 웹 사이트로는 커뮤니티 사이트, 블로그, 온라인 사진 저널, Wiki 등을 예로 들 수 있으며, 이는 단지 시작에 불과합니다. 웹 사이트에서 최고의 콘텐츠를 제공한다고 해도, 사용자가 사이트의 성장과 개발에 참여할 수 있는 길목을 막는다면 얼마 지나지 않아 사이트는 쓸모없는 곳으로 쇠락할 것입니다.
이러한 상황에서, 개발자로서 여러분이 할 일은 평균적인 고객의 요구를 수용할 수 있는 도구를 찾아 사용하는 것입니다. 뛰어난 사이트를 만들려고 할 때 가장 먼저 고려할 부분은 바로 웹 브라우저 자체로, 이는 소비자에게 가장 가까운 부분이기 때문입니다. 하지만 근래 사용되는 웹 브라우저가 가진 많은 기능의 장점을 활용하는 것이 언제나 쉬운 것은 아닙니다. 브라우저와 상호 작용하는 코드를 작성하는 일에는 상당한 노력이 필요한데, 이는 현존하는 브라우저 및 운영 체제 조합의 종류가 무수히 많아 일관성을 유지하기가 굉장히 어렵기 때문입니다. 많은 기능을 갖춘 클라이언트와 웹 응용 프로그램을 함께 만들 수 있는 하나의 플랫폼이 있어 특정한 브라우저에서의 사용자 환경을 최적화하는 데 필요한 노력을 다른 브라우저 환경을 위해 또 한 번 수행할 필요가 없다면 많은 도움이 될 것입니다.
ASP.NET AJAX는 웹 응용 프로그램 개발의 이러한 어려움을 해소하기 위해 Microsoft에서 개발한 기술입니다. 필자는 이 기사를 통해 ScriptManager라는 ASP.NET AJAX의 핵심 구성 요소를 소개하고 이를 사용하여 ASP.NET AJAX의 고급 프로그래밍을 활용하는 방법을 보여주고자 합니다. ScriptManager는 Web Form에 위치하는 서버 쪽 컨트롤이며 ASP.NET AJAX의 핵심적인 부분이 작동할 수 있게 만드는 요소입니다. ScriptManager의 주 역할은 Web Form의 모든 다른 ASP.NET AJAX 컨트롤을 조정하고 웹 브라우저에 올바른 스크립팅 라이브러리를 추가하여 ASP.NET AJAX의 클라이언트 부분이 작동하도록 만드는 것입니다. 다른 컨트롤, 웹 서비스, 클라이언트 스크립트를 등록하는 데 ScriptManager를 자주 사용하게 될 것입니다.
ScriptManager는 서버 쪽 컨트롤로서, ASP.NET 페이지의 수명 주기 내에 발생하는 이벤트에 반응하고 이러한 이벤트를 사용하여 ASP.NET AJAX에서 추가한 모든 컨트롤, 옵션, 코드의 동작을 조정합니다. ScriptManager는 특정한 이벤트에 연결되며 이 이벤트가 발생하면 알림을 받아 환경에 따라 몇 가지 설정을 구성하게 됩니다. 이러한 과정은 ASP.NET 페이지를 렌더링하는 주기를 따라 여러 차례 반복됩니다. ScriptManager가 구성하는 이러한 설정은 대개 ASP.NET AJAX가 매끄럽게 작동하는 데 필요한 설정입니다.
먼저 ScriptManager로 인해 사용이 가능한 ASP.NET AJAX의 몇 가지 주 기능에 대해 알아보고, 서버 컨트롤의 수명 주기를 살펴보도록 하겠습니다. ScriptManager의 내부를 이해해야만 ScriptManager가 제공하는 웹 응용 프로그램 개발용 옵션의 진가를 알고 이를 최대한 활용하는 방법을 배울 수 있을 것입니다.
ASP.NET AJAX의 중심 요소인 스크립팅부터 시작하겠습니다. 사실 ASP.NET AJAX의 모든 기능은 각각의 스크립팅 라이브러리에 의해 좌우됩니다. 스크립팅에 대해 살펴본 후 ASP.NET AJAX 내에서 지원되는 몇 가지 AJAX 기능에 대해 소개하고 웹 서비스와의 상호 작용 방법을 설명한 후 마지막으로 인증에 대해 약간 다루고자 합니다. 각 부분을 설명하면서 ScriptManager를 통해 옵션을 조정하는 방법도 설명합니다.

ScriptManager를 사용한 스크립팅
그림 1의 코드 블록은 ASP.NET AJAX에서 클래스를 정의하는 표준적인 방법을 보여 줍니다. 클라이언트 스크립트 라이브러리의 내부에 대한 내용은 이 기사에서 다룰 부분이 아니지만, 간단히 정리하면 ASP.NET AJAX 스크립트 확장 기능을 기반으로 클래스를 만드는 데 필요한 일반적인 단계는 다음과 같습니다.
  1. ASP.NET AJAX를 사용하여 네임스페이스를 등록합니다.
  2. 생성자 메서드를 작성합니다.
  3. 멤버 메서드와 기능을 지정하여 클래스 프로토타입을 만듭니다.
  4. ASP.NET AJAX를 사용하여 클래스를 등록합니다.
  5. Sys.Application.notifyScriptLoaded를 호출하여 형식 정의의 끝에 도달했음을 ScriptManager에서 추가한 클라이언트 스크립트에 통지합니다.
클라이언트에만 기능을 제공할 경우 이 클래스로 충분하지만 ScriptManager 컨트롤을 사용하면 ASP.NET AJAX의 흥미로운 스크립팅 기능을 활용하여 클라이언트 쪽의 JavaScript와 서버 쪽의 Microsoft® .NET Framework 코드에 동시에 기능을 제공할 수 있습니다. 예를 들어 컨트롤 사용자가 인스턴스의 속성을 다음과 같이 설정한 경우
public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        this.MyCustomButton.AlertMessage = "Hey, stop clicking me!"; 
    }
}
브라우저 내에서 다음과 같은 스크립트를 통해 컨트롤 인스턴스와 상호 작용할 수 있습니다.
<script type="text/javascript">
    function get_text()
    {
        var mb = $find("MyCustomButton");
        var text = mb.get_AlertMessage(); 
        // do something with the text
    }
</script>
서버 및 클라이언트 양쪽 모두의 컨트롤에 대한 참조로 MyCustomButton이라는 이름을 동일하게 사용했음을 눈여겨 보십시오. 속성인 AlertMessage도 사용했는데, 속성값은 서버/클라이언트 경계를 넘어 사용되고 있습니다. 이러한 방식은 아주 자연스러워 보이지만 ASP.NET AJAX가 사용되기 전에는 이러한 통합된 서버/클라이언트 프로그래밍 모델을 활용하는 것이 쉽지 않았으며 많은 양의 코드를 직접 작성해야 했습니다. 하지만 이제는 ASP.NET AJAX를 통해 이러한 통합된 서버/클라이언트 패러다임이 통합되었으며 완전하게 지원됩니다.
이러한 서버/클라이언트의 긴밀한 결합은 IScriptControl과 IExtenderControl이라는 두 개의 새로운 인터페이스 덕분에 가능한 것입니다. 이러한 인터페이스를 사용하려면 여기서 상속된 ASP.NET 웹 컨트롤을 만들고 필요한 인터페이스 메서드를 구현하고 페이지의 ScriptManager 컨트롤을 사용하여 컨트롤을 등록하면 됩니다. 다음은 IScriptControl의 필수 메서드를 구현하는 서버 쪽 컨트롤 코드의 기본 구조를 보여주는 예입니다.
class CustomButton : Button, IScriptControl
{
    IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
    {
        ...
    }

    IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
    {
        ...
    }
}
GetScriptDescriptors와 GetScriptReferences 메서드는 개발자의 컨트롤 코드를 서버 및 클라이언트 개체에 논리적으로 설명하는 데 필요한 모든 정보를 ScriptManager 컨트롤에 반환합니다. 그 결과로 앞서 본 것과 같이 개체 인스턴스가 서버/클라이언트의 범위를 넘나드는 환경이 가능해집니다.
GetScriptReferences는 컨트롤 코드에 필요한 스크립트 파일의 목록을 반환합니다. 이때 컨트롤의 정의를 스크립트 클래스로 표현한 스크립트 파일, 즉 서버 쪽 컨트롤을 클라이언트 쪽 스크립트로 나타낸 스크립트 파일은 반드시 반환되어야 합니다.
GetScriptDescriptors 메서드는 ScriptDescriptors를 반환하거나 클라이언트 클래스의 속성과 이벤트를 설명하는 개체를 반환합니다. ScriptDescriptors는 속성 및 이에 연관된 값을 포함하는 클라이언트 클래스의 메타데이터를 담고 있습니다.
그림 2는 앞서 살펴본 서버 컨트롤보다 약간 더 복잡한 형태의 예입니다. 이 경우 GetScriptDescriptors 및 GetScriptReferences 메서드의 내용이 채워져 있습니다.
private string _alertMessage = null;

public string AlertMessage
{
    get { return _alertMessage; } set { alertMessage = value; }
}

public IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
    ScriptControlDescriptor descriptor = new ScriptControlDescriptor(
        "CustomButton", this.ClientID);
    descriptor.AddProperty("AlertMessage", this._alertMessage);
    return new ScriptDescriptor[] { descriptor };
}

public IEnumerable<ScriptReference> GetScriptReferences()
{
    ScriptReference reference = new ScriptReference(
        "MyCustomContent.JScript1.js", "MyCustomContent");
    return new ScriptReference[] { reference };
}

GetScriptDescriptors 내에서는 먼저 ScriptDescriptor 개체를 인스턴스화했습니다. ScriptDescriptor의 생성자에는 대상 컨트롤의 이름인 CustomButton을 인수로 지정했으며 다음은 AlertMessage 속성과 그 값(전용 멤버 _alertMessage에 저장된 값)을 ScriptDescriptor에 추가하였습니다. 이제 ASP.NET AJAX를 통해 클라이언트 코드에서 AlertMessage 속성과 상호 작용할 수 있습니다.
GetScriptReferences에서는 .js 파일을 가리키는 ScriptReference 개체를 만들고 반환했습니다. .js 파일에는 컨트롤의 클라이언트 쪽 코드, 즉 모든 클라이언트 기능이 들어 있습니다.
이제 컨트롤을 ScriptManager에 등록하여 컨트롤이 있음을 알릴 수 있습니다(이 단계에 대해서는 뒤에서 설명함). 페이지가 렌더링되면 다양한 이벤트가 ScriptManager 컨트롤에 전달되고 이 컨트롤은 이러한 이벤트에 반응하여 GetScriptDescriptors 및 GetScriptReferences를 호출하게 됩니다. 호출된 두 메서드는 클라이언트 개체를 해당 서버 요소에 연결하는 데 필요한 모든 정보를 담은 ScriptDescriptors 및 ScriptReferences를 ScriptManager 컨트롤에 반환합니다. 앞서 소개한 예의 경우 ScriptDescriptor가 CustomButton이라는 사용자 지정 컨트롤을 AlertMessage라는 속성과 함께 ScriptManager 컨트롤에 전달하고 있습니다. 또한 GetScriptDescriptors 내에서 설정된 속성의 값도 ScriptDescriptor에 포함됩니다.
ScriptManager 컨트롤은 MyCustomContent.JSScript1.js라는 외부 .js 파일에 대한 참조도 받는데, 스크립트 파일에 대한 참조는 GetScriptReferences에서 반환하는 ScriptReference 개체를 통해 전달됩니다. .js 파일 내에서 컨트롤의 클라이언트 클래스에 대한 프로토타입과 나머지 내용은 그림 3과 같은 방식으로 정의됩니다.
CustomButton.prototype = {
    initialize : function() {
        // initialize the base
        CustomButton.callBaseMethod(this,'initialize');
        
        this._onclick = 
            Function.createDelegate(this, this._onclick);
        
        Sys.UI.DomEvent.addHandler(
            this.get_element(), 'click', this._onclick); 
    },
    dispose : function() {
        // release the handlers
        $clearHandlers(this.get_element());

        // call to the base to do its dispose
        CustomButton.callBaseMethod(this,'dispose');
    },
    get_AlertMessage: function(){
        return this._alertMessage; 
    },
    set_AlertMessage: function(value){
        this._alertMessage = value; 
        return; 
    },
    _onclick: function(e){
        alert(this._alertMessage); 
        return; 
    }
}
CustomButton.registerClass("CustomButton",Sys.UI.Control); 
if(typeof(Sys)!=='undefined') Sys.Application.notifyScriptLoaded();

가장 먼저 눈여겨볼 부분은 클라이언트 클래스에 AlertMessage 속성에 대한 get_ 및 set_ 메서드가 있다는 점입니다. ScriptManager 컨트롤은 이 속성의 값을 ScriptDescriptor 개체를 통해 서버에 지정한 모든 항목으로 설정합니다. 앞서 살펴본 예에서 AlertMessage는 서버 코드를 통해 제공되므로 서버에서 설정되는 모든 속성은 클라이언트 개체에 전달되는 AlertMessage 속성에도 반영됩니다.

AJAX와 ScriptManager
ASP.NET AJAX를 처음 사용하는 많은 개발자들이 가장 먼저 사용하게 되는 컨트롤은 UpdatePanel로, ScriptManager 컨트롤이 페이지에 포함되어 있고 UpdatePanel에 컨트롤이 있다면 이 컨트롤은 AJAX의 기능을 통해 비동기 방식으로 업데이트될 수 있습니다. Visual Studio®의 디자인 화면에서 본 이러한 설정의 기본적인 모습은 그림 4와 같습니다.
그림 4 간단한 비동기 컨트롤 
구조와 작동 방식은 매우 간단합니다. 사용자가 Button 컨트롤을 클릭하면 포스트백 이벤트가 발생하고 UpdatePanel 컨트롤이 이 이벤트를 감지합니다. UpdatePanel은 이 포스트백 이벤트를 부분 포스트백으로 다시 전송하며 브라우저가 페이지를 완전히 다시 로딩할 필요 없이 그 내용이 비동기적으로 업데이트됩니다.
하지만 이런 상황에서 개발자의 예측이 빗나가고, 그 원인을 찾을 수 없는 경우가 많습니다. 예를 들어 UpdatePanel 컨트롤과 AJAX의 새로운 스크립트 참조 방식 때문에 문제가 발생할 수 있습니다. 전에는 다음과 같이 전체 포스트백의 결과로 페이지에 스크립트를 추가했지만
protected void Button1_Click(object sender, EventArgs e)
{
    Page.ClientScript.RegisterStartupScript(
        this.GetType(),"myscript","alert('hello world!');");
}
ASP.NET AJAX에서는 이 새로운 메서드가 제대로 작동하지 않습니다. 이유는 무엇일까요? ClientScriptManager는 부분 포스트백과 부분 렌더링을 인식할 수 있는 컨트롤이 아니므로 여기에 등록된 스크립트 코드는 부분 포스트백의 결과인 페이지 응답에 포함되지 않기 때문입니다.
단추를 클릭했을 때 클라이언트 스크립트가 페이지 출력에 반영되도록 하려면 다음과 같이 ScriptManager를 대신 사용해야 합니다.
protected void Button1_Click(object sender, EventArgs e)
{
    ScriptManager.RegisterStartupScript(
        this,this.GetType(),"myscript","alert('hello world!');",true);
}
결과는 같지만 방법이 조금 다릅니다. 사실 ClientScriptManager 컨트롤의 메서드는 이제 정적 메서드로 ScriptManager 컨트롤에 포함되므로(예를 들어 RegisterStartupScript) ASP.NET AJAX를 활용하고 부분 포스트백을 통해 작업하고자 할 때에는 ScriptManager 컨트롤이 제공하는 메서드를 대신 사용해야 합니다.
또 한 가지 상황으로, 그림 5와 같이 설정된 컨트롤을 고려해 보겠습니다. 일반적인 상황에서는 LinkButton이 클릭되면 Web Form의 전체 포스트백이 이루어질 것입니다. 하지만 LinkButton을 눌러 비동기적으로 UpdatePanel의 내용을 비동기적으로 새로 고치고 싶다면 어떻게 할까요? 즉 LinkButton을 눌렀을 때 이 단추가 UpdatePanel 내에 있는 것처럼 동작하게 하려면 어떻게 해야 할까요? 이렇게 하려면 RegisterAsyncPostBackControl이라는 ScriptManager 컨트롤의 메서드를 사용하면 됩니다.
그림 5 비동기 방식으로 LinkButton 사용 
protected void Page_Load(object sender, EventArgs e)
{
    // register the LinkButton1 control as one that can 
    // cause partial postbacks. 
    ScriptManager1.RegisterAsyncPostBackControl(LinkButton1);
}
이제 LinkButton을 클릭하면 LinkButton 컨트롤이 실제로 UpdatePanel에 있는 것처럼 UpdatePanel의 내용이 비동기 방식으로 새로 고쳐집니다.
반대로 UpdatePanel 내의 요소가 전체 포스트백, 즉 페이지의 전체 내용을 새로 고치도록 할 수도 있습니다. 이렇게 하려면 RegisterPostBackControl이라는 또 하나의 ScriptManager 메서드를 사용하면 됩니다.
protected void Page_Load(object sender, EventArgs e)
{
    // Button1 will cause a full post-back no matter
    // where it is on the page.  
    ScriptManager1.RegisterPostBackControl(Button1);
}
이 코드가 실행되면 Button1 컨트롤이 UpdatePanel 내에 있음에도 불구하고 클릭했을 때 페이지의 전체 포스트백이 발생합니다.
한발 더 나아가 이런 것도 가능합니다. UpdatePanel 컨트롤의 부분 포스트백을 실행하도록 컨트롤을 조정하는 방법을 설명했는데, 페이지 내 어딘가에 있는 완전히 UpdatePanel의 범위를 벗어나는 컨트롤이 UpdatePanel이 새로 고쳐질 때 업데이트되도록 할 수 있을까요? ScriptManager 컨트롤을 사용하면 됩니다.
ScriptManager의 RegisterDataItem 메서드를 사용하면 UpdatePanel의 외부에 있는 컨트롤이나 데이터를 쉽게 새로 고칠 수 있습니다. RegisterDataItem은 UpdatePanel 컨트롤이 포스트백될 때 개발자가 선택한 추가 데이터를 클라이언트에 전송하고 이 데이터를 개발자가 클라이언트에 작성한 스크립트에서 사용할 수 있도록 하는 기능을 제공합니다.
예를 들어 그림 6과 같은 컨트롤이 있고 Calendar 컨트롤에서 값이 선택되면 Label을 업데이트하고 싶다면 어떻게 할까요? 간단해 보일지 모르지만 Calendar 컨트롤은 UpdatePanel 내에 있는 반면 Label은 그렇지 않습니다. UpdatePanel이 Label을 새로 고치도록 하려면 어떻게 할까요? 대답은 간단합니다. 서버 쪽 코드에서 RegisterDataItem을 사용하면 클라이언트 쪽 코드에 추가 데이터를 보낼 수 있으며 클라이언트는 RegisterDataItem이 전송한 데이터를 사용하여 Label을 새로 고칠 수 있습니다.
그림 6 UpdatePanel 외부의 컨트롤을 업데이트 
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
    ScriptManager1.RegisterDataItem(
        Label1, Calendar1.SelectedDate.ToShortDateString()); 
}
RegisterDataItem은 업데이트할 컨트롤을 첫 번째 인수로, 컨트롤 업데이트에 사용할 원시 데이터를 두 번째 인수로 취합니다. ScriptManager 컨트롤은 개발자가 전달한 데이터를 받아 래핑한 다음 부분 포스트백 이벤트에 대한 응답으로 클라이언트에 전송합니다. 클라이언트 코드에서는 이벤트가 종료된 후 ScriptManager 컨트롤이 전송한 데이터를 다음과 같이 얻을 수 있습니다.
<script type="text/javascript">
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(
        PageLoadingHandler); 
    function PageLoadingHandler(sender,args){
        var dataItems = args.get_dataItems(); 
        if($get('Label1')!==null){
            $get('Label1').innerHTML = dataItems['Label1']; 
        }
        return; 
    }
</script>    
스크립트 코드에서는 몇 가지 작업이 수행됩니다. 먼저 PageRequestManager 클라이언트 클래스를 통해 pageLoading 이벤트를 등록합니다. 다음은 pageLoading 이벤트에 대한 처리기인 PageLoadingHandler를 구현합니다. 이 처리기는 두 번째 인수인 args로부터 데이터 항목의 이름/값 컬렉션을 얻습니다. 마지막으로 서버에서 RegisterDataItem의 두 번째 인수로 제공한 컨트롤 이름을 사용하여 원하는 값을 얻어냅니다.

웹 서비스와 ScriptManager
ASP.NET AJAX 스크립트를 사용하면 비동기 방식으로 웹 서비스와 상호 작용하고, 오류를 포함하여 응답을 처리하고, 이러한 응답 처리를 통해 매우 유용하고 고유한 페이지를 만들어낼 수 있습니다. 이 과정의 시작부터 끝, 즉 브라우저에서 서버에 이르기까지 ASP.NET AJAX를 통해 매우 직관적인 방식으로 웹의 최신 기술을 활용하게 됩니다.
ScriptManager 컨트롤은 여러분의 ASP.NET AJAX 응용 프로그램에서 필요한 모든 서비스에 대한 전역 등록자 역할을 합니다. 그림 7은 Visual Studio를 통해 살펴본 ScriptManager 컨트롤의 속성 메뉴를 보여 줍니다.
그림 7 ScriptManager 속성 
Scripts 컬렉션이 선택되어 있으며 그 아래는 웹 서비스인 Services에 대한 컬렉션이 있음을 볼 수 있습니다. 클라이언트 코드에서 상호 작용할 모든 서비스는 ScriptManager를 사용하여 등록해야 합니다. ScriptManager 컨트롤에 서비스 참조를 추가하려면 Services 컬렉션을 확장하고 그림 8과 같이 참조를 추가하면 됩니다.
그림 8 웹 서비스 참조 추가 (더 크게 보려면 이미지를 클릭하십시오.)
이렇게 하면 어떤 일이 일어날까요? 자세한 내용은 곧 설명하겠지만 일단 ScriptManager를 통해 서비스를 참조하는 페이지의 소스를 보면 다음과 같은 내용을 확인할 수 있습니다.
<script src="WebService.asmx/jsdebug" type="text/javascript"></script>
웹 서비스가 ScriptManager를 사용하여 등록되었기 때문에 외부 참조 역시 ScriptManager에 의해 페이지 출력에 추가됩니다. 웹 서비스 이름에 /jsdebug가 추가되었음을 알 수 있는데, 릴리스 빌드였다면 /js만 추가되었을 것입니다. ASP.NET AJAX 파이프라인에서 이 서비스에 대한 요청을 발견하고 웹 서비스 이름에 /js가 붙어 있음을 확인하면 웹 서비스의 메서드를 래핑하는 스크립트 클래스(프록시 스크립트)를 반환하게 됩니다. 프록시 스크립트 클래스의 각 메서드 내에서는 해당하는 웹 서비스 메서드에 대한 비동기 호출이 수행되므로 웹 서비스 메서드를 호출하려면 단순히 ASP.NET AJAX 웹 서비스 프레임워크에서 작성한 스크립트 클래스에 있는 해당 메서드를 호출하면 됩니다. 아주 간단합니다.
WebService라는 서비스에 다음과 같이 Add라는 메서드가 있을 경우
[WebMethod]
public int Add(int a, int b) { return a + b; } 
스크립트에서 다음과 같이 호출할 수 있습니다.
function CallAdd()
{
    // method will return immediately
    // processing done asynchronously
    WebService.Add(0,6, OnMethodSucceeded, OnMethodFailed);
}
이 예에서는 프레임워크가 전달한 자동 생성 스크립트 프록시 클래스가 웹 서비스 호출을 래핑하고 있으므로 개발자는 스크립트에서 이 클래스와 상호 작용하면 됩니다. 이렇게 하면 WebService.Add가 해당 웹 서비스 메서드인 Add를 호출합니다.
일반적으로 웹 서비스를 호출할 때는 두 개의 콜백이 정의됩니다. 하나는 성공할 경우에 대한 것이고, 다른 하나는 실패할 경우에 대한 것입니다. 웹 서비스 호출은 비동기 방식으로 실행되므로 콜백은 호출이 실제로 어떻게 완료되었는지 알아야 합니다. 다음은 성공 콜백과 실패 콜백을 각각 구현하는 메서드의 예입니다.
function OnMethodSucceeded(result, eventArgs)
{
    var label = Sys.UI.DomElement.getElementById('Label1');
    var sb = new Sys.StringBuilder(); 
    sb.append('You got back a value of '); 
    sb.append(result.toString()); 
    label.innerHTML = sb.toString();  
}

function OnMethodFailed(error)
{
    alert(error.get_message()); 
}
웹 서비스로의 요청과 결과는 비동기 방식으로 전달되므로 그 효과는 UpdatePanels 컨트롤을 사용할 때와 유사합니다. 즉, 웹 서비스로부터 받은 데이터를 사용하여 전체 브라우저 포스트백 없이도 내용을 새로 고칠 수 있습니다. 앞서 살펴본 샘플 코드를 보면 WebMethod Add로의 웹 서비스 호출 결과를 사용하여 Label1을 비동기 방식으로 업데이트했음을 알 수 있습니다. 결과는 그림 9와 같습니다. 전체 포스트백은 발생하지 않으며 매끄럽게 Label1이 업데이트됩니다.
그림 9 업데이트된 레이블 

인증 및 개인 설정
인증 및 개인 설정과 같은 ASP.NET AJAX의 고급 기능 역시 웹 서비스를 사용합니다. ASP.NET AJAX의 인증 서비스는 두 메서드를 구현하는데, 하나는 사용자의 로그인을, 다른 하나는 로그아웃을 위한 것입니다.
Sys.Services.AuthenticationService.login
Sys.Services.AuthenticationService.logout
ASP.NET AJAX는 폼 인증을 사용합니다. 즉 웹 서버에 의해 브라우저의 세션에 올바른 폼 인증 쿠키가 삽입되면 사용자가 로그인됩니다. 쿠키 데이터가 ASP.NET AJAX의 세션으로 삽입되는 방식은 전체 포스트백을 통한 것과 같은 방식이므로 사용되는 메커니즘에는 차이가 없습니다. 쿠키가 이미 브라우저의 세션에 삽입되어 있다면 클라이언트는 서버에 인증되어 제한된 페이지와 내용을 볼 수 있게 됩니다.
인증을 수행하고 클라이언트 스크립트에서 특정한 사용자를 로그인 또는 로그아웃시킬 수 있다는 사실은 상호 작용이 원활한 사용자 기반의 시스템을 위한 흥미로운 가능성을 낳습니다. AuthenticationService와 스크립트를 사용하여 사용자가 로그인하는 예를 보겠습니다.
<script type="text/javascript">
    function MyMethod(username, password)
    {
        Sys.Services.AuthenticationService.login(username,
            password,false,null,null,null,null,"User Context"); 
    }
</script>
AJAX 응용 프로그램에서 인증을 사용하는 단계는 잘 문서화되어 있으므로(ajax.asp.net 참조) 여기서 다루지는 않겠습니다. 하지만 한 가지 분명하게 알 수 있는 것은 폼 인증이 스크립트를 통해 쉽게 구현될 수 있다는 점입니다.
표준 ASP.NET 인증 서비스만으로 부족하다면 자체 인증 방식을 만들고 ScriptManager 컨트롤로 등록하면 됩니다. 인증 기능을 구현하는 웹 서비스에 필요한 메서드는 다음과 같습니다.
[WebMethod]
public bool Login(string userName, 
    string password, bool createPersistentCookie)
{
    ... // code to check user credentials and log user in
}

[WebMethod]
public void Logout()
{
    ... // code to log user out. 
}
자체 구현 코드를 추가한 후에는 새 인증 서비스를 ScriptManager 컨트롤을 사용하여 등록해야 합니다. 새 인증 서비스가 등록되면 ASP.NET AJAX의 기본 인증 서비스와 상호 작용하던 기존의 클라이언트 코드가 이제 새 서비스를 대신 사용하게 됩니다. 따라서 클라이언트 스크립트 쪽에서는 사용자 지정 인증 웹 서비스를 사용하기 위해 변경할 부분이 없습니다.
다음은 ScriptManager를 통해 선언적으로 인증 서비스를 등록하는 예입니다.
<asp:ScriptManager ID="ScriptManager1" 
  runat="server" >
    <AuthenticationService 
  Path="WebService.asmx" />
</asp:ScriptManager>
이 시점에서 구현 내용에 대해 알지 못하더라도 ASP.NET AJAX의 자체 프로필 서비스의 장점을 활용할 수 있습니다. 프로필 서비스는 인증 서비스와 같은 방법으로 ScriptManager 컨트롤을 통해 등록할 수 있습니다. 프로필 서비스를 사용하면 웹 사이트를 특정한 사용자에 맞게 꾸밀 수 있습니다. 필요한 작업은 클라이언트 스크립트에서 진행되므로 사용자는 명확하고 매끄러운 환경을 누릴 수 있습니다. ajax.asp.net을 방문하면 이에 대한 예를 볼 수 있습니다.

작동 원리
ScriptManager 컨트롤은 자체적으로 두 가지 기본 단계를 수행합니다. 첫 번째 단계에서는 환경이 ASP.NET AJAX의 풍부한 모든 기능을 지원할 수 있는지 확인하고 이를 지원하기 위한 모든 내용을 설정합니다. 두 번째 단계에서는 클라이언트에서 실행되는 코드로 실제 비동기 통신을 수행하여 스크립트가 필요한 페이지 업데이트를 수행할 수 있도록 합니다. ASP.NET의 서버 쪽 컨트롤과 웹 프로그래밍은 이벤트 기반으로 진행되므로 ScriptManager 컨트롤의 핵심은 이를 어떻게 등록하고 이벤트에 어떻게 응답하느냐에 달려 있습니다. ScriptManager가 응답하는 이벤트의 개요는 그림 10에 나와 있습니다.
그림 10 ASP.NET AJAX에서의 클래스 정의 

ScriptManager를 사용한 개체 등록
스크립트와 서비스는 ScriptManager를 사용하여 선언적으로 추가할 수 있습니다. 하지만 ScriptManager 컨트롤의 Services 및 Scripts 속성을 통해 프로그래밍 방식으로도 추가할 수 있습니다. 또한 클라이언트에 특별한 데이터를 보내도록 선택하고 컨트롤이 특별한 스크립트 컨트롤로 ScriptManager와 함께 작동하도록 설계할 수도 있습니다. 이 모든 기능을 사용하려면 ScriptManager 컨트롤을 사용하여 개체를 참조해야 합니다.
그렇다면 ScriptManager는 이러한 참조를 가지고 무슨 작업을 할까요? ScriptManager 컨트롤과 ASP.NET AJAX 기능을 호스팅하는 페이지를 브라우저에서 처음으로 요청하면 페이지의 하위 컨트롤의 초기화 단계에서 ScriptManager의 OnInit 메서드가 호출됩니다. OnInit는 하나의 ScriptManager 컨트롤만 페이지에 있게끔 확인하는 것과 페이지가 부분 포스트백을 수행하는지를 확인하는 등 몇 가지 중요한 단계를 수행합니다. 하지만 OnInit가 수행하는 가장 중요한 단계는 InitComplete, PreRenderComplete, PreRender 등과 같이 호스트 페이지에서 생성되는 일련의 이벤트에 등록하는 것입니다. ASP.NET AJAX는 페이지의 이벤트를 기반으로 작동하므로 상위 페이지에서 이러한 이벤트가 발생하면 ScriptManager 컨트롤이 이를 알아야 합니다.
스크립트 및 서비스 참조를 브라우저에 로딩하는 데 가장 중요한 페이지 이벤트는 페이지의 PreRenderComplete 이벤트입니다. 이 이벤트의 처리기는 OnPagePreRenderComplete(그림 11 참조)이며 이는 ScriptManager 컨트롤의 메서드이기도 합니다.
private void OnPagePreRenderComplete(object sender, EventArgs e) 
{
    if (!IsInAsyncPostBack) 
    {
        if (SupportsPartialRendering) 
        {
            IPage.ClientScript.GetPostBackEventReference(
                new PostBackOptions(this, null, null, false, 
                false, false, false, true, null));
        }

        RegisterGlobalizationScriptBlock();
        RegisterScripts();     
        RegisterServices();
    }
    else RegisterScripts();
}

OnPagePreRenderComplete는 페이지의 PreRenderComplete 이벤트가 발생하면 실행되도록 ScriptManager 컨트롤을 사용하여 등록한 모든 스크립트와 서비스(스크립트 컨트롤에 필요한 스크립트, ScriptManagerProxy에서 참조하는 스크립트 등)를 처리하는 역할을 합니다. 페이지가 부분 포스트백 방식으로 처리되지 않을 경우 전역 스크립트 블록이 개발자의 모든 스크립트 및 서비스와 함께 등록됩니다. 반면 부분 포스트백이 적용될 경우 스크립트만 등록됩니다. ScriptManager 컨트롤은 언제든 스크립트를 포함할 수 있는 기능을 제공하기 때문에 스크립트는 부분 및 전체 포스트백에 대해 모두 등록되어야 합니다.
모든 스크립트와 서비스는 이 단계에서 등록됩니다. 이게 어떤 의미일까요? 스크립트나 참조의 등록이 페이지의 출력에 어떻게 반영될까요?
현재는 아직 첫 번째 페이지 요청을 처리하고 있으며 부분 포스트백을 처리하고 있지 않음을 유의하십시오. 때문에 스크립트 등록을 위해 ClientScriptManager를 계속 사용할 수 있습니다. 예를 들어 RegisterScripts는 ScriptManager 컨트롤로 등록된 모든 스크립트 내를 반복하면서 이를 페이지의 기본 ClientScriptManager 인스턴스에 전달합니다. 페이지가 렌더링되면 ClientScriptManager가 호출되고 ASP.NET AJAX 이전의 경우와 마찬가지로 스크립트 참조가 페이지 출력에 추가됩니다.
비동기 포스트백 중에는 그림 11의 else 절 때문에 RegisterScripts도 호출됩니다. 이 메서드는 여전히 ClientScriptManager를 호출하지만 ClientScriptManager는 비동기 포스트백 중에 무엇을 해야 할지 알지 못하므로 아무 일도 발생하지 않습니다. 대신 RegisterScripts가 내부 메서드인 RegisterScriptIncludeInternal을 호출하여 나중에 사용하기 위해 스크립트 참조를 내부 배열에 저장해 둡니다.
웹 서비스 참조는 어떻게 처리될까요? ScriptManager 컨트롤에 웹 서비스 참조를 추가함으로써 스크립트에 대한 참조가 페이지에 추가된다고 설명했습니다. 이 스크립트 참조를 통해 브라우저가 지정된 URL을 요청하게 되며 ASP.NET AJAX 프레임워크는 웹 서비스를 구현하는 클래스 구현을 조사하고 클라이언트 코드에서 사용할 수 있는 프록시 스크립트 클래스를 반환합니다. 브라우저는 자동으로 생성된 이 프록시 클래스를 다운로드하고 웹 서비스 참조로 사용합니다.
자동 생성된 프록시 클래스에 대한 스크립트 참조를 만들기 위해 RegisterScripts는 보유된 모든 웹 서비스 참조 사이를 반복하고 다음 메서드를 호출합니다.
private string GetProxyPath(Control containingControl, bool debug) 
{
    if (debug)
        return GetServicePath(containingControl, true) + 
            RestHandlerFactory.ClientDebugProxyRequestPathInfo;
    else
        return GetServicePath(containingControl, true) + 
            RestHandlerFactory.ClientProxyRequestPathInfo;
}
GetProxyPath에서 생성된 스크립트 참조는 일반적인 스크립트 참조와 동일한 방식으로 페이지에 추가됩니다. 즉 첫 번째 페이지 요청에 대한 ClientScriptManager를 사용하고 참조를 특정한 내부 배열에 넣게 됩니다.
이 내부 배열은 무엇일까요? 실제로 몇 개의 배열이 있습니다. 첫 번째 페이지 요청에 대해 ScriptManager는 스크립트 및 서비스 참조를 페이지에 대한 ClientScriptManager 클래스에 추가하는 기존 방법을 사용한다고 설명했습니다. 하지만 ClientScriptManager를 사용하는 방법은 부분 포스트백에서는 작동하지 않습니다. 따라서 ScriptManager는 대신 다른 방법을 사용해야 하며, 이를 위해 내부 배열이 필요한 것입니다. 부분 포스트백에 대한 응답은 올바르게 구성된, 쉽게 해석할 수 있는 형태의 데이터이므로 클라이언트 프레임워크에서 이를 검사하고 사용할 수 있습니다. ScriptManager 컨트롤의 Render 이벤트가 호출되면 이 이벤트는 다시 다른 클래스 PageRequestManager의 멤버 메서드인 ProcessScriptRegistration을 호출하게 됩니다(그림 12 참조).
private void ProcessScriptRegistration(HtmlTextWriter writer) 
{
    owner.ScriptRegistration.RenderActiveArrayDeclarations(
        updatePanelsToRefresh, writer);
    owner.ScriptRegistration.RenderActiveScripts(
        updatePanelsToRefresh, writer);
    owner.ScriptRegistration.RenderActiveSubmitStatements(
        updatePanelsToRefresh, writer);
    owner.ScriptRegistration.RenderActiveExpandos(
        updatePanelsToRefresh, writer);
    owner.ScriptRegistration.RenderActiveHiddenFields(
        updatePanelsToRefresh, writer);
    owner.ScriptRegistration.RenderActiveScriptDisposes(
        updatePanelsToRefresh, writer);
}

스크립트 참조가 ASP.NET AJAX의 페이지 출력에 렌더링되는 단계가 바로 이 부분입니다. 각 메서드는 Render 단계에서 HtmlTextWriter를 전달받아 필요한 콘텐츠를 페이지에 작성하게 됩니다. RenderActiveScripts와 같은 각 메서드는 각각 미리 채워진 해당 내부 배열을 참조합니다.

ASP.NET AJAX의 AJAX 기능
Fiddler HTTP 디버거 프록시 응용 프로그램(fiddlertool.com/fiddler)을 사용하면 컴퓨터의 Internet Explorer®를 통해 이동하는 모든 웹 트래픽을 추적할 수 있는데, ajax.asp.net의 AJAX 샘플을 실행하고 Fiddler로 그 결과를 살펴보면 부분 포스트백 이벤트를 호출할 때마다 실제 HTTP POST가 발생함을 알 수 있습니다. HTTP POST에는 평범한 HTTP 헤더가 포함되어 있지만 낯선 한 가지 항목도 볼 수 있습니다.
x-microsoftajax: Delta=true
낯선 이 헤더는 바로 키입니다. ScriptManager 컨트롤이 이 헤더를 발견하면 수동적으로 참조를 페이지 출력에 넣는 대신 폼 POST에서 보낸 데이터를 검사하고 클라이언트 스크립트가 해석할 수 있는 형태로 응답을 렌더링하여 클라이언트에 보냅니다.
서비스 및 스크립트 참조를 초기 페이지 출력에 작성함과 동시에 ScriptManager 컨트롤은 클라이언트 쪽 기능을 초기화합니다. 첫 번째로 렌더링을 수행할 때 ScriptManager는 두 개의 시작 스크립트가 ClientScriptManager로 등록되어 있는지 확인하는데, 하나는 런타임에 클라이언트 쪽을 초기화하는 메서드를 호출하며 다른 하나는 전에 설명한 PageRequestManager 클래스의 클라이언트 쪽 버전을 초기화합니다. AJAX를 이해하려면 PageRequestManager를 초기화하는 두 번째 초기화 스크립트가 가장 중요합니다.
이 클라이언트 스크립트는 RenderPageRequestManagerScript라는 메서드 호출을 통해 페이지 출력에 추가됩니다. 이해를 돕기 위해 불필요한 코드를 제외하면, 이 메서드의 일반적인 구조는 다음과 같습니다.
internal void RenderPageRequestManagerScript(HtmlTextWriter writer) 
{
    ...
    writer.Write(_owner.UniqueID);
    ...
    writer.Write(_owner.IPage.Form.ClientID);
    ...
    RenderUpdatePanelIDsFromList(writer, _allUpdatePanels);
    ...
    writer.Write(GetAsyncPostBackControlIDs(true));
    ...
    writer.Write(GetPostBackControlIDs(true));
    ...
}
UpdatePanels, PostBackControl ID 및 AsyncPostBackControl ID가 어떻게 페이지에 쓰여지는지 눈여겨 보십시오. 이는 ASP.NET AJAX 환경에서 각각 중요한 부분을 맡고 있는 컨트롤들입니다. 클라이언트 쪽 PageRequestManager는 ScriptManager를 통해 등록된 모든 컨트롤에서 생성된 모든 이벤트를 추적하는 역할을 하며 RenderPageRequestManagerScript 메서드는 클라이언트에서 작동하는 PageRequestManager를 정확한 대상 컨트롤과 함께 초기화하는 역할을 합니다.
클라이언트에서 포스트백 이벤트가 발생하면 이 이벤트가 RenderPageRequestManagerScript 내에 작성된 스크립트에서 확인된 컨트롤에 의해 발생했는지 PageRequestManager에 의해 확인됩니다. 만약 그럴 경우 PageRequestManager는 포스트백을 취소하고 다시 패키징합니다. 포스트백 이벤트에 의해 새로 패키징된 데이터는 Sys.Net.WebRequest(공개 클래스이므로 클라이언트 쪽 코드 어디서나 사용 가능)라는 클라이언트 클래스를 사용하여 서버로 전송됩니다. x-microsoftajax: Delta=true라는 헤더가 Sys.Net.WebRequest를 통해 서버로 전달되는 POST 요청에 설정됩니다.
서버 쪽에서는 이제 ScriptManager 컨트롤이 인스턴스화되고 페이지의 컨트롤 트리에 로드됩니다. ScriptManager는 서버 쪽 컨트롤이므로 LoadPostData를 통해 폼 POST 내의 데이터를 전송받게 됩니다. LoadPostData는 각각의 컨트롤을 폼 POST를 통해 필터링하여 적절한 정보를 추려내는 ASP.NET의 메서드입니다. 참고로 이 이벤트는 ASP.NET AJAX에서만 사용되는 것이 아니라 표준 이벤트입니다. 그림 10의 이벤트 다이어그램을 보면 페이지의 InitComplete가 발행한 직후 LoadPostData가 실행됨을 알 수 있습니다. LoadPostData 내에서 ScriptManager 컨트롤은 폼 POST를 유발하는 컨트롤을 확인합니다. 여기에는 내부의 UpdatePanel(있을 경우)도 포함됩니다. 포스트백 이벤트를 유발하는 컨트롤이 확인되면 나중에 사용하기 위해 저장됩니다.
지금까지 ScriptManager 컨트롤은 부분 포스트백이 발생했음을 인식하고 이를 유발한 컨트롤을 확인했습니다. 이제 클라이언트로의 응답을 만들 차례입니다. ScriptManager 컨트롤은 호스트 페이지의 기본 Render 메서드를 완전히 덮어쓰고, ASP.NET 페이지의 렌더링 작업을 담당하게 됩니다. 지금까지 ScriptManager 컨트롤은 단순히 ASP.NET AJAX 응용 프로그램의 다양한 설정을 조정하는 역할을 하는 것으로만 보아 왔지만 이제는 부여된 다양한 옵션을 통해 페이지 출력 스트림을 렌더링하기 위한 자체 형식이 완성된 새 페이지 클래스임을 알 수 있습니다.
사실 ScriptManager는 두 개체에 대한 기본 렌더링을 재정의하는 역할을 한다고 볼 수 있습니다. 하나는 Page 자체이며, 다른 하나는 페이지 내의 Web Form입니다. 따라서 ASP.NET 페이지 프레임워크에서 페이지 렌더링을 요청하면 ScriptManager의 자체 내부 구현이 호출되는 것입니다. 어떤 컨트롤이 포스트백을 유발하는지 알고 그에 연관된 정보(포스트백을 유발한 대상이 다른 컨트롤과 함께 UpdatePanel 내에 있는지, 아니면 UpdatePanel에 연결된 다른 곳에 있는지)를 ScriptManager 컨트롤이 확인하게 되면 어떤 하위 컨트롤의 렌더링을 요청해야 하며 어떤 요청은 무시해야 하는지 확인할 수 있게 됩니다. ASP.NET의 Page 클래스는 기본적으로 각 하위 컨트롤을 렌더링하도록 요청하지만 ScriptManager는 필요한 컨트롤만 렌더링하도록 요청합니다.
ScriptManager는 Form 개체의 렌더링을 재정의하는 과정에서 RegisterDataItem 메서드를 통해 등록된 모든 추가 데이터 역시 처리하여 클라이언트로 보냅니다. 따라서 클라이언트에 Form 개체의 렌더링을 요청할 시점에 데이터를 클라이언트로 보낼 준비가 되어 있어야 합니다. 클라이언트로 전송되는 데이터는 원시 형식 또는 JSON(JavaScript Object Notation) 직렬화 형식으로 인코딩됩니다.
마지막으로, 클라이언트 프레임워크는 서버로부터 비동기 응답을 받아 데이터를 해석합니다. ScriptManager 컨트롤은 모든 컨트롤 ID와 새 태그를 응답으로 묶어 전송하므로 클라이언트는 브라우저의 문서 개체 모델을 사용하여 스크립팅 작업을 수행하고 페이지 내용을 업데이트하기만 하면 됩니다. 이러한 모든 과정은 비동기 방식으로 수행되므로 브라우저는 신속하고 매끄럽게 업데이트되며 웹 페이지 사용자 역시 뛰어난 사용 환경을 누릴 수 있습니다.

스크립트의 실행
ASP.NET AJAX는 강력한 기술입니다. 웹 응용 프로그램에 ASP.NET AJAX의 다양한 기능을 활용하기 위해서는 이 기사에서 설명한 것처럼 ScriptManager 컨트롤을 사용해야 합니다.
ScriptManager 컨트롤이 ASP.NET AJAX 구현의 많은 세부 사항을 처리해 줄 것입니다. 지금까지 기사를 읽으면서 UpdatePanel과 같은 컨트롤의 기본 동작이 아닌 다른 기능이 필요한 경우 계속해서 ScriptManager가 해결책으로 등장했음을 보았을 것입니다. 스크립팅 기능과 AJAX 이외에도 ScriptManager 컨트롤은 인증 및 개인 설정과 같은 고급 기능도 지원합니다.
스크립트와 서비스는 ScriptManager 컨트롤과 페이지의 PreRenderComplete 이벤트를 사용하여 등록되어야 합니다. 전체 또는 부분 포스트백 중에 페이지에 스크립트 참조를 추가할 수 있습니다. 다른 개체 역시 스크립트가 등록될 때 자체 스크립트 및 서비스 참조를 ScriptManager에 전달하도록 요청 받습니다.
마지막으로, 호스트 페이지의 기본 구현을 재정의하는 방식으로 ASP.NET AJAX가 클라이언트에서 구현됩니다. 이때부터 ScriptManager가 페이지 렌더링 주기를 책임지며, 클라이언트에서 쉽게 해석할 수 있는 형태로 응답을 전송하고 브라우저에서는 이를 사용하여 필요한 요소를 업데이트합니다. 기본 페이지 렌더링을 재정의함으로써, ScriptManager를 통해 등록된 모든 데이터와 함께 올바른 컨트롤이 특별한 형식으로 클라이언트에서 렌더링될 수 있습니다.

Ben Rush는 ASP.NET 기술을 전문으로 하는 중서부 지역의 Microsoft .NET 컨설턴트입니다. Ben에 대해 더 자세히 알고 싶다면 ben-rush.net/blog를 방문해 보십시오.


출 처 : http://blog.naver.com/ecaface?Redirect=Log&logNo=140046678251

안녕하세요? 웹지니입니다.

 

페이지 메서드를 마지막으로 서버 측 라이브러리에 대한 소개를 마치면서 잠시, 아주 잠시 (ㅡㅡ;;) 중단되었던 ASP.NET AJAX가 궁금해? 강좌를 다시 이어가고 있습니다.

 

이번 강좌부터는 ASP.NET AJAX의 클라이언트 측 라이브러리인 Microsoft AJAX Library에 대해 소개할 예정입니다. 우선 예상 목차를 잡아보자면...

 

1. JSON: Microsoft AJAX Library를 이해하기 위한 필수 코스

2. Microsoft AJAX Library의 특징과 자바스크립트 확장

3. Microsoft AJAX Library의 기본 네임스페이스와 클래스 소개 1

4. Microsoft AJAX Library의 기본 네임스페이스와 클래스 소개 2

5. Microsoft AJAX Library를 활용한 객체지향 자바스크립트 프로그래밍 1

6. Microsoft AJAX Library를 활용한 객체지향 자바스크립트 프로그래밍 2

7. Microsoft AJAX Library를 활용한 비동기 네트워크 프로그래밍 1

8. Microsoft AJAX Library를 활용한 비동기 네트워크 프로그래밍 2

 

이와 같이 대략적인 목차를 설정해 봤습니다. 물론 뭐 저대로 강좌가 진행되면 얼마나 좋겠습니까마는 강좌를 진행해 가는 과정에서 다소나마 목차의 변동이 있을 수 있다는 사실을 미리 밝혀 드립니다. ^^;;

 

JSON: Microsoft AJAX Library를 이해하기 위한 필수 코스

 

여러분도 이미 아시다시피 대부분의 Ajax 라이브러리들은 아직 우리에게 익숙하지 않은 이상한(?) 형태의 자바스크립트 코드로 구현되어 있는 경우가 많습니다. 그 이상한 형태의 코드가 바로 JSON 표현식이라는 것은 이제 많은 개발자들이 인지하고 있을 것입니다.

 

이번 강좌에서는 Microsoft AJAX Library를 이해하기 위한 필수적인 지식인 JSON 표현식에 대해 알아보는 시간을 가져보겠습니다.

 

JSON, 영화 13일의 금요일의 그 머더라(Murderer)?

 

조금만 움직여도 땀이 줄줄 흐르는 이맘때쯤이면 TV에서 너도나도 공포 영화를 내보내곤 합니다. 영화 "13일의 금요일"에 보면 "제이슨"이라는 이름의 살인마가 나오지요. 나름 애처로운 과거를 간직한 이 살인마의 이름과 발음상 동일한 JSON, 왠지 이름만으로는 절대 친하고 싶지 않은 녀석이지만 Ajax가 판을 치는 세대를 살아가는 우리들은 어쩔 수 없이 친해져야 하는 녀석이기도 합니다.

 

JSON은 Javascript Object Notation의 약자로 한글로 풀어보면 "자바스크립트 객체 표현식" 정도로 해석할 수 있겠습니다. 이름에서 알 수 있듯이 자바스크립트 객체를 표현하기 위한 하나의 문법인 셈이지요. JSON 표현식은 Duglas Crockford라는 개발자가 넷스케이프에 제안하여 채택된 문법으로 사실은 매우 오래전부터 자바스크립트에서 제공되던 표현식입니다. Ajax 덕분에 뒤늦게 빛을 보게 된 셈이지요.

 

일반적으로 여러분은 지금까지 자바스크립트에서 객체를 구현하기 위해 아래와 유사한 코드를 사용했을 것입니다.

 

예제 1: 전통적인 자바스크립트 객체 표현식

function JsObject() {

    this.property1 = 0;

    this.property2 = "Hello!";

 

    this.method1 = function( ) {
    }

 

    this.method2 = function( ) {

    }
}

 

위의 예제 코드는 여러분에게 이미 상당히 익숙하지요? 물론 자바스크립트를 단지 함수 수준에서만 활용한 정도에 그친 개발자들도 있기 때문에 위의 예제 코드마저 생소한 분이 계실지도 모르겠습니다만 어쨌든 위의 예제는 property1과 property2라는 필드와 method1, method2라는 메서드를 가진 JsObject라는 이름의 객체를 정의하는 코드입니다.

 

위의 예제에서 구현된 객체를 사용하는 코드는 어떤가요? 대략 아래와 같을 것입니다.

 

var myObj = new JsObject();

alert(myObj.property1);

 

예, 대략 이와 같이 사용했었지요. 위의 예제가 무슨 문제가 있느냐? 그렇지는 않습니다. 다만 JSON 표현식을 이용하면 조금 더 간단하게 이와 동일한 객체를 표현할 수 있다는 것이지요. 그렇다면 JSON 표현식으로는 이 객체를 어떻게 표현하는지 한 번 살펴볼까요?

 

예제 2: JSON 객체 표현식

var JsObject = {

    property1: 0,

    property2: "Hello",

    method1: function( ) {

    },

    method2: function( ) {

    }

}

 

어떤가요? 앞서 예제 1의 코드에 비하면 조금, 아~~~주 조금 간단해졌지요? 하지만 이 때문에 JSON 표현식을 "별 것 아닌" 것으로 치부해 버리면 안됩니다. 왜냐하면 JSON 표현식은 많은 장점을 가지고 있기 때문이지요.

 

JSON 표현식을 굳이 써야 하는 이유는 뭔가요?

 

언뜻 보기에 JSON 표현식을 써야 하는 이유를 잘 알 수가 없습니다. 대체 왜 JSON 표현식을 이해하고 사용해야 할까요? 또 왜 많은 Ajax 라이브러리들이 JSON 표현식을 고집할까요? (쓸데없이 말야 쯧...ㅡㅡ;;) 제 나름대로 그 이유를 아래와 같이 정리해 봤습니다.

 

1. XML에 비해 간편하게 데이터 교환이 가능하다.

Ajax가 Asynchronous Javascript And Xml의 약자임은 이제 다들 알고 계실 것입니다. 여기서 XML의 역할이 바로 데이터 교환 수단으로서의 역할이었지요. Jess James Garett의 에세이를 보시면 아시겠지만 Ajax 웹 응용 프로그램에서 서버와 클라이언트 사이의 데이터 교환을 XML이 담당하고 있습니다. 그렇다면 대략 아래와 같은 형식이겠군요.

 

예제 3: Ajax에서 데이터 교환 수단으로서의 XML의 활용 예시

<user>

    <id>webgenie</id>

    <age>100</age>

    <gender>M</gender>

</user>

그러면 이와 동일한 표현을 JSON 형식으로 바꿔보겠습니다.

 

var JsonObject = {

    id: "webgenie",

    age: 100,

    gender: "M"

}

 

이와 같이 표현할 수 있겠네요. 자, 어떤 차이가 있을까요? 우선 눈으로 확인하기에도 JSON 표현식을 위한 문자열의 크기가 훨씬 적다는 것을 알 수 있습니다. 따라서 서버 측의 응답으로 XML을 사용하는 것보다 JSON 표현식을 사용하는 것이 네트워크 대역폭 측면에서 조금 더 유리하겠지요? 예제의 JsonObject 객체의 멤버에 액세스하는 방법은 아래와 같습니다.

 

alert(JsonObject.id);                   // "webgenie"가 출력됩니다.

 

2. XML에 비해 사용이 편리하다.

앞서 1번 항목의 연장선상에서 생각해 보면 서버의 응답으로 XML을 사용하는 것보다는 JSON 표현식을 사용하는 것이 더 편리할 것입니다. 왜 그런지 살펴볼까요? 우선 XML을 응답 데이터 로 전달하면 클라이언트 측, 즉 자바스크립트에서는 XMLHttpRequest 객체의 responseXml 속성을 이용하여 IXMLDomDocument 인터페이스를 조작하는 코드를 작성해야 합니다.

 

반면 JSON 표현식을 사용할 경우 아래와 같이 responseText 속성에 전달된 응답 데이터를 eval 함수를 이용하여 간단하게 자바스크립트 객체로 변환할 수 있습니다.

 

var user = eval("(" + xmlHttpReqObject.responseText + ")");

 

이렇게 하면 아래와 같이 user 객체를 사용할 수 있습니다.

 

alert(user.id);                    // "webgenie"가 출력됩니다.

 

언뜻 보기에도 상당히 쉬워 보입니다. 이 외에도 몇 가지 장점이 있지만 아마도 가장 큰 장점은 이 두 가지가 아닌가 생각이 됩니다. 그러면 JSON 표현식에 대해 본격적으로 알아볼까요?

 

JSON 표현식 살펴보기

 

앞서 살펴본 것과 같이 JSON 표현식은 중괄호( {와 } )로 객체를 표현하며 콤마를 이용하여 멤버를 구분합니다. 또한 멤버와 값 사이는 콜론(:)으로 구분합니다. 즉 대략 아래와 같은 형식을 가집니다.

 

{ member1: value1 [, member2: value2 [, member3: value3]]] }

 

물론 앞서 예제에서 볼 수 있듯이 멤버는 일반적인 자바스크립트의 내장 객체 (Number, String 등) 뿐만 아니라 함수도 멤버가 될 수 있습니다.

 

{

    function1: function() {

    },

 

    function2: function(param1) {

    }

}

 

당연한 이야기겠지만 자바스크립트의 내장 객체를 멤버로 가질 수 있으므로 배열 역시 JSON 객체의 멤버가 될 수 있습니다.

 

{

    numericArrayMember: [1, 2, 3],

    stringArrayMember: ["1", "2", "3"]

}

 

그렇다면 특정 객체의 배열도 가능할까요? 물론 가능합니다.

 

{

    objectArrayMember: [

         { prop1: value1 },

         { prop1: value2 },

         { prop1: value3 }

    ],

    dateMember: new Date()

}

 

예제에서 보듯이 객체의 배열은 물론 new 연산자를 이용하여 새로운 객체의 인스턴스를 멤버에 할당할 수도 있습니다. 이상의 내용으로 미루어 볼 때 JSON 객체는 자바스크립트에서 사용 가능한 모든 객체를 간단하게 하나의 객체로 그룹화할 수 있다는 장점이 있습니다. 또한 이를 잘 활용한다면 데이터베이스가 리턴한 결과 데이터 셋을 하나의 JSON 객체로 표현할 수도 있습니다.

 

지금까지 JSON 표현식에 대해 알아보았습니다. 언급한 내용이 그다지 많지는 않았지만 사실 그만큼 JSON 표현식이 쉽게 사용할 수 있는 것이기에 이번 강좌의 내용만으로도 개략적인 감을 잡는데는 큰 무리가 없을 것 같습니다.

 

다음 강좌에서는 Microsoft AJAX Library의 특징에 대해 알아보고 기본 자바스크립트 객체들을 어떻게 확장하고 있는지 살펴보도록 하겠습니다.

 

참고 자료

 

JSON Official Website: http://www.json.org


▣  ASP.net ajax updatepanel - .NET/ASP.NET - 2011. 6. 14. 20:20
출처 : http://blog.naver.com/ecaface?Redirect=Log&logNo=140046678125

작성자: 웹지니™

작성일: 2006년 12월 26일

적용범위: ASP.NET AJAX 1.0 RC

예제 다운로드: AJAXEnabledWebSite1.zip (6KB)

 

안녕하세요? 웹지니입니다.

 

25일 크리스마스 잘 보내셨나요? 전 그날 당직 근무가 걸려서 회사에 출근했더니 이번 한 주가 너어~무 길게 느껴지네요 쩝...ㅡㅡ;;

 

각설하고, 웹지니가 야심차게 준비한 새 강좌 "ASP.NET AJAX가 궁금해?" 그 두 번째 시간!

오늘은 UpdatePanel 컨트롤에 대해서 알아보도록 하겠습니다.

 

1. ASP.NET AJAX의 핵심 - UpdatePanel 컨트롤

 

오늘의 주인공은 ASP.NET AJAX에 조금이라도 관심이 있으신 분들은 너도나도 들어보셨을 법한 UpdatePanel 컨트롤입니다. UpdatePanel 컨트롤의 역할은 자신이 보여주는 컨텐츠 영역을 AJAX를 이용해서 화면 깜박임 없이 업데이트 시켜주는 것입니다.

 

즉, 웹 폼 페이지에서 원하는 영역에 AJAX 스타일을 적용하는 컨트롤이라고 이해하시면 될 듯 하고요, 이런 역할을 하다보니 당연지사 ASP.NET AJAX에서도 중요한 위치를 차지하는 서버 측 컨트롤입니다.

 

UpdatePanel 컨트롤을 사용하는 방법은 매우 간단합니다. 아래와 같이 AJAX 스타일로 깜박임 없이 업데이트 되어야 하는 영역을 UpdatePanel 컨트롤로 둘러싸 주기만 하면 됩니다.

 

<asp:UpdatePanel ID="up1" runat="server">
    <ContentTemplate>

        <asp:GridView ID="gridView1" runat="server"/>

    </ContentTemplate>

</asp:UpdatePanel>

 

이와 같이 GridView 컨트롤을 UpdatePanel 컨트롤의 <ContentTemplaet> 템플릿으로 한 번 감싸주기만 하면 GridView 상에서 여러분이 어떤 작업을 하더라도 이 GridView는 AJAX 스타일이 적용되어 라운드 트립 없이 업데이트가 가능하게 됩니다.

 

2. UpdatePanel 컨트롤을 이용한 심플한 예제 만들기

 

자, 그럼 UpdatePanel 컨트롤 예제를 한 번 만들어 보도록 하겠습니다. 앞서 강좌에서 ASP.NET AJAX를 이미 다운로드 해서 설치했다면 여러분의 Visual Studio 2005의 새 웹사이트 대화 상자에는 이미 아래 그림과 같이 AJAX-Enabled Web Site라는 프로젝트 템플릿이 존재할 것입니다.

 

그림 1: Visual Studio 2005의 새 웹사이트 대화 상자 (그림을 클릭하면 크게 보입니다.)

 

새 프로젝트를 생성하면 기본적으로 Default.aspx 페이지가 열리지요? 이 페이지는 아래와 같은 소스를 가지고 있을 것입니다.

 

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
        <div>
        </div>
    </form>
</body>
</html>

여기서 눈여겨 보실 부분은 굵게 표시된 <asp:ScriptManager> 컨트롤입니다. 이 컨트롤은 ASP.NET 웹 폼 페이지가 ASP.NET AJAX의 기능을 활용하기 위해 필수적으로 필요한 자바스크립트 파일을 관리하는 컨트롤입니다. 자세한 얘기는 다음 강좌에서 진행하도록 하고 오늘은 일단 이런 넘이 꼭! 있어야 한다는 것만 알아두고 패~~~~~~쓰!!

 

이제 웹 폼 디자이너 뷰로 전환하고 도구 상자를 보면 아래 그림과 같이 도구 상자에 이미 AJAX Extensions라는 탭이 추가되어 있는 것을 보실 수 있습니다.

 

그림 2: Visual Studio 2005의 도구 상자

 

그림에 UpdatePanel 컨트롤을 드래그해서 웹 폼 디자이너에 올려두시면 아래와 같이 Default.aspx 파일의 소스가 변경될 것입니다.

 

<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
    </asp:UpdatePanel>
</div>

 

이제 이 UpdatePanel 컨트롤 안에 아래와 같이 Label 컨트롤과 Button 컨트롤을 배치해 볼까요?

 

<asp:UpdatePanel ID="UpdatePanel1" runat="server">

    <ContentTemplate>

        <asp:Label ID="lbCurrentTime" runat="Server" />

        <asp:Button ID="button1" runat="server" Text="Show Current Time /w AJAX"

        onclick="button1_Click" />

    </ContentTemplate>

</asp:UpdatePanel>

 

<asp:Button ID="button2" runat="server" Text="Show Current Time without AJAX"

onclick="button2_Click" />

 

예제에서 보시면 UpdatePanel 컨트롤의 ContentTemplate 내에 Label 컨트롤과 Button 컨트롤이 각각 배치되어 있고 UpdatePanel 컨트롤의 바깥에 Button 컨트롤이 배치되어 있습니다. 이 두 개의 Button 컨트롤은 포스트 백을 발생시키는 컨트롤이 UpdatePanel 컨트롤 내부에 위치할 때와 그렇지 않을 때의 동작을 구분하기 위해 배치한 것입니다. 이제 Default.aspx.cs 파일을 열고 아래와 같이 이벤트 핸들러 메서드를 작성합니다.

 

protected void button1_Click(object sender, EventArgs e) {
 this.lbCurrentTime.Text = DateTime.Now.ToString();
}

protected void button2_Click(object sender, EventArgs e) {
 this.lbCurrentTime.Text = DateTime.Now.ToString();
}

 

보시다시피 두 메서드는 모두 Label 컨트롤에 현재 시간을 표시하는 코드를 실행합니다. 이제 페이지를 실행해 볼까요? Visual Studio 2005에서 F5키를 누르거나 Ctrl + F5를 누르면 아래 그림과 같이 웹브라우저가 실행됩니다.

 

그림 3: 예제를 실행한 모습

 

그림과 같이 예제가 실행되면 두 개의 버튼을 차례대로 클릭해 보시기 바랍니다. 당연히 짐작하신 대로 위쪽의 버튼을 클릭하면 화면 깜박임 없이 Label 컨트롤에 현재 날짜가 표시되지만 아래쪽의 버튼은 라운드 트립을 발생시키게 됩니다.

 

그렇다면 여기서 알 수 있는 사실 하나! ASP.NET에서는 UpdatePanel 컨트롤만 잘 쓰면 AJAX 스타일의 웹 응용 프로그램을 쉽게 만들 수 있다!! 단, 포스트 백을 발생시키는 컨트롤도 UpdatePanel 컨트롤 안에 들어 있어야 한다는거~

 

3. UpdatePanel 컨트롤의 트리거

 

자, 뭔가 좀 이상합니다. 솔직히 웹 폼 페이지 안에 있는 어떤 버튼을 클릭해도 AJAX 스타일로 동작해 줘야 맞는거 아닌가요? 꼭 UpdatePanel 컨트롤 안에 있는 컨트롤을 클릭할 때만 AJAX 스타일이 적용된다니 이건 아니자나~ 이건 아니자나~ T^T

 

이 문제를 해결하기 위해서 우리는 UpdatePanel 컨트롤의 트리거에 대해 알아야 합니다. ASP.NET AJAX는 두 가지 형식의 UpdatePanel 컨트롤 트리거를 제공하는데 그 사용법은 아래와 같습니다.

 

<asp:UpdatePanel ID="up1" runat="server">

    <Triggers>

        <asp:AsyncPostBackTrigger ControlID="컨트롤ID" EventName="이벤트명"/>

        <asp:PostBackTrigger ControlID="컨트롤ID" />

    </Triggers>

</asp:UpdatePanel>

 

바로 AsyncPostBackTrigger와 PostBackTrigger입니다. 이 두 가지 트리거의 차이점은 아래와 같습니다.

 

AsyncPostBackTrigger: UpdatePanel 컨트롤을 프스트 백 없이 비동기식으로 업데이트할 컨트롤과 이벤트를 지정합니다. 

 

PostBackTrigger: UpdatePanel 컨트롤을 기존과 마찬가지로 포스트 백을 이용하여 업데이트할 컨트롤을 지정합니다.

 

이상에서 알 수 있듯이 AsyncPostBackTrigger와 PostBackTrigger는 각각 비동기식, 동기식 업데이트를 수행할 컨트롤을 지정하도록 되어 있습니다. 이들을 활용하면 UpdatePanel 컨트롤을 업데이트 할 컨트롤을 지정할 수 있음은 물론 UpdatePanel 컨트롤을 동기식으로 업데이트할 것인지, 아니면 비동기식으로 업데이트할 것인지도 결정할 수 있습니다.

 

이제 예제를 만들어 봅시다! 먼저 새로운 웹 폼 페이지를 추가하고 이름은 Default2.aspx라고 하겠습니다. 그리고 앞서 만들었던 Default.aspx 페이지의 소스와 Default.aspx.cs 소스를 모두 가져와 Default2.aspx와 Default2.aspx.cs 파일에 복사해 넣고 아래와 같이 Default2.aspx의 UpdatePanel 컨트롤의 소스만 살짝 수정합니다.

 

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <asp:Label ID="lbCurrentTime" runat="server" />
        <asp:Button ID="button1" runat="server" Text="Show Current Time /w AJAX"

        onclick="button1_Click" />
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="button2" EventName="Click" />
    </Triggers>
</asp:UpdatePanel>
<asp:Button ID="button2" runat="server" Text="Show Current Time without AJAX"
onclick="button2_Click" />

 

앞서 Default.aspx 페이지의 소스 중 추가된 부분은 굵게 표시된 부분 뿐입니다. 이 코드를 보면 AsyncPostBackTrigger를 등록하는데 ControlID는 button2이고 EventName은 Click으로 지정하였습니다. 즉, 맨 아래에 추가된 button2 버튼에서 Click 이벤트가 발생하면 UpdatePanel 컨트롤을 업데이트하라는 의미가 됩니다. 이렇게 해서 예제를 실행해보면 그 결과는 아래 그림과 같습니다.

 

그림 4: 예제2를 실행한 모습

 

앞서 예제와 차이점이 무엇일까요? 이제는 둘 중 어떤 버튼을 클릭해도 UpdatePanel 컨트롤에 포함된 Label 컨트롤이 화면 깜박임 없이 AJAX 스타일로 업데이트가 됩니다!!!

 

4. ChildrenAsTriggers 속성

 

앞서 살펴본 AsycPostBackTrigger 외에 UpdatePanel 컨트롤은 PostBackTrigger 트리거를 지원합니다. 이것은 UpdatePanel 내부에 위치한 컨트롤들 중 UpdatePanel을 업데이트 시켜야 하는 컨트롤을 지정하기 위한 것인데 사실 이 트리거는 UpdatePanel 컨트롤의 ChildrenAsTriggers 속성 값과 연관이 있습니다.

 

ChildrenAsTriggers 속성은 UpdatePanel 컨트롤 내부의 자식 컨트롤들에서 어떤 이벤트가 발생하면 UpdatePanel을 업데이트 할 것인지를 지정하는 속성으로 기본값이 true입니다. 따라서 UpdatePanel 내부의 어떤 컨트롤을 클릭해도 UpdatePanel이 업데이트 되게 됩니다.

 

즉, 다시 말하면 ChildrenAsTriggers 속성을 false로 지정하고 UpdatePanel 내의 일부 컨트롤을 클릭할 경우에만 UpdatePanel 컨트롤이 Update되어야 할 경우 PostBackTrigger 트리거를 이용해서 어떤 컨트롤이 UpdatePanel 컨트롤을 업데이트 할 것인지를 지정하여 사용할 수 있는 것입니다.

 

그리고 가장 중요한 사실 하나, UpdatePanel 컨트롤은 ScriptManager 컨트롤의 EnablePartialRendering 속성이 반드시 true로 설정되어 있어야만 AJAX 스타일로 업데이트 됩니다. 하지만 EnablePartialRendering 속성은 이미 기본값이 true라는거~

 

다음 강좌에서는 UpdatePanel 컨트롤의 나머지 속성과 메서드에 대한 이야기들을 풀어나가 보겠습니다. 그럼 다음 시간에 또 만나욧~




articles
recent replies
recent trackbacks
notice
Admin : New post