ASP.NET AJAX : Microsoft AJAX Library의 핵심 컴포넌트
요즘 창스는 리소스가 많이 딸린다...해서 이것 저것 공부하고 있는 중이다. 평소 바쁘다는 핑계로 대충 넘어가려 했던 많은 것들....아...스바..그때 제대로 해 둘걸...
SI 프로젝트를 하다면 보면 제안서를 써야 하는 일이 생긴다. 더군다나 우리 회사처럼 작은 회사는 엔지니어가 곧 마케터이자 세일즈맨이자 관리자이자 개발자이자 아키텍트가 되야 한다.1인 5역 정도 되는듯 하다..여튼 제안서 쓰는 일은 참으로 고된일 중 하나이고, 엔지니어로서 부담스런 작업이 아니라 할 수 없다. 제안서 작업은 전문 지식은 기본이고, 때로 많은 창의력을 필요로하고, 미적 감각도 어느정도 갖추어야 한다. 그래야 뽀대나는 제안서로 프로젝트를 후려 잡을 수 있는 것이다...물론 최종적인 선택의 가장 중요한 factor는 견적가(돈)이므로 적당히 Pre-Self-Discount(PSD) 전략으로 고객을 혹하게 만들어야 할 것이다.(PSD? 고급 마케팅 전략 용어냐고? 아이다...걍 내가 만든 말이다..신경끄시라)
여튼, 이번에 제안서 쓰면서 디자인 패턴과 여러가지 개발 방법(기법)에 대해 다시금 정리할 필요가 있다고 생각되어, 요즘 책을 들고 있다...분명히 예전에 공부했던 건데..기억이 안난다..난 아마도 IQ가 낮은 넘인가보다...(두자리는 아니다..absolutely..-_-!!)
머가 또 說이 길다...AJAX 정리하고 난 뒤에 요즘 뜨는(?) MVC와 JQUERY에 대해서도 정리질 함 하련다..아..참 이번 글 쫌 길다..맘 단디 묵기 바란다..
Microsoft AJAX Library 는 아래 그림과 같은 컴포넌트로서 구성된다. 논리적인 3 개의 계층을 가진다. 가장 아래의 JavaScript 확장 계층은 이전 글에서 설명이 되었다.
여기서는 UI를 관련한 Sys.UI 와 핵심 클래스들에 대해 알아볼 것이다.
한가지 짚고 넘어갈 내용이 있는데, Microsoft AJAX Library에서 컴포넌트(Component)란 UI가 없는 재사용 가능한 객체를 의미하고 UI가 있는 재사용 가능한 객체를 컨트롤(Control)이라 칭한다. 이들은 각각 Sys.Component, Sys.UI.Control을 기본(Base) 클래스로부터 상속된다. Sys.UI.Behavior를 기본 클래스로 하는 동작(Behavior)라는 구성요소도 존재하는데 이들은 AJAX 동작을 정의하는 용도로 사용되고, 여기서 동작이란 연결된 DOM 요소의 기능을 확장하기 위한 구성 요소 정도로 이해할 수 있다. 즉 Behavior를 작성하여 우리는 기존 DOM 요소의 기능을 확장해 나갈 수 있다.

핵심 클래스들이 담당하는 역할은 아래와 같이 정리가 된다.
○ Sys : 기본 런타임 클래스들, Application 객체
○ Sys.Net : 네트워크 계층에 속하는 클래스들
○ Sys.UI : DOM 과 UI 관련 구성요소에 대한 작업을 위한 클래스들
○ Sys.Services : 프로파일, 멤버십, 인증 서비스와 같은 ASP.NET 서비스에 접근하기 위한 클래스들
○ Sys.Serialization : JSON 직렬화를 위한 클래스들
○ Sys.WebForms : 부분 페이지 렌더링에 관련된 클래스들
■ Sys.Application 객체
핵심이 되는 이 응용 프로그램 객체로서 ASP.NET의 서버 측 System.Web.UI.Page 객체와 같은 역할을 담당한다. Page 객체가 서버 측에서 페이지의 라이프 사이클을 관리하는 것과 같이 Sys.Application 객체는 클라이언트 측 페이지의 라이프 사이클을 관리한다. 따라서 이 응용 프로그램(Application) 객체를 곧 클라이언트 측 페이지에 해당하는 객체로 이해할 수 있다.
이 객체는 아래의 두 가지 중요한 역할을 담당한다.
- 페이지 컴포넌트에 대한 접근을 제공
- 외부 스크립트 파일들을 로드


