본문 바로가기

Window Programming/VB

클래스와 이벤트

■ 클래스와 이벤트

비주얼 베이직을 이용한 ActiveX 프로그래밍에서 빠지지 않는 요소가 클래스 모듈이다. 이 클래스 모듈의 C++이나 Java에서의 클래스와 같은 객체를 생성하는 역할을 수행하는 부분으로 인터넷 프로그래밍에 빠져서는 안돼는 요소이다. 지금부터 비주얼 베이직에 있는 여러 가지 모듈들의 기능의 차이와 클래스 모듈의 세부 사항에 대해서 알아보도록 하자.

2.1 클래스모듈과 기타모듈의 비교

비주얼 베이직에서 제공하는 모듈로는 표준 모듈, 폼 모듈, 클래스 모듈 등이 있다. 이들 각각의 모듈들이 하는 역할이 다르고 프로그램에서 사용되는 곳들도 다르다. 지금부터 각각의 모듈들의 특징과 여러 가지 이벤트들에 대해서 알아보자.

1) 폼 모듈

비주얼 베이직의 가장 기본이 되는 대화상자이자 모듈이다. [Hello World]의 작은 프로그램에서도 사용되었던 것이 폼 모듈이다. 폼 모듈의 가장 큰 특징은 자체가 사용자 인터페이스임과 동시에 여러 가지 컨트롤들을 포함할 수 있는 컨테이너의 역할을 수행하는 것이다. 앞의 비주얼 베이직을 이용한 COM의 구현에서 알 수 있듯이 하나의 클래스는 속성과 메서드를 포함할 수 있었다. 이런 관점에서 폼 모듈 또한 하나의 클래스라 할 수 있으며, 폼에 포함되는 여러 가지 컨트롤들의 속성들과 메서드를 활용하여 프로그래밍을 하는 것은 미리 정의된 클래스를 사용하는 것이라 하겠다. 또한 클래스 모듈에서의 속성, 메서드의 추가와 같이 폼 모듈에서도 동일하게 추가하여 사용할 수 있다.


2) 표준 모듈

표준 모듈은 폼 모듈이나 클래스 모듈과는 달리 이벤트를 소유할 수 없다. 그리고 표준 모듈에서 Public 형식으로 선언되는 변수나 프로시저는 다른 모든 모듈에서 공유할 수 있다

3) 클래스 모듈

클래스는 속성과 메서드를 동시에 가지고 있는 사용자 정의 자료형을 가리킨다. 클래스는 하나의 객체를 이루며 인터페이스를 통한 객체 쌍방향간의 통신을 수행할 수 있다. 클래스는 Public으로 선언할 수 있어 다른 프로젝트나 폼, 클래스에서 사용할 수 있는 OOP를 위한 요소이다. 또한 여러 가지 유형의 인스턴싱 모드를 제시할 수 있어 가장 적합한 유형으로 사용할 수 있다.

2.2 클래스의 이벤트

클래스는 폼 모듈처럼 인스턴스의 생성과 소멸에 관련된 두 가지 이벤트를 가지고 있다. Initialize의 생성 이벤트와 Terminate의 소멸 이벤트가 클래스의 이벤트이다.

1) Initialize 이벤트

Initialize 이벤트는 클래스가 New에 의해서 인스턴스가 작성될 때 가장 먼저 실행되는 이벤트이다. 따라서 이곳에 클래스에서 필요한 특정 변수들을 초기화하는 코드 등을 위치시켜 주로 사용한다.

--------------------------------------------------------------------------------
Private MyCount As Integer ' 카운트를 나타내는 변수 선언

Private Sub Class_Initialize()

' MyCount에 기본 카운터 설정
MyCount = 100

End Sub 
--------------------------------------------------------------------------------

2) Terminate 이벤트

Terminate 이벤트는 클래스가 Nothing으로 선언되어 클래스가 소멸할 때 실행되는 이벤트이다. 따라서 객체가 소멸되면서 수행해야 하는 작업을 이곳에 코드를 위치시켜 주로 사용한다.

