Posted
Filed under .NET/ASP.NET

좋다. 우리는 이전 Start.aspx 페이지를 코드 비하인드 페이지로 구성해 보았다. 실행이 되는 결과 모습은 이전 Start.aspx 와 완전하게 동일했으며, 코드와 UI를 분리하여 작업을 효율적으로 할 수 있게 되었다. 하지만, 코드 비하인드의 기능은 단지 코드와 컨텐트의 분리 정도가 아니다. 과연 정말로 그러한가? 좋다. 내친김에 하나의 aspx 페이지를 더 만들어 보도록 하자.

Start3.aspx 라는 이름으로 페이지를 하나 더 메모장으로 작성해 보자. 코드는 다음과 같다.

<%@ Page language="c#" Inherits="Start" Src="Start.cs" %>
   <HTML>
      <body>
         <form runat="server">
             <p><asp:Label id="Label1" runat="server" Text="Welcome. Welcome" /></p>
             <p><asp:Label id="lblMsg" runat="server" /></p>
             <asp:Button id="btnSubmit" runat="server" BorderStyle="Solid" BackColor="Orange"
                Text="클릭해 보세요" OnClick="btnSubmit_OnClick" />
         </form>
      </body>
   </HTML>

코드는 Start2.aspx와는 조금 다르다. Label 컨트롤이 하나 더 추가되었으며, Button의 텍스트와 모양도 조금 바뀌었다. 가급적 여러분들은 이 페이지가 Start2.aspx 와는 전혀 다른 페이지라고 인식하도록 하자. 단지, 버튼이 클릭될 경우, 호출하는 이벤트 함수가 여전히 btnSubmit_OnClick 이며, lblMsg 라는 id의 Label 컨트롤이 여전히 존재한다는 것만 기억해 두자.

코드를 다 작성하였으면, 이 파일을 Start3.aspx 라는 이름으로 TaeyoBook 이라는 가상 디렉터리 안에 놓도록 하자. 물리적인 전체 경로는 C:\Inetpub\wwwroot\TaeyoBook\Start3.aspx 이 될 것이다.

그리고, 다음과 같이 브라우저를 열고, Http://localhost/TaeyoBook/Start3.aspx 를 실행하도록 하자. 밑의 왼쪽과 같은 결과 화면을 만날 수 있을 것이다. 그리고, 버튼을 클릭하면 오른 쪽과 같은 그림을 보게 될 것이다.

그렇다면, 이전 예제였던 Start.aspx 페이지의 소스를 다시금 한번 살펴보자. 그 소스는 다음 그림과 같이 서버 사이드 프로그래밍 코드와 UI 컨텐트 코드가 뒤섞여 있는 구조였다.

코드 비하인드로 구현하긴 하였으나, 코드 비하인드 파일을 Start2.aspx 에서 사용했던 그 클래스 파일을 그대로 사용하고 있다. 말 그래도 하나의 비하인드 파일을 공유해서 사용하고 있는 것이다. 우리가 구성해 놓은 하나의 Start.cs 라는 클래스 파일을 Start2.aspx와 Start3.aspx 파일에서 모두 사용하고 있다. 그리고, Start.cs 에서 여러분이 코드를 수정하게 되면 그 내용은 Start2.asp와 Start3.aspx 모두에 반영된다. 그림으로 표현하면 다음과 같다.

하지만, 사실 위의 그림은 여러분들이 이해하기 좋도록 개략적으로 나타낸 그림일 뿐 실제는 이렇지가 않다. 클래스 파일인 Start.cs는 클래스 자체로서는 실행을 할 수가 없다. 클래스는 일종의 설계도 일뿐 이고, 그것이 실행되려면 하나의 실행이 될 수 있는 파일(어셈블리, DLL)로써 존재하고 있어야만 한다.

즉, 우선적으로 클래스 파일은 컴파일이 되어 있어야 한다는 것이다. 그러나, 우리는 클래스 파일을 컴파일 한 적이 없다. 그럼에도 실행은 제대로 되었다. 이것은 무엇을 의미하는가? 어쩌면 우리가 클래스 파일을 컴파일 하지 않았어도 사실상 내부적으로 이 클래스 파일은 컴파일이 된 것은 아닐까? 그렇다. 아주 정확한 추측이다.

