관리 메뉴

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

닷넷 게시판 만들기 Part 19 - 이벤트. 그리고 포스트백(postback) 개념. 본문

ⓟrogramming/asp.net 게시판

닷넷 게시판 만들기 Part 19 - 이벤트. 그리고 포스트백(postback) 개념.

가이브 2011.02.15 15:30
2011/01/19 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 10
2011/01/20 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 11
2011/01/21 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 12
2011/01/25 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 13
2011/01/26 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 14
2011/01/31 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 15
2011/02/10 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 16
2011/02/11 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 17
2011/02/14 - [ⓟrogramming/asp.net 게시판] - 닷넷 게시판 만들기 Part 18


1. 닷넷 개발환경 준비, 테스트
2. 닷넷 알아보기 [7/7]
3. asp.net 컨트롤 [10/10]


이번 시간은, 서버컨트롤에서 자주 이용되는 이벤트(Event)를 알아보자.
프로그래밍에서의 '이벤트'라는 것은, "어떤 상황이 일어났을 때 이렇게 해라"라고 생각할 수 있다.

웹프로그래밍에 사용하는, 값을 전달하는 방법인 순수 HTML Form 에서 <input type="submit">로 지정된 버튼을 누르면 지정된 action 값으로 전송이 되는 것을 이벤트라고 부르지는 않지만 asp.net 서버컨트롤로 만든 것은 "이벤트"를 지정하고 이벤트 처리기를 만들어서 작성하는 것이 일반적이다.

이번 3장 초반에 HtmlControls 를 처음 다룰 때 이벤트를 사용했던적이 있다.

<input type="submit" value="로그인!" runat="server" onserverclick="Login_Proc">


태그에 runat="server"를 붙였으므로, 서버컨트롤이 되고, 이것은 해당 태그에 맞는 클래스로 인스턴스 화 된다고 했다. 여기서 onserverclick="" 속성으로 이벤트를 연결하게 된다.
그리고 우리는 이 이벤트를 만들어야 했다.

void Login_Proc(object o, EventArgs e)
{
      Response.Write("아이디: " + userid.Value + "<br>");
      Response.Write("비밀번호: " + pwd.Value + "<hr>");
}


WebControls 인 웹폼 방식에서는 위 기능과 동일하게 하기 위해서 다음처럼 만들 수 있다.

<ASP:Button text="로그인!" runat="server" OnClick="Login_Proc">

#참고
1. 디자인에서 서버컨트롤의 속성은 대소문자를 구분하지 않는다.
2. 여기서는 생략했지만, Button 컨트롤은 <form runat="server">..</form> 내부에 넣어야한다.



이렇게 서버컨트롤로 버튼을 만든 후, 이벤트를 연결해주면 된다.
(이벤트 선언은 HtmlControls에서 사용한 방식과 다르지 않다)

