관리 메뉴

새로운 시작, GuyV's lIfe sTyle.

닷넷 게시판 만들기 Part 28 - 사용자 컨트롤(ascx), 인클루드(include)전략 본문

ⓟrogramming/asp.net 게시판

닷넷 게시판 만들기 Part 28 - 사용자 컨트롤(ascx), 인클루드(include)전략

가이브 2011. 3. 11. 20:50

1. 닷넷 개발환경 준비, 테스트
2. 닷넷 알아보기 [7/7]
3. asp.net 컨트롤 [10/10]
4. 데이터베이스(DB) [7/7]
5. 닷넷 게시판을 만들어보기 전에.. [2/..]
# 이번 장은 이전 장(Part 27)의 예제를 이어갑니다.

이번 Part 에서는 asp.net 페이지의 템플릿 구성에 대해서 알아보자.
일반적으로 말하는 공통 부분을 포함하는 인클루드(include)의 개념이라고 보면 되겠다.
어디든 웹사이트를 다니면 실제 내용을 담는 공간을 제외하고 페이지 상단의 메뉴라든가 페이지 하단의 내용, 좌우 옆에 있는 내용 등 거의 비슷비슷한 레이아웃으로 구성된다. 
이것을 순수하게 HTML로만 코딩한다면 이것은 모두 한페이지 한페이지 동일해도 직접 태그를 타이핑해야 될 것이다. 그러나 대부분 프로그래밍 코드가 들어감으로서 이런 공통적인 것을 하나의 페이지에 담고, 그것을 포함(include)시키는 기법을 사용한다.

asp.net 은 다른 웹 프로그래밍 언어와 다르게 닷넷스러운 맛(?)이 존재한다. 말 그대로 결과물이 태그이긴 하나, asp.net 은 aspx 파일 하나가 처리되는 것도 내부적으로 이벤트들을 호출하여 처리한다. 이전 Part 에서 Code Behind 를 해보았듯이 페이지가 처리되는 것을 재정의(override)하여 기존에 처리하는 것은 처리하도록 하고 부가적으로 더 처리할 수 있는 코드를 삽입할 수 있다.

asp.net 에서 공통 페이지를 포함시키는 방법은 여러가지가 있다.
두 가지를 개념적으로 생각해보자.

1. 포함할 페이지 내에 단순히 디자인 요소만(서버컨트롤이 전혀 없는) 있는 경우
2. 포함할 페이지 내에 서버컨트롤이 존재하는 경우


다음은 google 의 어느 웹페이지다.


네모가 이 페이지의 내용이라고 생각하자. 나머지는 모두 어느 검색을 하든 거의 동일한 내용이 출력된다. 그러므로 구성상 공통적인 디자인 요소를 include 하면 좌측 메뉴에서 무얼 누르든 구조를 그대로 따라갈 수 있게된다. 내부적으로 태그가 어떻게 이루어져 있는지 알 필요가 없고, 개념적으로 생각하자.

------------------------ include 시작 ------------
<html>
<head><title>제목</title></head>
<body>
------------------------ include 끝 ------------


실제 페이지 내용
..
..

------------------------ include 시작 ------------
</body>
</html>
------------------------ include 끝 ------------


위의 내용처럼 include 를 구성하게 되면 기본 태그들를 입력하지 않아도 된다.
내용이 예제와 다르게 많으면 필요성은 더욱 더 유용할 것이다. 

다음처럼 좀 더 깊게 해보자.

------------------------ include 시작 ------------
<html>
<head><title>제목</title></head>
<body>
<table>
... 상단 메뉴
... 좌측 메뉴

------------------------ include 끝 ------------

실제 페이지 내용
..
..

------------------------ include 시작 ------------
... 우측 배너
... 하단 연락처,링크 등
</table>

</body>
</html>
------------------------ include 끝 ------------


꼭 필수 태그 뿐만 아니라 메뉴에 들어가는 디자인 요소 등을 함께 포함시킬 수도 있겠다.

