지금까지 해온 웹 프로그래밍은 ASP.NET 2.0 기반으로 해왔기 때문에, 이 지식을 기반으로 Java에 매핑하기 시작했다. 사실 지금까지 ASP.NET 2.0 형태로 Web Form을 구성하면서, 외부에 노출되지 않은 내부 기능들에 많이 답답해 왔던 것도 사실이다.


그런데, 이번 Java기반 웹 프로그래밍을 하면서 이 ASP.NET이 많은 부분에 있어 프로그래머에게 편의를 주고 있다는 점을 알게되었다. ( 물론 Java 기반의 웹 프로그래밍을 전부 파악하고 하는 말은 아니다. 분명 Java에서도 다양한 기능들이 있기 때문에, 쉽게 처리할 수 있는 방법은 있을 것이다. )


일단 ASP.NET 2.0 으로 넘어가면서 웹 페이지 디자인 코드 부분과 코드 부분이 명확하게 나뉘게 되었다. 그래서 실제적인 .NET 코드들은 코드 부분이 담기는 페이지에 담기고, HTML 부분은 ASP 부분에만 담기게 되었다. 그 사이를 IIS와 .NET 엔진에서 알아서 붙여 진행하였다. ( 이 부분은 대부분의 웹 프로그래밍 환경에서는 최악의 문제점으로 알고 있다. 디자인과 코드가 뒤엉키다 보면 유지보수가 너무 어렵다. )


더 결정적인 부분.

사실 Form에서 데이터를 전달할 때, Ghost 페이지라는 것을 만들어 사용했다. 즉, Form에서 입력된 데이터를 DB에 저장하거나, 그 데이터를 기반으로 특정 값을 찾는 작업을 하려고 할 때, 사용자에게 보여주지는 않는 페이지를 Form의 Action으로 등록하여 처리하는 것이다. 


이 때, Servlet과 JSP에서는 이렇게 처리한다.

JSP에는 실제 사용자에게 값을 입력 받을 때 사용되는 Form(혹은 결과값을 보여주는 Form)으로 제공되고, Servlet은 이 Form에서 만들어진 값을 받아 처리하게 되는 일종의 Ghost 페이지처럼 동작하도록 하는 것이다.


즉, 입력 Form(JSP) –> Servlet –> Form(JSP).


합리적이긴 하지만, ASP.NET 2.0 기반 프로그래머 입장에서는 순간 헤매기 십상일 듯 싶었다.

게다가 Servlet 이라는게 사실 Web Server와 직접 연동하여 동작하는 작업을 구성하는 것이기 때문에 왠지 접근하기가 쉽지 않은(.NET 에서는 이 부분의 로직을 모두 숨겨서 알아서 처리해 줬기 때문이다. )부분이라, 망설임이 지대로다.


지금 Google Apps Engine 코드들을 하나씩 까면서 차근 차근 따라가보고 있다.

뭐랄까 새록새록 한 기분?

신고
Posted by 하인도

ASP.NET에서 사용되는 각종 서버 기반의 Control ( Button, TextBox 등등 )이 동작하는 방법을 가만히 살펴보면, 일부 컨트롤에서는 화면 리프레쉬 없이 동작하곤 한다. 또, AJAX 기분을 내기 위해 특정 영역 부분의 데이터만 업데이트 할 때가 있다. 보통 이런 경우 ASP.NET에서 제공하는 Postback이라는 기능을 알게 모르게 사용하게 된다.