ASP.NET은 코드 비하인드 클래스와 연계된 aspx 페이지가 요청될 경우, 아직 그 비하인드 클래스가 컴파일 되지 않았다면, 우선적으로 그 클래스를 컴파일하고, DLL로 만들어 어셈블리 캐쉬 위에 올려놓는다. (이전의 ASP.NET 실행모델에서 설명을 하였었다)

그리고, 이후로는 Start2.aspx 나 Start3.aspx 요청 시 Start.cs의 컴파일 단계 없이 이미 어셈블리 캐쉬에 존재하는 해당 DLL 을 이용하는 것이다. 고로, 이것을 구체적으로 나타내면 다음 그림과 같다고 볼 수 있다.

다음 그림은 MSDN 에서 제공하는 ASP.NET Page 의 구성과 실행 모습이다.(우리의 상황에 맞게 약간 편집을 하였다) 지금의 여러분이라면 이해할 수 있을 것이다. 만일 이해가 여전히 가지 않는다면, 일단은 그냥 읽어나가고 여러분이 필자의 책을 모두 정독한 후, 지식의 수준이 상승한 다음 다시 이 그림을 확인해 보기 바란다. 그 때에는 아래의 그림이 여러분의 지식을 깔끔하게 정리 해 줄 것이다

위의 그림을 차근히 바라보자.

우리가 작성한 Start.cs 라는 비하인드 클래스 파일은 Page 라는 .NET 클래스로부터 상속을 받아 생성되었으며, 이는 초기 컴파일을 통해서 특정 이름의 DLL(그림의 경우는 MyProject.dll)로 만들어지게 된다. 이러한 컴파일은 ASP.NET 이 자동적으로 처리 한다는 것을 기억하자. 물론, 이러한 초기 컴파일은 해당 파일이 처음 요청될 경우에만 발생하는 작업이다. 만일, Start.cs 의 컴파일 결과 DLL 이 이미 만들어져서 어셈블리 캐쉬에 존재하게 되었다면, 이후 요청 시에는 이러한 컴파일 단계를 거치지 않을 것이며, 어셈블리 캐쉬에 이미 존재하는 해당 DLL 을 사용하게 될 것이다. (물론, 이 DLL은 중간 언어인 IL 이다)

만일, Start.cs 라는 클래스 파일이 수정되면 어떻게 될까? 그럴 경우는 예상대로 초기 컴파일부터 다시 수행하게 될 것이고, 그 결과 DLL 을 어셈블리 캐쉬에 올려놓게 될 것이다.

그리고, 이제 위 그림의 우측인 런타임 시를 살펴보자. 런타임 시(클라이언트로부터의 요청 시)는 요청에 의해 UI 페이지인 Start.aspx는 코드 비하인드 파일의 DLL(그림의 경우는 MyProject.dll)과 어우러져서(상속되어) 두 번째 컴파일이 발생하게 된다. 이 런타임 컴파일은 이미 알고 있다시피 Common Language Runtime의 JIT 컴파일러에 의해 수행되어지며, temporary.dll 이라는 원시 코드 파일을 만들어내고, 이에 의해 실행이 일어나게 되는 것이다.

물론, 위에서 예를 든, MyProject.dll 과 temporary.dll은 가상 명칭이다. 실제로는 ASP.NET에 의해서 이름이 랜덤하게 만들어지게 된다. 나중에 살펴보겠지만 그러한 DLL 들은 다음 경로에서 찾아 볼 수 있다. 이 곳이 바로 ASP.NET 을 위한 어셈블리 캐쉬라는 특별한 구역이다.

C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\Temporary ASP.NET Files\가상 디렉터리명

필자로서는 이러한 프로세스를 여러분들이 반드시 이해하기를 희망한다. 이 흐름은 여러분이 ASP.NET을 이해하는데 큰 도움이 되어주는 개념이기 때문이다. 그리고, 이 과정을 이전 장(章)에서 살펴보았던 ASP.NET 실행모델과 함께 매칭시켜서 또한 정리를 해보도록 하자. 다음 그림이 기억나는가?