이렇듯 include 를 잘 구조화 하면 코드를 중복으로 처리하는 부분이 적을 수 밖에 없다. 잘 활용하면 그만큼 시간이 절약되고 차후에 수정이 필요할 때 그 부분만 수정하면 되기 때문에 더욱 유용하다. 웹 프로그래밍은 실제 프로그래밍 코드가 본문(닷넷에서는 aspx)에 포함될 경우가 종종있다.

사실 asp.net 구조상 실제 aspx 에는 단 한개의 태그조차도 넣지 않고도 완벽한 홈페이지를 만들 수도 있다. 홈페이지 실제 눈으로 보이는 내용(.aspx)을 클래스로 처리해서 페이지가 로드될 때 서버컨트롤을 넣어버리는 형식이나, 아직 언급하지 않았지만 사용자컨트롤로 만들어서 그 컨트롤만 해당 내용에 넣어버리면 될 것이다.

이렇게 말처럼 그대로 코딩이 된다면 얼마나 좋을까? ^^;
(공부하며 만드는 과정에서는 오류를 만나는 것을 더 기뻐하길 바란다)

asp.net 템플릿(Template)은 말 그대로 페이지를 구성하는 방법이라고 생각하자.
여러가지 방법이 존재하지만 개발자 입맛에 맞게 만들면 그만이다. 우리는 효율성 따위는 일단 버리도록하자. 좀 했다는 경력 개발자가 초보에게 "그러면 효율성이 없어"라는 말이 가장 영양가 없는 말이다. 우리는 아직 그딴 것 보다 "구현하는 방법이 더 중요"하다.

여기에서는 사용자 컨트롤(User Control, 사용자 정의 컨트롤이라고도 한다)을 이용한 템플릿 구성 방법을 예제로 하려고 한다.

단순 페이지 포함 방법은 프로그래밍 코드가 전혀 없을 때 쉽게 사용할 수 있다. 
그러나 프로그래밍 코드가 들어갈 일이 더 많을 것이다.

예를들어 홈페이지에 로그인 기능이 있다 생각하자. 이 로그인 기능은 모든 페이지에 다 들어가야 된다고 가정하자. 그렇다면 include 기능으로 포함하여 중복 코딩을 하지 않는 것이 맞겠다. 그런데 로그인 기능은 로그인이 되어있을 때와 로그오프 되어있을 때가 구분되어야 한다. 이러한 기능으로 보아서는 프로그래밍 코드로 처리할 필요가 있을 것 같다.

로그인이 안 되었을 때는 로그인 폼이 보이고, 로그인이 되었을 때는 정보수정 및 로그오프 버튼을 보여주게 하는 것이다. 이 두 가지 디자인을 서버컨트롤에 넣어주고 (<div>태그로 렌더링 되는 Panel 컨트롤이 적합할 것이다) Visible 속성을 true/false 로 조절해주면 그만일 것이다.

사용자 컨트롤을 이용하면 이렇게 프로그래밍 코드를 처리할 수 있기 때문에 이 방식을 추천한다. 또한 그나마 구현이 쉬운 방법이기 때문에 우리 초보가 더 쉽게 사용 할 수 있다.


실습을 위해 이전 Part 의 예제였던 behind2.aspx 를 사용하자. /bin, /app_code 폴더에 behind2.aspx 에서 사용하는 라이브러리, 소스가 들어있어야 잘 작동할 것이다.

먼저 behind2.aspx 에 디자인 구성을 해보자. 테스트를 위해 상단에 메뉴를 추가하고 하단에도 디자인 요소로 글자를 입력했다. 예를 들어 이러한 기능의 웹사이트가 있을 때, 메뉴를 클릭하여 열린 페이지마다 선택한 메뉴를 표시하기 위해 배경색을 넣어주도록 하자.

수정된 behind2.aspx


<%@ Page Language="C#" Inherits="Behind" %>