이 객체는 페이지가 로드될 때 마다 생성되며, 페이지의 수명 동안 유지된다. pageInit, pageLoad 및 pageUnload와 같은 클라이언트 페이지 수명 주기 이벤트를 발생시키고, 등록된 컴포넌트의 추가/삭제를 관리한다. 참고로 이 객체는 Sys._Application 클래스의 단일 인스턴스이고, Sys._Application은 System.Component의 자식 클래스이다.
□ Sys.Application의 메서드
□ Sys.Application의 이벤트
이 이벤트는 곧 페이지의 이벤트 이며 페이지의 초기화(init) --> 로드(load) --> 언로드(unload) 시 마다 아래의 이벤트가 발생한다.
□ Sys.Application 객체 이벤트에 대한 핸들러 함수를 등록하는 방법★ [Tip] 이벤트를 등록하거나 제거할때는 add_이벤트명, remove_이벤트명의 형식을 사용한다.
아래의 코드는 pageInit 이라는 함수를 init 이벤트에 대한 핸들러로서 등록하는 코드이다. 같은 방식을 load, unload 이벤트에 대한 핸들러를 등록할 수 있다.
Sys.Application.add_init(pageInit);
function pageInit()
{
alert("Entered the Init stage!");
}
사실 위의 코드처럼 별도로 등록하지 않더라도 pageInit(), pageLoad(), pageUnload()라는 이름의 핸들러로서 기본적으로 등록된다. 다른 이름의 함수를 핸들러로 등록하려면 명시적으로 등록해야 한다.
□ 클라이언트 코드 실행을 시작하는 가장 적당한 위치는 window.load가 아닌 pageLoad
Microsoft Ajax Library로 작업할 때, 클라이언트 코드를 실행하는 가장 적절한 위치는 pageLoad 함수(이벤트 핸들러)이다. 반면 window.load 이벤트의 핸들러 상에서 클라이언트 코드를 실행하면, 런타임 초기화가 수행중인 상태이므로 안전하지 않을 수 있다. 따라서 런타임 초기화가 완전하게 완료되어 ScriptManager 컨트롤에 의해 추가된 모든 스크립트 파일이 로드 되었으며, 클라이언트 컴포넌트가 모드 생성되었고 초기화 된 후에 발생하는 Sys.Application.load 이벤트에 대한 핸들러(pageLoad 함수) 상에서 코드를 실행하는 것이 가장 안전하고 적절하다.
■ System.Net.WebRequest 클래스
내부적으로 XMLHttpRequest 객체를 이용해 HTTP 요청을 관리하는 클래스이다. 이 클래스의 객체를 생성하여 직접 비동기 HTTP 요청을 전송할 수 있다.
보통 페이지 메서드나 웹 서비스 호출을 위해서 이 클래스를 직접 사용하지는 않고, 라이브러리 내에 생성된 프록시 클래스를 활용하는 것이 일반적이다.
이후의 글에서 웹 서비스 및 웹 메서드 호출 시에 다시 언급될 것이다.
아래는 간단한 사용 예시이다.
function pageLoad(sender, e) {
// Instantiate the WebRequest object.
var wRequest = new Sys.Net.WebRequest();
// Set the request Url.
wRequest.set_url("Echo.aspx");
// Set the request verb.
wRequest.set_httpVerb("POST");
var body = "Message=Hello! Do you hear me?"
wRequest.set_body(body);
// Set the web request completed event handler,
// for processing return data.
wRequest.add_completed(OnWebRequestCompleted);
wRequest.invoke();
}
// This the handler for the Web request completed event
// that is used to display return data.
function OnWebRequestCompleted(executor, eventArgs)
{
if(executor.get_responseAvailable()) {
alert(executor.get_responseData());
}
}
★ [Tip] 속성에 값을 설정하거나 읽어올때는 get_속성명 혹은 set_속성명의 형식을 사용한다.
[서버 측 호출 페이지]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Echo : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.Write("hello" + Environment.NewLine);
Response.Write(Request.Form.ToString());
Response.End();
}
}
□ Sys.Net.WebRequest 의 멤버(속성 및 메서드)
□ Sys.Net.XMLHttpExecutor의 멤버(속성 및 메서드)
요청 완료에 대한 콜백 함수로 넘겨지는 executor 매개변수의 타입은 Sys.Net.XMLHttpExecutor 이며, 이 타입에는 아래와 같은 멤버가 존재한다.
Sys.Net.WebRequest의 경우 실제로 네트워크 요청을 수행하는 "실행자"는 Sys.Net.XmlHttpExecutor 이다. 즉 wRequest.invoke(); 가 실행되면 내부적으로 XmlHttpExecutor의 Sys.Net.XmlHttpExecutor.executeRequest()가 호출된다는 의미이다. 곰은 재주가 부린다는 말의 곰이 바로 Sys.Net.XmlHttpExecutor 되겠다.
■ Sys.WebForms.PageRequestManager 클래스
Sys.WebForms 네임스페이스는 부분 페이지 렌더링에 관련된 클래스를 포함한다고 언급하였다. 그 중에서 가장 핵심이 되는 클래스가
PageRequestManager 클래스이며, 이 클래스가 부분 페이지 렌더링을 관리한다. 서버측 컨트롤인 UpdatePanel 컨트롤이 제공하는 부분 페이지 렌더링은 사실 이 클래스가 작동하여 얻어지는 결과인 것이다. 즉 이놈이 "곰" 되겠다.
□ Sys.WebForms.PageRequestManager 의 멤버
□ Sys.WebForms.PageRequestManager 이벤트 발생 순서
이 클래스의 이벤트 발생 순서에 대한 그림이다. UpdatePanel을 이용한 부분 페이지 갱신이 일어날 때 어떤 이벤트가 어떤 순서로 클라이언트 상에서 발생하는지 파악해 두면 후에 문제해결에 많은 도움을 줄 수 있다.