정리해 보면, 코드 비하인드 파일은 각 UI 페이지에 프로그래밍 로직을 제공해주는 역할을 하며, 여러 aspx 페이지에서 공유해서 사용될 수도 있다. UI 페이지인 aspx 페이지에는 그 어떠한 프로그래밍 코드도 존재하지 않으며, 이는 모두 코드 비하인드 파일로 분리가 되어지고, 코드의 관리와, 유지 보수, 재 사용성을 증가시킨다.

이것이 코드 비하인드 이다. 물론, 위와 같은 식으로 클래스를 작성하고, 공유해서 사용하는 경우는 매우 드물 것이다. 각각의 ASP.NET 페이지는 자신만의 기능을 가질 것이고, 두 페이지가 공유해서 어떠한 로직을 가지는 경우는 드물다. 해서, 대부분의 ASP.NET 페이지는 위의 예처럼 하나의 클래스 파일을 공유해서 사용하지 않고, 자신만의 클래스 파일을 가지는 편이다. 하지만, 위의 방법은 이후 조금은 중급적인 코딩 방법에 상당한 도움을 준다. 그렇기에 꼭 기억해 두자. 여러분이 ADO.NET을 통해 데이터베이스와 연동할 경우 위의 지식은 응용력을 통해 상당한 도움을 제공해 줄 수 있다.

조금 더 이야기를 해보자. 이제 막 감을 잡아나가기 시작하는데, 이대로 정리하고 넘어가면 여러분의 지식은 또한 금새 흩어져 버릴 것이다. 그러하다면, 기존의 소스를 조금 수정해 보도록 하자. 먼저, Start.cs 라는 클래스 파일을 다음과 같이 수정하도록 하자. 기존의 코드는 그대로 존재하며, 추가적으로 AnotherStart 라는 하나의 클래스를 더 정의 하였다.

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public class Start : Page
{
    protected Label lblMsg;
    public void btnSubmit_OnClick(Object sender, EventArgs e)
    {
        lblMsg.Text = "클릭!!!";
    }
}

// 새롭게 추가된 클래스. 하위 부분을 추가하자.public class
AnotherStart : Page
{
    protected Label lblMsg;
    public void btnSubmit_OnClick(Object sender, EventArgs e)
    {
        lblMsg.Text = "Good Morning~~ ASP.NET!!";
    }
}

이제 Start2.aspx 페이지의 상단에서 @Page 지시자 부분을 다음처럼 수정하자. 오로지 Inherits 속성의 지정이 바뀌었을 뿐이다.

<%@ Page language="c#" Src="Start.cs" Inherits="AnotherStart"%>

이제 다시금 Start2.aspx와 Start3.aspx 각각의 페이지를 브라우저로 실행하여 결과를 보도록 하자. Start2.aspx 에서 버튼을 누를 경우와 Start3.aspx 에서 버튼을 누를 경우, Label 컨트롤에는 각기 다른 문자열이 출력되어 나올 것이다. 그림과 같이 말이다.

Start2.aspx, Start3.aspx 모두 Start.cs 를 비하인드 페이지로 사용하고 있지만, 상속을 받는 클래스가 다르기에, 각각 적용된 이벤트 함수도 다르게 나오는 것이다.

이것이 바로 Inherits 속성에 명확히 사용할 클래스 명을 지정해 주어야 하는 이유이다.

위의 예제는 하나의 비하인드 클래스 파일이 여러 개의 클래스를 갖는 예제이기는 하지만, 실무에서 이렇게 사용할 일은 그다지 많지 않은 편이다. 예제는 예제일 뿐 이다. 하지만, 이러한 방법을 여러분이 적절히 응용해서 사용한다면 웹 어플리케이션을 조금 더 효율적으로 구성할 수 있을 것임은 분명하다.