<html>
<head>
<title>코드 비하인드 테스트</title>
</head>
<body>

<table width="500" border="1" cellpadding="5" cellspacing="0">
 <tr height="30">
  <td width="100" id="td1" runat="server">
  <a href="behind2.aspx?menu=1">About me..</a>
  </td>

  <td width="100" id="td2" runat="server">
  <a href="behind2.aspx?menu=2">My Family</a>
  </td>


  <td width="100" id="td3" runat="server">
  <a href="behind2.aspx?menu=3">Blog</a>
  </td>

  <td width="100" id="td4" runat="server">
  <a href="behind2.aspx?menu=4">Guestbook</a>
  </td>

  <td width="100">
  &nbsp;
  </td>
 </tr>
</table>


<p>
안녕하세요! 여기는 홍길동의 홈페이지입니다~ 제 메일주소는
hgd@hgd.com 입니다!
</p>


<form runat="server">

 <ASP:TextBox id="txtName" runat="server" />
 <ASP:Button runat="server" text="쿼리문 실행" OnClick="Button_Click" />

 <br>
 <ASP:DataGrid id="dg1" runat="server" />


</form>


<hr size="1">
Contract me :
hgd@hfd.com | 퍼가실 때는 꼭 출처를 남겨주세요.

</body>
</html>




진하게 표시된 것이 추가된 태그이다. 메뉴는 테이블로 구성하였고, 각각의 <td>는 td1~td4 까지 서버컨트롤로 지정했다.

일단 기능 구현을 위한 코드를 넣기 전에 진하게 표시된 부분이 공통적으로 사용될 것이기 때문에 이를 사용자 컨트롤로 떼어내보자. 사용자 컨트롤의 확장자는 .ascx 이다. 소스에서 녹색 부분이 현재 페이지의 실제 내용이기 때문에, 이를 기준으로 상단을 top.ascx, 하단을 bottom.ascx 파일로 만들기로 한다.

이렇게 되면 behind2.aspx 에 top.ascx, bottom.ascx 파일 두 개가 더 추가되어서 총 3개이다.

상단 공통페이지 [ top.ascx ]

<html>
<head>
<title>코드 비하인드 테스트</title>
</head>
<body>

<table width="500" border="1" cellpadding="5" cellspacing="0">
 <tr height="30">
  <td width="100" id="td1" runat="server">
  <a href="behind2.aspx?menu=1">About me..</a>
  </td>

  <td width="100" id="td2" runat="server">
  <a href="behind2.aspx?menu=2">My Family</a>
  </td>


  <td width="100" id="td3" runat="server">
  <a href="behind2.aspx?menu=3">Blog</a>
  </td>

  <td width="100" id="td4" runat="server">
  <a href="behind2.aspx?menu=4">Guestbook</a>
  </td>

  <td width="100">
  &nbsp;
  </td>
 </tr>
</table>


<p>
안녕하세요! 여기는 홍길동의 홈페이지입니다~ 제 메일주소는 hgd@hgd.com 입니다!
</p>




behind2.aspx (페이지의 내용)

<%@ Page Language="C#" Inherits="Behind" %>

<form runat="server">

 <ASP:TextBox id="txtName" runat="server" />
 <ASP:Button runat="server" text="쿼리문 실행" OnClick="Button_Click" />

 <br>
 <ASP:DataGrid id="dg1" runat="server" />


</form>

하단 공통페이지 [ bottom.ascx ]

<hr size="1">
Contract me : hgd@hfd.com | 퍼가실 때는 꼭 출처를 남겨주세요.

</body>
</html>


위의 내용처럼 녹색의 상단/하단 공통 페이지를 떼어놓자.
그리고 이제 behind2.aspx 에서는 공통 페이지를 사용하면 되겠다.


behind2.aspx (페이지의 내용)

