PROGRAMMING WORKSHOP

COMAddIns | Interface와 Implement 이해하기

VB.Net으로 COMAddIn을 만들어 보자
이것을 개발하는데는 Visual Studio VB.Net버전을 사용한다
uno-weekly VB.Net관련에서 조금씩 감각을 익히시고,
워크샵의 VB.Net다른 코너에서 조금씩 감각을 익히셨다면
충분하게 만들수 있는 참으로 기특한 프로그래밍이 될 것이다

그러면 COMAddIn이 뭘까???
COMAddIns는 COMAddIn의 집합체이니
COMAddIn을 하면 된다
말 그대로 Add-In 추가기능 화일인데 ..
COM라이브러리로 만들어 졌다는 것이다
VB.Net과 대별하여 이전의 DLL화일들이
모두 COM라이브러리라고 보시면 된다
아래를 실행 해보시면 ..

Sub checkCOMAddins()
Dim oCom As COMAddIn
Dim iRow As Integer
iRow = 1
With Worksheets.Add
    
    .Range("A1").Resize(, 5) =  _
	Array("Application", "Creator", _
	"Description", "GUID", "progID")
    For Each oCom In Application.COMAddIns
        iRow = iRow + 1
        .Range("A" & iRow).Resize(, 5) = Array( _
                    oCom.Application.Name, _
                    oCom.Creator, _
                    oCom.Description, _
                    oCom.GUID, _
                    oCom.progID)
      
    Next
    With .UsedRange
        .Font.Name = "맑은 고딕"
        .Font.Size = 10
        .Columns.AutoFit
    End With
End With
End Sub

현재 엑셀에서 사용하고 있는 COM 추가기능목록이고
이 목록중의 하나의 것을 만들어 보도록 하자
COMAddIn으로 사용되는 것은
VB.Net으로 만들어서 사용한다고 해도
또 방법이 여러가지가 있다
대표적인 것은

1)VSTO로 만들어서 사용하는 방법(Visual Studio의 템프릿)
2)Office용 AddIn 템프릿(Visual Studio에서 제공)으로 만드는 방법
3)일반적인 COM 라이브러리를 만드는 방법

이중에서 맨땅에 헤딩하기 3번째 방법을 먼저 해보도록 한다
이것은 템프릿같은 것 없이 크래스라이브러리를 쌩짜로 만든다
실은 이것은 워크샵 VB.Net코너에서 한번 다루었지만
다시 위의 3가지를 비교하면서 다시 만들도록 하자
이것을 만들때 Visual Studio Express버전으로는 곤란하다
되기는 되지만..
엑셀참조를 위한 Tlb화일을 별도록 생성하여야 하고
Register에 등록하는 과정을 수동으로 하거나 복잡하기 짝이 없다
하지만 Visual Studio 정품에는 이것이 자동으로 만들어진다



만들게 될 크래스라이브러리의 프로젝트속성창에서
위의 두개를 꼭 첵크해주어야
.Net시스템에서 COM시스템으로 가능하게 해주게 된다
그래서 Visual Studio 2010 정품으로 만드는 것으로 진행한다

COMAddin을 시작하기전에 좀 이해하기 까다로운것이 하나 알고 가야 할 것이 있다
VB.Net 이전에 사용되던
Interface와 Implement라는 키워드가 있다
.NetFrameWork 를 기반으로 하는 VB.Net이전
VB6 에서 사용하던 즉 COM라이브러리에서는
Interface와 Implement라는 키워드가 사용되었다
이것이 VB.Net에서도 계속 유지가 되는 키워드이다
아래와 같이 크래스라이브러리 프로젝트를 하나 만들고



Class1.vb모듈시트가 열려 있을 것이고 아래와 같이 달랑
크래스 열고, 닫고만 작성되어 있다

Public Class Class1

End Class

이 크래스 위에 아래와 같이 작성한다


Public Interface IMyInterface
    Sub proc_A()
    Sub proc_B()
    Sub proc_C()
    Function fun_A(ByVal iX As Integer) As Integer
End Interface

Public Class Class1

End Class

Interface라는 키워드를 사용하였다...
이것이 도대체 뭐지??라는 궁금증을 갖고 Interface는 Implement라는
키워드와 쌍을 이루고 다닌다는 점을 잊지 마시기바란다
위의 상태에서..
아래의 그림과 같이



Class 모듈내에 Implement라는 키워드를 입력하고 한칸띄우고
I라는 문자를 치면 (위의 Interface의 이름을 I로 시작하게 지었다)
Interface의 이름은 마음대로 만들어도 되지만
내장된 다양한 Interface는 모두 I문자로 시작되어 있으니
이것을 따르면 좋을 것이다
그래서 I를 입력하면 제공되는 다양한 Interface목록이 나타난다

아하..목록상의 열쇠같이 생긴 아이콘이 Interface를
의미하는 것이구나!!를 챙기시고..

이중에 하나가 위에서 작성한 IMyInterface가 나타나고 이것을
선택하고 엔터키를 치는 순간 아래와 같이 작성된다



내장된 Interface가 아니고 사용자정의 Interface를 만들고
이것을 크래스에서 사용하게 된 것이다
Implement는 말 그대로 Interface를 구현하겠다는 이야기다
Interface는 내용은 하나도 없고 제목만 있는 것이다
이것의 내용을 작성하고 실천,실행(Implement)하겠다는 이야기다
만약에 Class1 밑에 Class2를 하나 만들고 똑같이 그 속에서
Imlement IMyInterface를 입력하면 똑같이 만들어진다
이 말은 하나의 Interface를 여러개의 Class에서 같이 사용할수
있다는 의미가 된다