--------------------------------------------------------------------------------
' TempClass의 참조변수 선언
Private MyTempCls As TempClass

' TempClass의 초기화
Private Sub Class_Initialize()
Set MyTempCls = New TempClass

End Sub

' 생성한 TempClass의 소멸작업
Private Sub Class_Terminate()

Set MyTempCls = Nothing

End Sub
--------------------------------------------------------------------------------

2.3 클래스에 이벤트 추가하기

1) 클래스 인터페이스 이해하기

인터페이스라는 것의 사전적인 의미는 '접촉면', '경계면'을 말한다. 그러면 클래스의 인터페이스라는 무엇을 의미할까? 바로 클래스가 외부의 다른 대상과의 통신을 위한 길의 역할을 수행하는 하나의 통로라 볼 수 있다. 클래스 내부적으로는 복잡한 계산이 일어나겠지만 사용자는 클래스로 입력하는 데이터의 양식과 클래스에서 출력하여 주는 결과 값만 사용하면 되는 것이다. 이것이 바로 클래스를 사용하는 목적이며, 객체지향 프로그래밍이 탄생하게 된 배경이기도 하다.

클래스에 의해 생성되는 하나의 객체는 이처럼 인터페이스를 통해서 서로간의 통신을 수행한다. 객체에서의 인터페이스의 구성은 다음과 같이 이루어진다.

--------------------------------------------------------------------------------
Incomming Interface : 프로퍼티, 메서드
Outgoing Interface : 이벤트
--------------------------------------------------------------------------------

객체에서의 인터페이스의 구성은 위에서 보듯이 Incomming, Outgoing으로 나누어진다. 프로퍼티나 메서드를 사용하면 특정 데이터가 객체 내부로 들어가 연산이나 여러 가지 특성들을 변경하는 역할을 수행하므로 Incomming Interface라 불린다. 그리고 이벤트는 객체 내부에서의 연산작업이 완료된 후 이벤트가 외부로 나가 해당 객체를 사용하고 있는 다른 객체의 이벤트에 정의된 역할을 수행하므로 Outgoing Interface라 한다.

2) 클래스의 이벤트 정의하기

이벤트는 실제 프로그램에서 사용하는 사용자에게 이루어지는 처리의 결과를 알려주는 역할을 수행하는 것이다. 이처럼 이벤트는 프로그램 내에서 여러 개체간의 통신의 수단으로 이용되고 있다.

① 이벤트 발생

이벤트의 선언문은 반드시 모듈에만 위치할 수 있으며, 표준 모듈에는 선언될 수 없다. 이벤트의 기본적인 선언문은 다음과 같다.

--------------------------------------------------------------------------------
Public Event 이벤트명, (인수 리스트)
--------------------------------------------------------------------------------

이벤트는 선언만 되어서는 아무런 기능을 발휘하지 못한다. 이벤트가 선언되는 곳에서 실제 이벤트가 발생하는 구문을 입력하여야 한다. 이벤트 발생문은 다음과 같다.

--------------------------------------------------------------------------------
RaiseEvent 이벤트명, (인수 리스트)
--------------------------------------------------------------------------------

다음의 이벤트의 선언과 발생하는 구문의 실제 적용 코드를 살펴보자.

--------------------------------------------------------------------------------
' 이벤트 선언
Event TempEvent()

Public Sub TempMethod()

  Static Count As Integer ' 정적변수 선언
  Count = Count + 1

  If Count > 100 Then
    RaiseEvent TempEvent
  End If

End Sub 
--------------------------------------------------------------------------------

② 이벤트 처리

클래스에서 정의한 이벤트를 실제 폼에서 활용하는 방법에 대해서 알아보자. 이벤트 선언과 발생처럼 이벤트를 처리하고자 할 때 이벤트 변수의 선언은 다음 구문 양식을 따른다.  