사실, 이러한 코드 비하인드를 제대로 이해하기 위해서는 여러분의 머리 속에 OOP에 대한 개념이 먼저 어느 정도는 자리잡고 있어야만 한다. 이 말은 곧 여러분이 이 책과 함께 최소한 한 권의 C# 초보 서적은 같이 봐 주어야 한다는 이야기이다. 서운하다? 그렇다. 한 권의 책에서 모든 것을 다 해결하고 싶었는데, 다른 책을 보라니 이것은 너무나도 서운하다고 말할 수도 있을 것이다. 이 책에서 OOP와 C# 문법에 대한 가벼운 소개만을 한다고 해도 200-300 페이지는 차지할 것이며, 이 책은 C# 책이 아니라 ASP.NET 책이다. 필자도 그러한 설명을 이 책에서 같이 나누지 못함을 안타깝게 생각한다. 물론, C# 에 대한 지식이 없이도 이 책을 따라갈 수는 있다. 하지만, 자신이 원하는 것을 이루기 위해서는 결과적으로 ASP.NET 에 대한 지식보다는 C# 이라는 언어에 대한 지식이 많은 부분을 좌우할 것이다. 예를 들어, 여러분이 웹에서 사용 가능한 차트를 만든다거나, 사용자가 업로드 한 이미지를 조작, 필터링 하는 등의 고급작업을 하고 싶다면 그것은 C# 등의 .NET 언어를 잘 구사함으로써 가능한 것이다. 그러니 열심히 하자. 이 말을 이 책에서도 한번쯤은 전하고 싶었다.

이제 코드 비하인드의 개념과 사용방법에 대해서는 어느정도 설명이 된 듯 하다. 어려운 이야기를 따라오느라 고생이 많았으니, 이번에는 코드 비하인드를 쉽게 사용하는 방법에 대해서 알아보자..

그것은 바로 Visual Studio.NET을 사용하는 것이다. 짜잔!!!!

출처 : Taeyo.pe.kr

2007/08/23 15:52 2007/08/23 15:52
Posted
Filed under .NET/ASP.NET

Code Behind

사실 이번 강좌는 이전 강좌에서 약속한대로 Start.aspx 를 VS.NET으로 만들어 보는 강좌이고자 했다. 하지만, 몇몇가지 문제가 있었는데 그중에 하나는 VS.NET은 웹 폼 페이지에 기본적으로 코드 비하인드라는 기법을 사용한다는 것이다. 즉, 여러분이 Start.aspx 를 VS.NET으로 만들기 위해서는 반드시 코드 비하인드라는 것이 어떤 것인지 알고 있어야 하며, 그것을 모를경우 전반적인 이해가 어려울 수 있다는 것이다

해서, 이번 강좌부터는 갑작스럽긴 하지만, 그리고 그리 쉬운 내용은 아니지만 코드 비하인드 기술에 대해서 먼저 심도있게 알아보고자 한다

혹시나 여러분이 ASP를 해본 적이 있다면 그 경험에 빗대어 ASP.NET 을 매우 만만하게 보고 있을 수도 있겠다. 하지만, 사실 ASP.NET 은 그리 만만하지 않다. 이제 여러분은 ASP.NET이 ASP의 업그레이드 버전이 아닌 완전히 새로운 기술이라는 것을 실감하게 될 것이다.

그 시작은 바로 코드 비하인드이다.

ASP.NET 페이지의 구성은 기본적으로 크게 UI(User Interface)와 Logic 부분으로 나뉘어진다. 이중에 UI를 담당하는 것이 HTML 과 여러 서버 컨트롤들(이도 사실상 결과로써는 HTML이다)이며, Logic을 담당하는 것은 여러 서버 사이드 측의 함수들이 될 것이다. ASP 에서는 이 두 부분이 하나의 페이지에 모두 들어있어야만 하는 구조였고, ASP.NET 도 그러한 구조를 지원하지만, ASP.NET은 추가적인 코드 비하인드라는 구조를 제공해 준다.

코드 비하인드라는 것은 말 그대로 코드를 뒷면에 숨겨두겠다는 이야기이다. 즉, 컨텐트 페이지와 프로그래밍 코드 페이지를 따로 두겠다는 의미이며, 런타임 시에 같이 어우러져 동작하게 하겠다는 의미이다. 이것은 ASP 의 Include 파일과는 자못 틀린 개념이다. 코드 비하인드를 생각하며 절대로 Include를 떠올리지 말기 바란다. 그것은 개념의 혼란만을 가중시킬 뿐이다.

그렇다면, 이전 예제였던 Start.aspx 페이지의 소스를 다시금 한번 살펴보자. 그 소스는 다음 그림과 같이 서버 사이드 프로그래밍 코드와 UI 컨텐트 코드가 뒤섞여 있는 구조였다.