Interface는 코드의 내용은 없다 프로시져,함수,속성등의
이름과 정보의 타입등만 규정지어지는 템프릿같은 존재이고
실제의 코드의 모든 내용은 크래스에 같은 이름과 타입으로 전개 되는 것이다
아래와 같이 Module을 하나 추가하고 위의 크래스를 구현해보자


Public Interface IMyInterface
    Sub proc_A()
    Sub proc_B()
    Sub proc_C()
    Function fun_A(ByVal iX As Integer) As Integer
End Interface

Public Class Class1
    Implements IMyInterface
    Public Function fun_A(ByVal iX As Integer) As Integer Implements IMyInterface.fun_A
        Return True
    End Function
    Public Sub proc_A() Implements IMyInterface.proc_A
        MsgBox("Class1에서 호출한 프로시져")
    End Sub
    Public Sub proc_B() Implements IMyInterface.proc_B

    End Sub
    Public Sub proc_C() Implements IMyInterface.proc_C

    End Sub
End Class
Public Class Class2
    Implements IMyInterface

    Public Function fun_A(ByVal iX As Integer) As Integer Implements IMyInterface.fun_A
        Return True

    End Function

    Public Sub proc_A() Implements IMyInterface.proc_A
        MsgBox("Class2에서 호출한 프로시져")

    End Sub

    Public Sub proc_B() Implements IMyInterface.proc_B

    End Sub

    Public Sub proc_C() Implements IMyInterface.proc_C

    End Sub
End Class

Module myModule
    Sub main()
        Dim oCls1 As New Class1
        oCls1.proc_A()
		
        Dim oCls2 As New Class2
        oCls2.proc_A()
    End Sub
End Module

모듈시트를 추가 삽입할 것없이 그냥 한장의 크래스화일에
계속 추가해도 괞찮다..VB6에서는 이런 것들을 모두 각각의 화일로
만들었으나(물론 VB.Net에서도 그렇게 해도 되고...한장에 몰아서 해도 되고)
위와 같이 줄줄이 한장에 처리하여 편리하다
컴파일될 때 알아서 컴파일러가 알아서 분산처리하여 만든다
이것을 실행시켜보려면..윈도우폼도 없고..Class모듈만 달랑있으니까..
실행할 인터페이스가 있어야 한다
아래의 그림과 같이 프로젝트속성화일을 열고
Application Type을 Console Application으로 선택한후
StartUp Object를 Sub Main이나 혹은 myModule을 선택하고
디버깅 실행하면 크래스를 개체화시켜서 일을 시켜 볼 수 있다



이제 의문이 생긴다..
아니 Interface와 상관없이 개체가 생성되잖아..
그런데 뭐한다고 복잡하게 Interface라는 것을 만들어서
연결하고 자시고 하는 것이지???!!

아래의 그림과 같이
크래스에서 메소드등을 실행하면(Implements) 연결된 Interface가
실행되는 셈이고 이말은 개체가 만들어지는 것이 Interface를 통한
개체가 만들어졌다고 보면 되는 것이다



글쎄..그러니까..왜 그렇게 복잡하게 하느냐구??!!
그림과 같이 예를 들어서
쇼핑몰에서 고객의 지불방법이 다양하다고 치자
신용카드를 통한 절차는 Class_A에서 하고
현금을 통한 절차는 Class_B로 하고
또 다른 어떤 경로를 통한 지불절차는 Class_C라고 한다
그런데 앞으로도 어떤 경로로 지불하는 방법이 생길지 모른다
또 다른 지불방법를 구현하는 크래스가 몇개가 만들어 질지도 모른다
또 현재 사용하고 있는 Class_A나 Class_B도 크래스내부를 보수하여야
할지도 모른다
그렇다면 어떤 하나의 절차를 위하여 다른 것도 죄다 영업중단을
하여야 하는 경우가 생길 것이다
이때 이런 모든 추가작업이나 보수작업등을 업무에 지장없이
하는 방법은 일반적인 방법으로 Inteface를 가볍게 물고 있고
나머지는 영업에 지장없이 부품을 갈아끼우고 보수할수가 있게 되는 것이다
또한
프로그램이 돌아갈때, 모든 지불절차를 하나의 크래스에 넣은 것과
분산하여 넣고, 필요한 것만 Interface를 통하여 알아서 Client와
연결이 되니까..프로그램이 가벼워지게 되는 것이다
이런 것을 개체지향프로그래밍의 다형성(Polymorphism)의 구현방법중의
하나라고 할 수 있다
아니..VBA로 엑셀프로그래밍과 좀더 확장하여 Add-In을 만들고 싶은데
뭐 이런 복잡한 것을 알아야 하나요???
왜냐면 COM라이브러리가 바로 Interface를 통하여 개체가 만들어지는
형식이라서 COMAddIn을 만들때 알고 있어야 하기 때문이다
그리고 알고 있어서 나쁠것도 없다

자동차의 기어를 1단,2단,3단등으로 바꾸는 것은
기어의 손잡이가 Interface인 셈이고
나머지 안보이는 곳에서 일하는 기어 박스가 크래스인 셈이다
지금까지 하는 내용은 일반적인 크래스와 인터페이스이야기니
Express버전에서도 모두 되는 것들이니 같이 보셔도 좋다

***[LOG-IN]***