왜 이런 기묘한 구성요소를 만들었을까?
일단 왜 이런 것이 필요한지에 대해 살펴보면서 진행하도록 한다. 과거 ASP나 PHP로 웹 응용 프로그램을 짜게 되면, 이른바 Ghost 페이지라는 것을 만들어 사용한다. 화면에 사용자의 입력을 받는 Form을 만들고, 그 Form의 Action 부분에 Ghost 페이지의 URL을 적어 동작하게 한다. 그래서 사용자가 입력 후 Submit 이라는 Form 동작을 하면 자동으로  이 Ghost 페이지를 호출하게 한다.
호출 되는 이 Ghost 페이지는 앞서 있던 Form에 있는 사용자 입력 값들을 GET이든 POST으로든 값을 받아, 이 값을 이용하여 서버에서 처리해야 되는 작업( 데이터베이스 입/출력 또는 비지니스 로직 등등)을 수행하게 된다.
이에 반해 ASP.NET에서는 Ghost 페이지 역할을 없애고 대신 이 Postback이라는 기능으로 대처하게 되었다. 즉 Form에서 Submit을 할 때, 예전 처럼 Ghost 페이지를 부르는 것이 아닌 자기 자신의 페이지를 부르는 것이다. 만일 default.aspx 페이지에 사용자 입력용 Form이 있다면, 그 Form에서 Submit을 하면 default.aspx를 다시 부른다는 것이다. 그래서 사용자의 입력값들을 모두 default.aspx 페이지 내에서 처리해 줄 수 있게 되는 것이다. 한개의 페이지 내에서 다양한 사용자의 액션도 처리할 수 있고, 보다 서버와 유기적으로 동작할 수 있다는 것이다. 페이지 리다이렉트 로 인해 발생되는 보안적인 오류( 이 Ghost 페이지에 별도 추가 설정을 하지 않는 경우 몰래 이 Ghost 페이지만 접속하여 해킹을 할 수 있다. )도 해결할 수 있고, 구현 작업을 위한 각종 소스가 별도 페이지로 쪼개지지 않아 유지보수에도 우수하다. 그외에도 이런 저런 장점이 있지만, 자세한 내용은 ASP.NET 관련 책자나, 사이트를 참조하도록 한다.

이제 이 Postback의 동작 원리를 살펴보도록 하겠다.
이 Postback의 동작을 따라가기 위해서는 먼저 ASP.NET으로 된 Page의 Life cycle 파악이 필요하다. 영어로 Life Cycle이라고 적어 뭔가 고상해 보일지는 모르겠다. 간단히 말해서 서버 상에서 이 ASP.NET 페이지가 언제 메모리에 올라갔다가, 언제 내려가는지를 살펴 보는 것이다.
ASP.NET으로 만든 페이지 자체가 HTML을 의미하는 것이 아니기 때문에, 웹서버에서는 이 ASP.NET 페이지를 메모리에 올려 각종 로직들을 처리하고 그 결과 값에 해당하는 HTML을 생성해서 뿌려주는 것이다. 즉 이런 전체 흐름을 보고 바로 Life Cycle이라 표현 한 것 뿐이다.

즉 Postback이 동작할 때 저 Life Cycle 중 언제 동작하는지를 명확히 알기 위해서는 바로 이 ASP.NET 페이지의 Life Cycle에 대한 이해가 필요하기에 먼저 그 부분을 짚고 넘어가도록 한다.

맨처음 ASPX 페이지를 Web Browser를 이용하여 Load 하게 되면 바로 ASP.NET 페이지의 Life Cycle이 시작된다. 아래의 그림을 보면 Page Load, CreateChildControl, OnPreRender, SaveViewState, Render 이런 순으로 나열 되어 있는데, 이 나열들의 하나하나들은 System.Web.UI.Page 에 만들어져 있는 각각의 메소드들을 의미한다.
보통 ASPX 페이지를 만들게 되면 System.Web.UI.Page를 상속 받아 구성하게 되는데, 상속 받게 되면 그 안의 메소드들이 자동으로 ASPX 페이지에 있는 것 처럼 된다. 물론 자신의 ASPX 페이지 내에 아래와 같은 메소드가 없어도 되는 것 같다고 말씀하시는 분이 계실지 모르겠는데, 만일 ASPX 페이지내에 해당 메소드를 구현 하지 않았다면, System.Web.UI.Page 클래스 자체에 있는 각각의 메소드를 대신 호출 하게 된다. 사실 ASP.NET 페이지를 가지고 여러가지 작업을 하게 되면 보통 아래의 순서들에 제신된 메소드들을 override 해서 대부분 쓰게 된다.