--------------------------------------------------------------------------------
[Dim | Public | Private] WithEvents 변수명 As 클래스명
--------------------------------------------------------------------------------

클래스에서 정의된 이벤트를 변수로 선언하는 구문이다. 사용 범위에 따른 변수의 선언을 달리할 수도 있다.

실제 변수에 선언한 이벤트를 사용하기 위해서는 이벤트 핸들러의 정의는 다음 구문의 양식을 따라야 한다.

--------------------------------------------------------------------------------
객체명_이벤트명 (인수 리스트)
--------------------------------------------------------------------------------

클래스 부분에서 다루었던 메서드의 호출과 비슷하다. 이벤트 호출의 사이에 다른 코드를 넣을 수도 있다.

이벤트를 활용하는 실제 적용 코드를 살펴보자.

--------------------------------------------------------------------------------
Private WithEvents TempCls As CTempClass ' 이벤트 변수 선언

Private Form_Load()

  ' 객체 생성
  Set TempCls = New CTempClass

End Sub

Private Sub TempCls_TempEvent()

  ' 이벤트 호출

End Sub 
--------------------------------------------------------------------------------

위의 코드에는 실제 이벤트가 호출되었을 때 이루어지는 동작들이 정의되지 않았다. 그러나 이벤트를 활용하는 간단한 코드로써 기억하고 있어야 하는 구조이다. 앞으로 이런 구조들을 활용하여 비주얼 베이직에서의 인터넷 프로그래밍을 수행하고자 하니 이점 유의하기 바란다.

2.4 클래스 이벤트 활용예제

클래스를 이용한 예제를 제작하여 보자. 이번 예제는 폼에 텍스트 박스를 두 개 추가한 뒤 하나의 텍스트 박스에 임의의 숫자를 입력하면 다른 텍스트 박스에서는 앞서 입력한 숫자의 제곱을 구하는 것이다. 클래스의 이벤트가 Outgoing Interface이므로 클래스에서 계산된 결과 값을 우리가 필요로 하는 곳으로 전달할 수 있는 것을 이용하는 것이다.

1) ClsEvent 프로젝트 시작

우선 새로운 표준 EXE 프로젝트를 실행한 뒤 새로운 클래스 모듈을 하나 추가하자. 추가한 클래스 모듈의 이름을 clsSquare로 변경하고, 폼의 이름은 frmClsEvent로 변경하자.


우선 폼 디자인을 수행하여 보자. 폼에 두 개의 레이블과 텍스트 박스, 커맨드 버튼을 각각 추가하여 다음과 같이 속성을 변경하라.

 

--------------------------------------------------------------------------------
● frmClsEvent - 폼 파일이며, Caption 속성을 '클래스 이벤트 활용하기'로 변경하자.
● Label1, Label2 - 레이블 컨트롤이며, Caption 속성을 각각 '숫자를 입력하세요'와 '결과값'으로 변경하자.
● txtNum - 텍스트 박스 컨트롤이며, Text 속성은 공백으로 처리하자.
● txtSquareNum - 텍스트 박스 컨트롤이며, Text 속성은 공백으로 처리하자.
● cmdCalc - 커맨드 버튼 컨트롤이며, Caption 속성은 '제곱 구하기'로 변경하자.

--------------------------------------------------------------------------------

이렇게 변경된 폼 디자인은 다음과 같은 모양을 가지게 된다.


2) 전체 소스코드

ClsEvent 프로젝트에 다음의 소스코드를 입력하도록 하자.

● clsSquare.cls  

--------------------------------------------------------------------------------
Event SquareEvent(Num As Integer)

Public Sub Square(RequestNum As Integer)

  Dim SquareNum As Integer
  SquareNum = RequestNum ^ 2

  RaiseEvent SquareEvent(SquareNum)
End Sub
--------------------------------------------------------------------------------

● frmClsEvent.frm 