코드 비하인드라는 구조는 위와 같은 혼합적인 코드의 구조를 다음 그림과 같이 분리시켜서, UI 렌더용 HTML 페이지와 ASP.NET 코드 페이지로 구성하는 것을 의미한다.

그림의 경우에서는 분리된 코드 비하인드 파일의 이름을 Start.aspx.cs 라고 주었는데, 이것은 VS.NET 이 명명하는 기준을 따른 것이고, 사실상은 여러분이 주고 싶은 어떠한 이름이라도 사용할 수 있다. 단지, 이 코드 비하인드 파일은 반드시 .NET 언어의 클래스로 구성되어야 하기에, 그 확장자는 C#의 .cs 이거나 VB.NET의 .vb 등이어야만 하며, Page 라는 .NET 클래스로부터 상속을 받은 클래스로써 구성이 되어야만 한다. 구체적인 이야기는 곧 나올 것이다.

페이지를 이렇게 코드 비하인드로 구성하게 되면, 여러분은 UI와 코드를 완벽하게 분리할 수 있게 되기 때문에 소스를 디버그 하거나, 유지, 보수, 관리할 경우 상당한 이점을 얻을 수 있게 된다.

단, 코드 비하인드로 Logic 부분을 분리시킬 경우, 코드 비하인드 페이지는 여러분이 위의 그림에서 본 모습과는 다르다. 위의 그림은 일종의 예시였을 뿐이다. 코드 비하인드 페이지는 여러 가지 따라주어야 하는 까다로운 조건들을 가지고 있다. 이제부터 그러한 조건들과 규칙들에 대해서 이야기를 해볼까 한다.

이 이야기는 사실상 OOP(개체 지향 프로그래밍)에 대한 지식이 있어야 이해할 수 있는 내용이기는 하다. 전에 말했듯이 ASP.NET은 여러 가지 .NET 의 기술들을 복합적으로 사용하는 기술이며, 그 근간은 여러 .NET 클래스들에 의해 구성되어 있다. ASP.NET 페이지라는 것은 사실상 Page 라고 하는 하나의 .NET 클래스를 기본으로 한다. 그렇기에 이제부터 필자가 서술할 이야기는 OOP가 낯 설은 초보 프로그래머들에게 있어서는 매우 복잡하고, 이해하기 어렵게 느껴질 수 있는 이야기이다. 물론, 여러분이 글을 읽는 즉시 필자의 이야기를 이해할 것이라고는 생각하지는 않는다. 하지만, 어렵다고 하더라도 일단은 그렇다고 받아들이고 읽어나가자. 지금은 이해하기 어려울 수 있지만, 이 책을 마무리할 즈음에는 어느 정도 이해할 수 있을 것이며, 개별적인 .NET 언어에 대한 학습을 통해 이 지식을 다져나갈 수 있을 것이라 믿는다.