다시 원점으로 돌아와서, ASPX 페이지가 맨처음 불리게 되면 웹서버의 메모리에 올라가게 된다. 그 시점에 실행되는 부분이 바로 Page Load 부분이다. 이 부분은 대개 초기화에 관련된 사항들을 많이 넣게 된다. 그리고 난 뒤 CreateChildControl 이다. 완전 처음 부터 ASP나 PHP 등의 순수 웹 응용프로그램 언어 부터 출발하신 분들 께서는 이 부분이 명확하지 않은들 싶은데, 이 개념은 어떻게 되면 Windows 응용 프로그램 개발 프로세스에서 돌출된 사항으로 생각된다.
즉 ASP.NET에서는 System.Web.UI.Page 라는 큰 틀 안에 Control들을 붙인다는 생각에서 출발한 것이다. 예전에는 사용자 입력하는 값들이나 보여주는 부분을 대부분 HTML 페이지 내에 Form을 만들어 구성했었다. 그렇게 되면 사실 서버와는 완전히 분리되어 Form에서 Submit을 할 때까지는 서버와의 데이터 통신이 불가능하다. 그래서 ASP.NET 에서는 Server Control 이라는 개념을 만들었다. 그래서 그 컨트롤들을 System.Web.UI.Page 내에 붙여서 마치 Window Form 프로그램에서 처럼 넓다란 Form 위에 컨트롤들을 얹어 얹어 만드는 것처럼 구성한 것이다.
보통 해당 객체 내에 있는 Controls 라는 콜랙션 내에 더해주는 것으로 처리하게 된다.
(예 : Button btnOK = new Button; this.Controls.Add(btnOK); )
이런 유형의 소스 구현을 바로 CreateChildControl에서 수행한다.
다음은 OnPreRender. 이를 설명하려면 Render라는 것을 먼저 언급해야 할 것 같다. Render라는 것은 현재 Page 클래스내에 있는 Control들을 모두 합쳐 만든 HTML을 생성해주는 부분이다. 즉 실제 그리기 부분으로 이 부분에 직접 HTML을 뿌려주게 할 수 도 있고, CreateChildControl 에서 Controls.Add(xxxxx)를 통해 조립한 뒤 그 조립한 그대로를 자동으로 HTML화 시켜주기도 한다. 그런데, 이렇게 Render 하기에 앞서, UI에 관련된 일부분의 데이터 조작이나 수정작업을 할 때, 여기서 처리하게 된다. 대개는 PageLoad나 CreateChildControl에서 해주기는 하지만, 가끔Control이 생성되고 Add 되고 난 뒤, 별도 조작을 해야 하는 경우 바로 이 OnPreRender에서 그 뒷처리를 하곤 한다. 그리고 SaveViewState. 페이지가 새로 고침을 하는 경우 보통 HTML로 만든 경우 Input 내에 있는 각종 값들은 날라가게 된다. 그에 반해 ASP.NET을 이용해 만든 TextBox의 경우에는 새로 고침을 해도 값이 안전하게 담겨 있는 경우가 있는데, 그게 바로 이 SaveViewStatus 단계 때, 어떤 값들을 어떤 순서로 저장되는지를 정의하는 부분이다. 사용자가 Button을 누르게 되면 화면이 자동으로 새로 고침하게 되는데, 이 경우 ASP.NET의 Life Cycle이 Redner를 실행한 뒤, 모든 데이터가 사라지게 된다. 즉 C#으로 Behind Code로 클래스를 만들었을 때, 클래스 내의 맴버 변수들의 값들도 모두 사라지게 된다. 이 값들을 임시라도 저장을 할 때 이 부분에 구현하게 된다. 값을 실제 저장하는 방법들은 ASP.NET에 관한 다른 책들이나 자료를 참고하도록 한다. 마지막으로 Render.드디어 각종 처리를 수행한 뒤, 실제 HTML을 찍는 부분이다. 여기서는 HttpTextWriter 라는 개체를 제공하는데, 그 안에 원하는 HTML을 쓰거나, 아니면 base.Render()를 실행해서 해당 Page에 딸린 각종 서버 기반 Control들을 HTML화하여 자동으로 써지게 하는 것이다.

자 위의 Render 까지 하게 되면 실제 웹서버 상에서 해당 페이지 HTML을 클라이언트에게 제공하고, Page 및 그에 딸린 Behind Code들은 메모리 밖으로 퇴출된다. 즉, 모든 데이터들이 사라지게 되는 것이다. ( 물론 SaveVIewState에 저장해 놓을  수 있다. )