■ Sys.UI.DomElement 클래스
Sys.UI는 사용자 UI에 관련된 클래스들을 포함하고 있다고 이야기 한 바 있다.
이 클래스는 기본 DOM 요소(element)를 나타내며, DOM 요소를 확인하고 조작하기 위한 여러 메서드와 속성을 제공한다.
□ Sys.UI.DomElement의 멤버
DOM 요소를 가져와 CSS 스타일을 추가/제거하거나 요소의 위치를 가져오거나 설정하는 등의 작업에 사용할 수 있다.■ Sys.UI.DomEvent 클래스
DOM 요소에 이벤트 핸들러(처리기)를 하나 또는 그 이상 추가하거나 제거하는 기능을 제공하고, 또한 이벤트와 연결된 속성을 조회할 수 있도록 제공한다.
이벤트와 연결된 속성이란 이벤트 발생 시 Alt 키의 상태나 마우스 버턴의 상태 혹은 마우스 포인터의 x,y 좌표와 같은 값을 말한다.
□ Sys.UI.DomEvent 의 멤버
이벤트 핸들러를 추가/제거하는 메서드들을 별칭을 가지고 있는데, 이에 대한 목록은 이글의 뒷부분에서 따로 정리를 하도록 한다.
■ Sys.Debug 클래스
이름에서 알 수 있듯이 디버깅 및 추적(Tracing) 처리에 관련된 클래스이다. 그 활용에 대해서는 다른 글을 통해 소개할 예정이므로 간단하게 소개만 하도록 한다.
□ Sys.Debug의 멤버
■ 주요한 핵심 클래스 메서드에 대한 별칭들
아래의 별칭을 사용하여 메서드를 호출할 수 있다.
□ 이벤트 핸들러 등록/제거 관련 주의사항
- $addHandler 또는 @addHandlers를 이용해 이벤트 핸들러 추가 시에 이벤트 이름은 접두어를 제거한 이벤트 이름 부분만 명시해야 한다. (아래 그림 참조)

- 이벤트 핸들러 등록 후 항상 등록된 이벤트 핸들러를 제거하는 처리를 수행하도록 한다. 이렇게 함으로써 메모리 누수나 다른 성능 상의 문제를 감소시킬 수 있다. $removeHandler 혹은 $clearHandler를 두기에 가장 적당한 장소는 pageUnload 이벤트 핸들러인데, 이 이벤트는 브라우저가 웹 페이지를 언로드 하기 전에 발생하는 이벤트이기 때문이다.