ASP.NET 페이지를 위해 .NET 은 특별한 클래스를 하나 준비해 두었는데, 그 클래스의 이름은 Page 이며, 모든 ASP.NET 코드 비하인드 페이지는 Page 라는 .NET 의 클래스로부터 상속된 하나의 클래스로 제작해야 한다. 그러므로, 하나의 aspx 페이지당 하나의 코드 비하인드 클래스가 필요하게 된다. 예를 들자면, 다음 그림은 각각의 aspx 페이지마다 각각의 코드 비하인드 페이지가 연결되어 있는 VS.NET의 모습을 나타내고 있다. (C# 언어를 사용하였기에 비하인드 파일의 확장자가 .cs 인 것을 알 수 있다.)

하지만, 코드 비하인드 파일이 언제나 하나의 aspx 당 하나가 필요한 것은 아니다. 하나의 코드 비하인드 파일은 여러 개의 aspx 페이지에서 공유하여 사용할 수도 있다. 잠시 후 관련 예제를 보게 될 것이다.

우선, 코드 비하인드 페이지는 다음과 같은 페이지의 골격을 가져야만 한다. 이것은 C# 을 사용했기 때문에 이렇게 작성된 것이며, 만일 VB.NET 을 사용한 경우는 조금 다르게 구성한다.(완전한 소스는 VB.NET으로 작성한 코드도 보여주도록 하겠다)

단, C#으로 작성했던 VB.NET으로 작성했던, 그 어떤 .NET 언어로 작성을 했던지 간에 현재의 클래스의 부모 클래스로는 반드시 System.Web.UI.Page 가 지정되어야 한다

using System;

public class Start : System.Web.UI.Page
{
}

클래스의 이름은 일반적으로 aspx 페이지의 파일명을 기준으로 한다. 클래스 이름은 현재의 웹 어플리케이션 내에서 절대적으로 고유한 이름을 사용해야만 하는데, 파일명 또한 그러하기 때문에, 주로 파일명을 클래스 명으로 사용하는 것이다.

소스를 보면 소스의 제일 첫 줄에는 using System; 이라는 문장이 있는 것을 볼 수가 있다. 이는 System 이라는 네임스페이스에 존재하는 클래스들을 사용하도록 하겠다는 의미라고 볼 수 있다.

System 이라는 네임스페이스 안에는 여러 가지 기본적인 .NET 클래스들이 존재하고 있는데, array, Boolean, byte, char, DateTime, int, string 등등의 기본적인 데이터 타입들이 모두 제공 된다. 대부분의 코드에서는 이러한 데이터 형들을 매우 자주 사용하게 되기에, 이 네임스페이스를 소스 코드에 추가하는 것은 거의 필수적이다.

만일, 여러분이 System이라는 네임스페이스를 using 키워드를 통해서 코드에 추가하지 않으면, 코드내에서 string 을 사용해야 할 경우, System.String 과 같이 완전한 이름으로 사용해야만 한다. 이러한 불편함을 덜어주기 위해서 System 이라는 네임스페이스를 using를 통해서 첨부한 것이다.

코드의 두 번째 줄에는 다음과 같은 코드가 있다.

public class Start : System.Web.UI.Page

이것은 System.Web.UI.Page 라는 클래스로부터 상속을 받는 Start 라는 클래스를 우리가 작성하겠다는 의미를 가지는 부분인데, 여기서 .NET 이 ASP.NET을 위해 특별히 준비해 둔 Page 클래스라는 것이 바로 System.Web.UI.Page임을 알 수 있다.

System.Web.UI.Page 라는 부분을 유심히 보면, Page 라는 클래스는 System.Web.UI 라는 네임스페이스 안에 들어있는 하나의 클래스라고도 볼 수 있다. 그렇다. System.Web.UI는 하나의 네임스페이스이며, page 는 그 네임스페이스 안에 들어있는 하나의 클래스인 것이다.

필독 : 네임스페이스(namespace) 란 ?

여기서 네임스페이스(namespace)라는 단어가 여러 차례 등장했다. 네임스페이스라는 것은 무엇일까? 네임스페이스라는 것은 .NET 에서 관련된 여러 클래스들을 그룹을 지어 묶어 놓은 일종의 논리적인 그룹핑이다. 관련이 있는 클래스들을 하나의 이름으로 묶어서 관리하는 구조인 것이다. 예를 들어서, .NET 에서 제공하는 모든 클래스들은 System 이라는 가장 큰 단위로 모두 묶여있다. 그리고, 그 클래스들 중에서 Web과 연관이 있는 클래스는 System의 하위로 Web 이라는 네임스페이스를 두어 그 곳에 모두 모아 두었다. Web 내에서도 UI 와 관계가 있는 클래스들은 다시 세분화하여 UI 라는 네임스페이스에 두도록 했다. 대표적인 UI 관련 클래스로는 이미 위에서 보았듯이 Page 라는 것이 있다. 해서, 이 Page 라는 클래스를 완전하게 나타낸다면 System.Web.UI.Page 라고 말할 수가 있는 것이다. .(점)은 "..의 밑의” 라는 의미로 생각하면 되겠다. 중요한 것은 이러한 네임스페이스 구조에서는 자신의 네임스페이스 내에 직접적으로 존재하지 않는 클래스는 인식하지 못한다는 것이다. 무슨 말인고 하니, Page 라는 클래스는 System.Web.UI 라는 네임스페이스에 존재하고 있지, System.Web 이라는 네임스페이