위는 ASP.NET 페이지의 Life Cycle이였다면, 과연 이 Postback은 언제 동작하는 것일까?.
일단 위의 모든 Life Cycle이 끝나야 한다. 실제 Postback 처리는 사용자가 실제 수행하는 동작을 대처하기 위한 부분이기 때문에, 무엇보다 선결되야 하는 것인 사용자의 웹브라우저에 HTML로 그림이 확실히 그려져 있어야 한다는 것이다. 그러기에 위의 단계가 완전히 끝나야, 실제적인 Postback이 실행 될 수 있는 조건이 된다.

Postback을 부르기 위해서는 대부분 Javascript를 사용하게 된다. 만일 Button 이라는 서버 기반의 컨트롤이 있다면, C#에서는 Button btnOK = new Button(); btnOK.Text = "OK!"; this.Controls.Add(btnOK);와 같은 단 세줄의 코드로 끝내져도, 실제 HTML로 찍히게 되면, 실제 Javascript를 이용하여 실행될 수 있도록 한다. 즉 ASP.NET의 서버 컨트롤이 진짜 서버에서 실행 동작된다고 보면 안되고, 실제로는 서버 컨트롤의 HTML + Javscript가 바로 그 서버 컨트롤이 된다.
Button .... 이라는 소스는 <input type="button" ..... >이 되고, 저 <input 태그 내에 Javacript로 서버를 다시 부르게 끔 하는 것이다.

아래의 그림을 보면 Callback이라고 적힌 부분이 있는데, Postback으로 이해를 하도록 한다.
자 아래의 Run Callback이라는 부분이 있다. Button에 해당하는 HTML 소스를 끄집어 내 보면 그 안에 click="webform.doPostback(......."  뭐 대충 이런 느낌의 메소드가 들어 있다.
바로 그 부분이 javascript 부분이고, 그 자바 스크립트에서는 각종 필요한 정보를 서버에 보내기 쉽게 구성하는 것이다.

자 이 Postback이 실행되면 어떻게 동작하는 것일까?
아래의 그림을 보시면 대략적인 Postback이 동작하는 그 순서를 볼 수 있을 겁니다.

맨 위의 Run Callback 이라는 부분이 있는데, 그 부분이 바로 Javascript로 된 서버 호출 로직을 담고 있는 부분이다. 이 부분이 기본 ASP.NET 컨트롤이라면 저 Run Callback이 Form의 Submit 으로 동작하는 부분일 것이고, 별도 PostBack 기반의 Callback Interface를 만들어 구성한 경우라면 Javascript로 실행하게 될 것이다. 여기서는 Javascript로 구성한 사용자 정의 Postback을 기준으로 나열할 것이므로 위의 그림이 나오는 것이다.

자 그림을 보면 Postback을 실행하는 경우 LoadViewState를 한뒤 CreateChildControl을 하고 Page를 Load 한다. 그리고 난 뒤 실제 Callback을 실행한다.
아까 맨처음에 떳던 그림과는 순서가 조금 다르지 않은가?

일단 제일 큰 차이점은 바로 Render 부분이 없다는 것이다.
Postback이 발생하였을 때, 실제 페이지에 대한 그림 그리는 부분은 없고, 단지 서버 상에서 ViewState를 복구하고 서버 컨트롤들을 구성한 뒤, Page Load 부분을 수행한다. 그리고 난뒤 Callback에 대한 실제적인 처리를 시작하게 된다. 그림 없이 데이터만 복구 하고 데이터만 돌려주는 구조라는 것이다.

위의 Page LifeCycle을 보면서 Callback에서 처리해야 하는 데이터에 대해 어떻게 보존할 것인지, 그리고 어떻게 처리할 것인지를 판단하면서, 맞추는 것이 관건이다.
초기 ASPX 페이지가 Load되서 Render된 후 Page Unload 되는 순간 모든 데이터는 파괴된다. ( 특히 aspx.cs 파일 내에 정의한 각종 member 변수들 ) 만일 이런 값들을 Callback에서 사용을 한다면 반드시 SaveViewState에서 저장해 놓도록 한다.