--------------------------------------------------------------------------------
Private WithEvents MySquare As clsSquare

Private Sub cmdCalc_Click()

  MySquare.Square (Val(txtNum.Text))

End Sub

Private Sub Form_Load()

  Set MySquare = New clsSquare

End Sub

Private Sub MySquare_SquareEvent(Num As Integer)

  txtSquareNum.Text = Num
  MsgBox "결과를 구했습니다"

End Sub
--------------------------------------------------------------------------------

3) 설명

우선 클래스 모듈의 코드를 살펴보자. 가장 먼저 선언되어 있는 것이 클래스를 선언하는 부분이다. Event SquareEvent(Num As Integer) 라 선언을 하는 것은 앞서 이야기했듯이 이벤트를 사용한다는 것을 미리 알리는 부분이다. 
--------------------------------------------------------------------------------
Public Sub Square(RequestNum As Integer)
  Dim SquareNum As Integer
  SquareNum = RequestNum ^ 2

  RaiseEvent SquareEvent(SquareNum)
End Sub
--------------------------------------------------------------------------------

이후에 추가되어 있는 프로시저는 실제 계산을 수행하는 함수이다. 실제 폼에서 넘어오는 변수의 제곱을 구하여 이벤트를 통해 다시 넘겨주는 기능이 수행된다. 즉 RequestNum에는 폼에 입력되는 값이 넘어오는 것이며, RaiseEvent를 통해 이벤트를 발생시켜 RequestNum의 제곱수를 구한 결과를 SquareNum을 통해 넘겨주게 된다.

폼에 추가되어 있는 코드를 살펴보자. 가장 첫 부분에 Private WithEvents MySquare As clsSquare 라 하여 클래스 변수를 선언하는 부분이 있다. 다만 앞의 다른 선언과는 달리 WithEvents라는 키워드를 사용하여 이벤트를 가지는 클래스를 사용한다는 것은 명시한다.

 

--------------------------------------------------------------------------------
Private Sub Form_Load()
  Set MySquare = New clsSquare

End Sub
--------------------------------------------------------------------------------

실제 코드가 수행되는 순서를 따라가 보자. 우선 폼이 로드되면 클래스 객체를 앞서 선언한 변수에 할당하는 부분이 실행된다.

--------------------------------------------------------------------------------
Private Sub cmdCalc_Click()
  MySquare.Square (Val(txtNum.Text))
End Sub
--------------------------------------------------------------------------------

이렇게 할당된 변수는 클래스 모듈에서 선언한 메서드를 수행한다. 실제 커맨드 버튼을 클릭하였을 때 메서드가 실행되어야 하므로 다음과 같은 메서드의 실행문이 추가되었다. 다만 제곱수를 구하기 위해 메서드에 인수가 같이 가는 형태를 주의 깊게 살펴봐야 한다.


--------------------------------------------------------------------------------
Private Sub MySquare_SquareEvent(Num As Integer)
  txtSquareNum.Text = Num
  MsgBox "결과를 구했습니다"
End Sub
--------------------------------------------------------------------------------

이렇게 수행된 메서드는 메서드 내부에서 이벤트 발생을 일으킨다. 이렇게 발생된 이벤트는 폼에서 이벤트를 수신하게 되는데 [클래스 객체_이벤트 이름]의 프로시저에서 이 부분을 담당하게 되는 것이다. 그렇기 때문에 이 부분에 이벤트에서 넘어온 결과값을 텍스트 박스에 처리하는 부분을 수행하고, 메시지 박스를 통한 결과 수신을 완료하는 부분을 입력하게 되는 것이다.


ClsEvent 프로젝트를 실행하여 보자. 입력란에 제곱으로 구하고자 하는 숫자를 하나 입력한 뒤 제곱 구하기 버튼을 클릭하여 제곱수가 정상적으로 구해지는지 확인하도록 하자.

[그림 4-2] ClsEvent 프로젝트 결과