<%@ Page Language="C#" Inherits="Behind" %>
<%@ Register TagPrefix="INCLUDE" TagName="TOP" src="top.ascx" %>
<%@ Register TagPrefix="INCLUDE" TagName="BOTTOM" src="bottom.ascx" %>


<INCLUDE:TOP runat="server" />


<form runat="server">

<ASP:TextBox id="txtName" runat="server" />
<ASP:Button runat="server" text="쿼리문 실행" OnClick="Button_Click" />

<br>
<ASP:DataGrid id="dg1" runat="server" />


</form>


<INCLUDE:BOTTOM runat="server" />


빨간색이 사용자 컨트롤을 페이지에 등록하는 소스이다. 그리고 이것을 진하게 표시된 코드처럼 원하는 위치에 배치시킨다. 형식은 TagPrefix:TagName 이다. 서버컨트롤이므로 runat="server" 를 꼭 붙여주자. 오타가 나거나 이 속성이 붙지 않으면 당연히 있는 그대로 전송될 것이다.

이대로 실행을 해보자. 우리가 떼어놓은 녀석이 잘 붙었는가? 이런 형식을 behind2.aspx 뿐만 아니라 앞으로 추가될 페이지에 모두 같은 형식으로 사용하면 될 것이다. 또한 이제부터 top.ascx 또는 bottom.ascx 만 수정하면 모든 페이지에서 똑같이 적용될 것이다. 이것이 페이지 include 의 목적이다.

bottom.ascx 파일은 그냥 고정된 텍스트이다.
그러나 앞에서 언급했지만  top.ascx 는 프로그래밍 코드가 필요하다.
각각의 메뉴는 menu 인자를 behind2.aspx 파일에 넘긴다. 이것을 받아서 해당 <td>태그의 id에 맞게 배경색을 바꾸려고 한다.

top.ascx 에는 코드파일이 필요하므로 제일 상단에 우리가 이전 Part 27 에서 했듯이 제일 상단에 참조할 클래스명과 소스파일(.cs)를 지정하자. (코드 분리가 필요하지 않다면 aspx 파일처럼 예전 방식대로 해도 상관없다)

<%@ Language="C#" Inherits="Include" codefile="top.ascx.cs" %>

ascx 에서 aspx 파일과 다른 점은 "Page" 지시자가 빠진 것이다. 
이제 top.ascx.cs 파일을 생성하고, Include 클래스 이름으로 코드파일을 만들자. top.ascx 파일과 같은 경로에 있으면 된다.

top.aspx.cs 소스파일

using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;
public partial class Include : UserControl
{
 protected void Page_Load(object sender, EventArgs e)
 {
  if (Request["menu"] != null)
   ( (HtmlTableCell)FindControl("td" + Request["menu"]) ).Attributes.Add("bgcolor", "yellow");
 }
}
 


aspx 파일의 코드 비하인드와 특별히 다른 것이 없다. Include 클래스에서 aspx에서는 Page를 상속했는데, ascx 에서는 UserControl 을 상속해주는 것이 다르다.

기능을 구현하기 위한 코드는 자동 실행되는 Page_Load(object, EvnetArgs) 메서드를 재정의 하도록 하자. 여기에 menu 값이 넘어왔다면 (Request["menu"] 값이 null 이 아니면) 컨트롤을 찾아서 태그의 속성(bgcolor)의 값(yellow)를 넣어주게 된다. 실행을 해보면 프로그램 코드도 잘 작동할 것이다. (이번 예제는 정말 '예제를 목적'으로 사용한 것임에 유념하자)


이렇듯 예제는 단 2개의 ascx 파일을 사용했지만 홈페이지의 성격에 따라 여러개로 나눌 수도 있을 것이다. 그리고 해당 컨트롤은 모두 서버컨트롤로 작동하게 된다. 

이 내용은 자주 사용되니 여러분들이 직접 다른 방법으로 작성해보고 자기 것으로 만들기 바란다.
이번 Part 의 내용은 여기까지이다.

반응형
Comments