그리고 실제 Callback이 처리되어야 하는 로직에서는 RaiseCallbackEvent 에서 처리하도록 한다.

각 상세 코드는 2편에서 계속하도록 한다.

신고
Posted by 하인도
ASP.NET의 서버 웹컨트롤로 만들면 CS 프로그램 짜듯이 쉽게 UI를 구성할 수 있다.
마치 일반 Windows Form 프로그램 짜듯이 붙이게 되는데,
이 컨트롤을 실제 웹 브라우저에서 볼 수 있도록 HTML로 번역하게 된다.

TextBox 같은 경우 <Input type="text" .. >로,
Button 같은 경우 <Input type="button" ...> 로  번역되어 나타낸다.

그런데, 이 중 요상한 것이 있는데, 바로 Label 컨트롤이다.
이 Label 컨트롤을 다른 컨트롤 처럼 만들어서 붙이면 이상하게 <span> 으로 붙는다.
그런데 다른 부분의 Html 소스를 보면 <Label ..> 로 구성되어 있다.
그래서 간혹 CSS를 구성하다 보면 유독 그 녀석만 CSS가 안먹는 기이한 현상을
만들어 낸다. 게다가 HTML 코드 자체가 틀리니 미묘하게 짜증까지...

하지만 그 속에서 쓰고 있는 웹 컨트롤은 모두 똑같이 Label 이였다.
그럼 이와 같은 차이가 발생하는 이유는 무엇일까?

그것은 Label의 역할에 따라 다르게 번역되는 것이다.
사용자 삽입 이미지
위의 구성 내용 중 RSS Feed 주소 부분이 바로 이 Label로 만들어진 부분인데,
그냥 Label을 생성해서 붙이기만 하면 저 부분은 Span으로 구성되게 된다.
      <span .... > RSS Feed 주소 </span>

만일 html에서 Label로 표시하고 싶으면, Label의 속성 중에 AssociatedControlID 라는 부분에 이 Label이 수식하고 있는 컨트롤 ID를 넣으면 된다.
즉 만일 저 위의 그림의 예제에서 TextBox ID가 txtRSSFeeder 이면,
  label.AssociatedControlID  = "txtRSSFeeder";
이렇게 서버에서 구성해주면 된다.

그러면 실제 웹에서 보여주는 소스를 보게 되면,
     <Label for="txtRSSFeederxxxxxxxx" > RSS Feed 주소 </Label>
     (txtRSSFeederxxxxxx에서 xxxxxx 부분은 볼때 마다 틀린 값이 붙는다.)






     
신고
Posted by 하인도
보통 WSS 및 ASP.NET 사이트를 구축하려면
반드시 시스템에 IIS와 함께, .NET Framework 2.0 이 설치되어 있어야 한다.
그러나 종종 IIS 가 설치되기 전에, .NET Framework 2.0이 설치를 해서,
IIS 내에 .NET Framework 2.0 기능을 전혀 활성화 시키지 못하는 경우가 있다.
대부분의 경우는 2.0을 다시 설치하거나 기타 2.0에 관련된 Update를 하면 되기는
하지만, 이 또한 비용이 드는데다, 다시 설치하게 되면 기존 설치 기록들이 잘못 적용될 수 있다.

다시 설치하지 않고 해결 하는 방법은 의외로 간단하다.
일단 .NET Framework 2.0이 설치되어 있으면 아래와 같은 경로가 있을 것이다.

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

위의 경로를 들어가면, 여러가지 관리도구들과 핵심 어셈블리들이 있는데,
그 중 aspnet_regiis.exe 를 이용하여 IIS에 관련된 .NET 구성요소를 설치하게 된다.

그래서 아래의 명령을 명령줄에 입력하면 된다.

C:\WINDOWS\Microsoft.NET\Framework\v2.0.
50727\aspnet_regiis.exe -iru

사용자 삽입 이미지


즉 aspnet_regiis.exe 에 -iru 라는 옵션을 넣어 한번 실행해 주면 완료된다.
아래에 이 aspnet_regiis.exe에 대한 옵션들에 대한 설명이다. 참고로 추가한다.

ASPNET_REGIIS.EXE 도움말

신고
Posted by 하인도


티스토리 툴바