이벤트를 선언할 때는 위에서 보듯이 인수가 꼭 붙는데 MSDN에 해당 이벤트에 나와있다.
먼저, MSDN에서 WebControls 의 Button(클래스) 에 Click 이벤트를 한번 살펴보자.
(해당 MSDN 주소 : http://msdn.microsoft.com/ko-kr/library/system.web.ui.webcontrols.button_members(v=VS.80).aspx)

** 하단에 있는 "Control에서 상속됨" 이벤트는 모든 컨트롤의 공통적인 이벤트이므로 일단 무시하도록 한다. 그림에서는 잘려져있다.

웹폼의 Button 이벤트에는 두 개의 이벤트가 존재한다. 둘 다 설명으로 Button 컨트롤을 클릭하면 발생한다고 되어 있다. 이벤트를 지정하는 방법은 앞서 보았듯이, 이벤트명 앞에 "On"을 붙여주어

OnClick="호출할_메서드"
OnCommand="호출할_메서드"


이렇게 지정한다. 모든 웹폼의 이벤트 연결 방법은 이렇게 사용된다.

일전에 웹폼 <ASP:Button>의 렌더링 결과를 확인해봤는가? 이 버튼 서버컨트롤은
<input type="submit">
으로 렌더링이 되는데, 우리가 알다시피 이것은 HTML에서 <form>값을 보낼 때 사용하는 버튼이다. Button 뿐만 아니라, DropDownList, LinkButton 과 같은 버튼 형식이 아닌 몇몇 웹폼 컨트롤도 자체적으로 <form>값을 보내는 것과 같은 기능을 하게된다.

asp.net 이라는 것을 무시하고, HTML에서는 <form>태그의 값을 보낼 때 오직 <input type="submit"> (또는 <input type="image" src="이미지_경로">) 으로만 보낼 수 있다. 버튼밖에 없다는 말이다.

그러나 버튼 이외의 방법으로 보낼 수 있는 이유는 "자바스크립트(javascript)"라는 클라이언트에서 처리되는 스크립트가 있기 때문에 가능하다. 그래서, 버튼 이외의 형식의 컨트롤도 이렇게 값을 보내는 기능을 처리하기 위해 asp.net 에서는 값을 보내는 컨트롤을 모두 자바스크립트라는 것으로 처리한다. 서버컨트롤에서 특히 Button 이나 DropDownList, 앞에서 해보았던 Calendar 등, 입력기능이 있는 컨트롤이 들어간 결과물의 소스 결과를 보면 유달리 복잡해 보이는 코드가 추가된 것을 알 수 있다.

일단, 우리는 이렇다는 것만 알고 있자.
(언젠가는 다시 돌아와서 여러분들이 직접 살펴볼 날이 오기 때문에.. ^^)

MSDN에서 사용하려는 이벤트를 클릭하면, 이벤트의 구문과 설명, 예제가 나와있다. 사용해 본 적이 없더라도 예제를 참고하면 각각의 컨트롤에 있는 이벤트 구현은 어렵지 않게 구현을 할 수 있다.

정리해보면, 웹폼 서버컨트롤에는 해당 컨트롤의 기능에 맞는 이벤트가 있다. 디자인단에서 이벤트를 지정하기 위해서는 앞에 [On] 을 붙여주고 이벤트이름을 적어주면 된다. 그리고 해당 이벤트의 값은 괄호를 제외한 메서드명이다. 지정한 메서드명은 코드에서 이벤트의 인수와 일치하게 선언해주면 된다.

asp.net 에서 꼭 서버컨트롤을 이용할 필요는 없다. 누차 말하지만 서버컨트롤은 개발자의 태그 코딩을 줄이기 위해, 또는 어렵지 않게 하기 위해 사용하고, 각각의 컨트롤들을 동적으로 우리 마음대로 조작할 수 있기 때문에 쉽게 사용할 수 있다.


잠시, 이론적인 얘기를 해보자.

asp.net 의 결과물인 (그래봐야 <tag>인) HTML 페이지라는 것은 요청을 하고 응답하면 끝이나게 된다. 그러나 서버컨트롤을 이용하게 되면 각각의 컨트롤들은 처리가 된 후에도 계속해서 해당 상태를 유지하는 특징이 있다. asp.net 의 가장 큰 특징이라고 할 수 있다.

예를 들어서, 순수 HTML로 submit 을 했을 때 해당 <form>내의 컨트롤들의 값은 비어있을 것이다. 당연하지만 해당 페이지를 새로 열었기 때문이다. 
그러나 이것을 모두 서버컨트롤로 만들었을 때는 이야기가 달라진다.
특정 컨트롤(<input type="password">로 렌더링 되는 것)을 제외하고는 모두 값이 입력되어 있거나, 체크되어 있거나, 선택되어 있게된다.

asp.net 의 서버컨트롤은 기본적으로 "상태유지"라는 것이 있다. 바로 뷰스테이트(viewstate)라고 불리는 것 때문이다. 웹폼으로 구성한 폼의 소스 보기를 하면 꼭 붙어있는 태그가 있다.

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTM1OTA4MjdG9uLCBob3dlgQ1c6kbnHCj7SXQjEO5/4IM=" />


보이지 않는 컨트롤이고, __VIEWSTATE 라는 이름에, 값은 알 수 없는 문자로 되어있다.
asp.net 은 언제나 이 __VIEWSTATE 값을 계속해서 보내며 유지시킨다. 그리고 이벤트 등으로 페이지 처리가 일어날 때 알 수 없는 형식의 이 값들을 참고로 각각의 컨트롤의 상황을 계속해서 유지시킬 수 있는 것이다.

asp.net 이런 행위를 하는 것을 포스트백(Postback)이라고 한다.
서버컨트롤을 사용하면서 매우 중요한 개념이다. 이 강의에서 이 개념을 이해하지 못하신다면, 다른 책이나 강의를 통해서 꼭 이해하기 바란다.

출처를 모르는 곳에서 퍼온 다음 이미지를 보도록 하자.


(영문이지만, 어쩔 수 없다 -_-)

복잡해 보이지만 1번부터 12번까지 하나씩 살펴보자. 우리가 이미 알고 있는 내용이다.

1. 사용자가 GET으로 웹 브라우저로 요청 (eventtest.aspx)
  ▶ 주소창에 입력하는 모든 방식은 GET 방식이다.

2. 서버처리(eventtest.aspx)가 일어난다.
  ▶ asp.net이 해석한다는 말이다.

3. Page_Load 이벤트를 호출.
  ▶ 우리가 늘 프로그램 코드를 넣을 때 사용했던 메서드이다.

4. HTML 응답 생성 
  ▶ 결과물은 그래봐야 <tag>문..

5. (파란 제목의 그림처럼) 사용자 브라우저에 보여짐
  ▶ TextBox, DropDownList, Button 이 보인다. 하단에 Label도 있을 것이다.

6. 사용자가 각각의 값을 입력하거나 클릭하여 <form>을 채운다.
  ▶ 그런 후 [Enter] Button 컨트롤을 누를 것이다.

7. Postback to server: 서버에 포스트백을 보낸다. eventtest.aspx파일로 POST방식으로 요청.
  ▶ <form></form>을 보내는 것과 동일하다. 그러나, asp.net 에서는 이를 '포스트백'이라고 부른다. 상태유지를 하는 코드가 들어가 있기 때문이다. 왜?  Button 과 같은 <form>의 submit 컨트롤이 존재하기 때문이다. (단, 서버컨트롤의 상태 유지를 강제로 하지 않을 수 있게 설정 가능하다)

8. 서버처리(eventtest.aspx)가 일어난다.
  ▶ (2)번과 같은 동작을 한다.

9. Page_Load 이벤트(메서드)를 호출.
  ▶ (3)번과 같은 동작을 한다.

10.  btnEnter_Click 이벤트를 호출.
  ▶ <form>작성 후 클릭한 버튼의 이벤트를 호출한다. 만약 이벤트가 연결되어 있지 않다면 호출할 필요가 없겠지만, 예제에서는 btnEnter_Click 이라는 이벤트를 연결 해놓은 것 같다. 그러므로, 해당 이벤트 메서드를 처리하게 된다. 여기서, Page_Load 이벤트가 앞서 호출되는 것에 집중하자.

11. HTML 응답 생성
  ▶ 처리가 끝났으니, 닷넷은 <tag>형태로 출력할 것이다.

12. 사용자 브라우저에 보여짐
  ▶ 그림을 잘 보면, 사용자가 입력된 값이 그대로 있고, 하단에 처리결과가 출력된 것을 볼 수 있다. (아마도 btnEnter_Click 에서 처리된 것 같다)


(영어로 된 용어가 불편하겠지만, 프로그래머라면 무시하지말고 하나라도 알고 넘어가자.)

위의 그림이 닷넷에서 값을 보낸다는 의미인, 포스트백(Postback)의 과정이다.

이 포스트백이 되었는지의 여부는 IsPostBack 이라는 bool 자료형으로 체크할 수 있다.

aspx 페이지에서

Page.IsPostBack
or
IsPostBack

이다. 일반적으로 실제 사용할 때에는 if(IsPostBack) {..} 을 이용해 포스트백이 안되었을 때(처음 열렸을 때)와 클릭이벤트 등으로 값이 전송되었다라는 의미인 포스트백이 되었을 때를 구분하여 처리를 달리하게 된다.
 
이것은 왜, 어떨 때 필요할까?

아주 적절한 예제가 있다. 
웹에서 자주 이용하는 게시판에서 사용하는 "수정기능"을 생각해보자.

'백문이 불여일행'이니 실행 예제를 위해 postback.aspx 파일을 하나 만들자.

웹폼 컨트롤로 TextBox 두 개를 놓고, Button 을 하나 만들자.
항목은 이름(id="name"), 나이(id="age") 정도? 버튼 Click 이벤트명은 btn_Click 정도로 만들자.
버튼에는 id가 필요없을 것 같다. 프로그래밍 코드로 기능을 넣을 필요가 있다면 말이 다르겠지만.

꼭 직접 만들어보길 바란다. 타이핑 한번한번 할 때 여러분들의 실력은 자기도 모르게 올라가게 되어 있다. 이 것은 진리(-_-)이다. 필자의 예제소스는 다음과 같다.


postback.aspx


<%@ Page Language="C#" runat="server" %>

<script language="C#" runat="server">

 void Page_Load()
 {
 }

 void btn_Click(object o, EventArgs e)
 {
 }


</script>


<form runat="server">

이름 : <ASP:TextBox id="name" runat="server" />
<br>
나이 : <ASP:TextBox id="age" runat="server" />
<br>
<br>
<ASP:Button text="보내기" runat="server" OnClick="btn_Click" />

</form>


여러분이 익히 써 본 코드로 만들면 그만이다. 
이제 프로그래밍 코드에서,

1. Page_Load() 메서드에 IsPostBack 변수를 출력해서, 포스트백 상태를 항상 확인.
2. Page_Load() 메서드에 "Page_Load() 되었음"을 출력.
3. btn_Click 에는 "btn_Click() 되었음"을 출력.


1차적으로 위와 같이 구현하도록 하자. 다음처럼 수정하면 되겠다.


 void Page_Load()
 {
    Response.Write("IsPostBack: " + IsPostBack + "<br>");
    Response.Write("Page_Load() 되었음");
 }
 void btn_Click(object o, EventArgs e)
 {
    Response.Write("btn_Click() 되었음");
 }

이제, 웹브라우저에서 실행해보자.

첫 실행시는 다음처럼 나올 것이다.


IsPostBack 변수값이 "false"로 출력된다. 포스트백이 되지 않았기 때문이다.
그리고 Page_Load() 되었음이 출력된다. (단지 Response.Write() 로 출력했을 뿐이다)

값을 입력하고, Button 을 클릭하여 btn_Click 이벤트를 발생시키자.
이제 <form runat="server"></form>에 지정된 postback.aspx 파일에 submit 이 일어날 것이다.


서버컨트롤로 작성된 이름, 나이 필드의 값이 보내기 버튼을 누르기 전에 입력한 상태 그대로 남아있다. 앞서 단계별로 본 것 처럼 btn_Click() 이전에 Page_Load()가 먼저 일어나는 것에 주목하도록 하자.

이렇게 보내게 되면, 파일로 저장을 하거나 사용자 정보가 저장이 되었다고 가정을 하자.

일반적으로 정보를 수정한다고 하면, 수정할 값이 텍스트박스에 미리 보여지게 된다. (게시판 수정 기능을 생각해보자) 미리 저장된 값은 "수정 페이지가 열릴 시점에" 값을 불러올 것이다.

예제에서는 "데이터를 불러왔다고 가정"하고 자료를 미리 입력하기로 하자.

step 1.
TextBox 컨트롤인 name, age 에 해당 값을 넣기로 하자. 물론 Page_Load() 메서드에 작성한다.

step 2.
수정기능이므로, 그럴듯하게 Button 의 Text를 "보내기"에서 "수정"으로 바꾸자. 이벤트는 그대로 놔둔다. 수정한 결과니까 말이다. 대신 사용자가 수정한 "이름", "나이"를 출력하는 Response.Write()를 넣어보자.

다음은 step1, step2에 맞게 수정된 코드이다.

 void Page_Load()
 {
    Response.Write("IsPostBack: " + IsPostBack + "<br>");
    Response.Write("Page_Load() 되었음<br>");
    // 기존값을 불러왔다고 가정
    name.Text = "김길동";
    age.Text = "25";
 }
 void btn_Click(object o, EventArgs e)
 {
    Response.Write("btn_Click() 되었음<br>");
    // 수정된 결과 출력
    Response.Write("name: " + name.Text + "<br>");
    Response.Write("age: " + age.Text + "<br>");
 }



추가된 코드를 확인하자.
처음 페이지가 열릴 때는 예상대로, name, age에 각각 값이 들어갈 것이다.


이제 이것을 수정해보자. 이름과 나이를 수정하고, "수정"버튼을 눌러 btn_Click 이벤트를 호출하도록 하자.


예상대로, IsPostBack 값은 True로 변경되었다.
그러나, 우리가 변경한 이름과 나이는 수정하기 이전값이다.
아무리 수정해도 변하지 않는다.

이유는 앞에서 말했지만, 클릭이벤트(btn_Click)보다 Page_Load() 가 먼저 실행되기 때문이다. 그러므로, IsPostBack 을 확인해서 수정되기 전(false)에는 기존 자료를 넣어주고, 수정된 후(IsPostBack=true)에는 기존 자료를 넣어주는 과정을 건너뛰어야 할 것이다.

이런 실수는 초보 프로그래머들이 처음 닷넷 컨트롤을 접하고, 게시판 등처럼 작성된 것을 수정하는 기능을 만드는 과정에서 자주 하게된다. asp.net 은 컨트롤의 "이벤트기반 프로그래밍"이라고 볼 수 있다. 단순하지만, 앞으로 복잡한 이벤트가 엮일 때 겪을 수 있는 부분이니 참고하도록 하자.

다음이 수정된 코드이다.

void Page_Load()
{

      Response.Write("IsPostBack: " + IsPostBack + "<br>");
      Response.Write("Page_Load() 되었음<br>");
   if (!IsPostBack)
   {
        // 기존값을 불러왔다고 가정
        name.Text = "김길동";
        age.Text = "25";

   }

 }


기존 자료를 불러오는 조건으로, "페이지가 처음 로드되었을 때"로 지정하면 그만인 것이다.
다시 실행해보자. 잘 작동하는가? ^_^

문제가 있다면 다음 코드를 참고해서 완성해보도록 하자.

postback.aspx



언젠가는 우리가 만들게 될 게시판 수정기능에 지금 사용한 (Page.)IsPostBack 속성이 활용될 것이다. 이외 여러 프로그램에서 asp.net 처리 순서가 이러하기 때문에 서버컨트롤 사용시에 유용하게 사용될 것이다.


"원래 사용한다"라는 개념은 버리셨으면 한다.
필자는 이러한 이유 때문에 사용하면 좋다라고 말해주고 싶다.

프로그래밍에서는 단 1개의 타이핑이라도 "왜?" 라는 이유가 있기 때문이다.


0 Comments
댓글쓰기 폼