Silverlight를 설치하려면 여기를 클릭합니다.*
Korea 대한민국변경|Microsoft 전체 사이트
MSDN
|개발자 센터
MSDN Home   MSDN Home
MSDN 홈 > MSDN Magazine > 2001년 기사 > Visual Basic.NET: 개발 능력을 향상시키는 새로운 프로그래밍 모델과 언어

Visual Basic.NET: 개발 능력을 향상시키는 새로운 프로그래밍 모델과 언어

Ted Pattison

요약? Visual Basic.NET은 Visual Basic을 Microsoft .NET Framework에 맞도록 재구성한 것입니다. 여러 단계의 수정 과정을 거친 Visual Basic.NET은 Visual Basic 6.0에 비해 사용하기 편리하고 강력하며, 이전에는 C++을 사용해야 가능했던 시스템 리소스에 대한 액세스를 제공합니다. 추가된 기능 중 가장 중요한 것은 개체 상속입니다. Visual Basic.NET에서 모든 관리 유형은 시스템 개체에서 얻어집니다.
가장 중요한 언어 기능은 공통 언어 런타임에 의해 관리되고 보다 나은 메모리 관리 기능을 제공하는 가비지 수집입니다. 유니버설 유형 시스템은 보다 큰 상호 운용성을 제공함으로써 Visual Basic.NET에 향상된 힘과 유연성을 제공하는 데 기여합니다.

지금까지 해 본 경험이 없다면, 이제 Visual Basic.NET 프로그래밍 언어를 배워볼 때입니다. 이 문서의 목표는 Visual Basic.NET 및 새로운 Microsoft®.NET 플랫폼을 간략하고도 집중적으로 소개하는 것입니다. Visual Basic.NET에 대해 알기 위해서는 .NET 플랫폼의 몇 가지 핵심적인 측면을 이해해야 합니다. 이 문서의 목적은 Visual Basic.NET의 기본적인 것부터 설명하는 것으로서, 이를 위해 새로운 프로그래밍 모델 및 .NET 플랫폼의 실행 엔진인 CLR(Common Language Runtime)의 고급 아키텍처에 대한 논의부터 시작하겠습니다.
CLR이란 무엇이며 어떻게 작동하는지 설명하는 한편, Visual Basic.NET을 사용하는 몇 가지 예를 제공할 것입니다. 앞으로 보게 되겠지만, Visual Basic®은 CLR 및 이와 관련된 프로그래밍 모델을 수용할 수 있도록 수정 과정을 거쳤습니다. 그 결과 Visual Basic.NET은 많은 새로운 개체 지향 디자인 기능 및 이전 버전의 Visual Basic에 비해 훨씬 높은 수준의 유형 안전성을 갖게 되었습니다.
또 한 가지 알아 두어야 할 것은 Visual Basic.NET에서는 이전 버전의 Visual Basic에서 사용되었던 아주 적은 수의 몇 가지 구문 형식이 삭제되었다는 것입니다. 따라서 Visual Basic 6.0에서 작성된 코드를 컴파일링하려면 여러 가지 수정 작업을 해야 합니다. 또한 Visual Basic.NET에서 최상의 코드를 작성하려면 Visual Basic 6.0에서는 지원되지 않는 기능과 구문을 사용해야 합니다. 그러므로 Visual Basic 6.0 프로젝트를 Visual Basic.NET으로 마이그레이션하려면 일반적으로 단순한 포팅이 아니라 다시 쓰기 작업을 해야 합니다.
Visual Basic 6.0 프로젝트를 Visual Basic.NET으로 마이그레이션하는 작업에는 상당한 다시 쓰기 작업이 포함되는데, 그 이유는VBA(Visual Basic for Applications) 런타임 또는 ActiveX® Data Objects(ADO)와 같은 이전 라이브러리에 대한 의존성 때문입니다. 효율적인 .NET 프로그래머가 되려면 CLR으로 구축된 공유 클래스 라이브러리를 완벽하게 수용해야 합니다.
Visual Basic.NET은 CLR 및 .NET 프레임워크를 위해 특별히 만들어진 여러 가지 새로운 언어 중 하나입니다. 많은 주목을 받고 있는 또 다른 언어는 C#입니다. Visual Basic을 사용하는 다른 많은 프로그래머들처럼 C#을 어떻게 Visual Basic.NET에 비교할 수 있는지 의아해 할 수도 있습니다. Visual Basic.NET처럼 C#은 CLR 및 .NET 플랫폼 전용으로 만들어진 언어입니다. 그러나 Visual Basic.NET과 달리 C#은 C와 C++에 이미 익숙한 프로그래머가 편리하게 사용할 수 있도록 만들어진 것입니다. 이 글에서는 이러한 언어 중 어느 하나를 선택하는 데 도움이 되도록 두 언어의 몇 가지 핵심적인 차이점에 대해 설명합니다. 그러나 어떤 언어를 사용하더라도 CLR 및 .NET 프레임워크의 장점을 최대한 활용하는 소프트웨어를 작성할 수 있습니다. 먼저 .NET 플랫폼의 핵심 개념에 대한 설명부터 시작하겠습니다.

맨 위로


CLR의 역할
.NET 플랫폼을 위해 작성된 코드는 CLR의 제어 아래 실행됩니다. CLR은 COM, MTS(Microsoft Transaction Services), COM+의 기존 런타임 계층을 대체하기 위해 만들어진 것이라는 점을 알아 두어야 합니다(그림?1 참조). 그림과 같이 CLR은 궁극적으로 Visual Basic 런타임 계층의 필요성을 없애줍니다.
분명히 CLR은 COM을 하룻밤 사이에 대체하지는 않을 것입니다. 많은 기업은 COM, MTS, COM+ 등에 기반한 응용 프로그램에 대해 작성된 코드에 상당한 투자를 해 왔습니다. 그러므로, COM 기반 소프트웨어 및 CLR용으로 작성된 소프트웨어 사이의 상호 운용성은 중요한 문제입니다. Microsoft는 CLR-COM 간 상호 운용성 계층이 가능한 유연성 있고 효율적으로 작동하도록 하기 위해 많은 투자를 해 왔습니다. 그러나 Microsoft의 전문가는 장기적으로 Windows에 대한 대부분의 투자가 CLR을 .NET 플랫폼으로 옮기는 데 집중될 것으로 예측하고 있습니다.
CLR의 제어 아래에서만 실행하도록 작성된 코드를 관리 코드라고 합니다. COM 및 Win32® API에 의존하는 이전 코드는 비관리 코드라고 합니다. Visual Basic 6.0은 비관리 코드만을 생산할 수 있는 반면, Visual Basic.NET은 관리 코드만을 생산할 수 있습니다. 두 버전의 Visual Basic에 대한 근본적인 차이점이 바로 여기에 있습니다.
Visual Basic 팀은 관리 실행 가능 개체(DLL 및 EXE)를 생산할 수 있는 새로운 버전의 Visual Basic 컴파일러(VBC.EXE)를 개발했습니다. 예를 들어 Visual Basic.NET 컴파일러에 둘 이상의 Visual Basic 소스 코드 파일을 공급함으로써 관리 DLL을 만들 수 있습니다. 이전 버전의 Visual Basic과는 달리 Visual Basic.NET 소스 코드 파일은 일반적으로 .VB를 확장자로 갖는다는 사실에 주의하십시오. Visual Basic 소스 코드의 쓰기 및 컴파일링을 훨씬 쉽게 만들어주기는 하지만, Visual Studio.NET은 Visual Basic.NET으로 소프트웨어를 작성할 때 반드시 필요한 것은 아닙니다. 어떤 편집기에서라도 Visual Basic.NET 소스 코드를 작성하고, 명령줄에서 DLL과 EXE를 만들 수 있습니다.
Visual Basic.NET은 전체 프로젝트의 모든 코드를 단 하나의 소스 파일에서 관리할 수 있도록 해 주기 때문에 소스 코드의 관리가 간편합니다. 이전 버전의 Visual Basic과는 달리 각 클래스를 별도의 .CLS 파일에 정의할 필요가 없습니다. 물론 하나의 프로젝트에 대한 코드를 많은 수의 .VB 파일에서 관리하고 이를 하나의 바이너리로 컴파일링하여 배포할 수 있습니다.
또 하나의 새로운 멋진 기능은 Visual Basic.NET에서 NMAKE.EXE 유틸리티와 MAKEFILE을 사용하여 생산 빌드를 자동화할 수 있다는 것입니다. 다수의 개별 소스 파일을 관리하고 테스트 및 생산 빌드를 지속적으로 컴파일링하는 기업은 이것이 Visual Basic 6.0보다 향상된 기능이라는 것을 알 수 있을 것입니다.

맨 위로


관리 유형
단순한 콘솔 기반 응용 프로그램을 Visual Basic.NET으로 작성하고 컴파일링하는 데 어떠한 것이 필요한지 살펴보도록 합니다. 그림?2의 코드를 통해서 알 수 있듯이 CLR용으로 작성된 코드는 관리 유형이라는 개념에 기반한 것이라는 점을 알아 두어야 합니다. 이 예에는 MyApp 및 Class1 등 두 가지 관리 유형의 정의가 포함되어 있습니다.
MyApp 모듈에는 이 콘솔 응용 프로그램의 진입점을 뜻하는 Main이라는 이름의 단일 메서드가 포함되어 있습니다. Main 메서드의 구현은 Class1의 인스턴스를 만들고 Method1을 호출합니다. Method1의 반환값은 콘솔 창에 메시지를 쓰는 데 사용됩니다. 이 예는 Visual Basic.NET이 제공하는 새로운 구문상의 편리함을 보여줍니다. 이제 코드 한 줄에 변수를 선언하고 초기화할 수 있습니다.
그림?2의 다른 관리 유형 정의는 Class1입니다. 이 클래스에는 Method1이라는 하나의 메서드가 들어 있습니다. Method1에는 또한 Visual Basic.NET이 제공하는 새로운 편리함이 있습니다. Method1은 반환문을 사용하여 반환값을 호출기에 반환합니다. Visual Basic.NET을 사용하면 더 이상 기능 이름을 사용하여 반환값을 할당할 필요가 없습니다.
마지막으로 CLR 클래스 라이브러리의 Console 클래스 액세스에 대한 그림?2를 살펴봅니다. Console 클래스의 WriteLine을 호출하는 코드는 System이라는 단어에 의해 한정된다는 점을 기억합니다. 이 경우 System은 이름 공간으로 사용되고 있습니다. 이름 공간이라는 개념은 CLR에 매우 중요하며, 따라서 Visual Basic.NET에 아주 중요합니다. 다른 라이브러리에서 관리 유형을 확인할 때 이름 공간이 어떻게 작동하는지를 이해해야 합니다.
이름 공간은 관리 유형을 정의하는 사용자 정의 범위입니다. 대부분의 CLR 기본 유형은 System.Object, System.Int32, System.String 등과 같은 System 이름 공간 안에서 정의됩니다. 이름 공간은 System.Data.DataSet와 같은 클래스를 갖고 있는 System.Data의 경우처럼 다른 이름 공간에도 위치할 수 있다는 점에 주의합니다.
Visual Basic.NET은 이름 공간 안에 유형에 어긋나는 프로그래밍이 선언되었을 때 Imports 문을 통해 구문상의 바로 가기를 제공합니다. 예를 들어 Visual Basic.NET 소스 파일에 다음 줄을 추가한다고 가정해 봅시다.
Imports System
이 Imports 문은 아래에서 볼 수 있는 바와 같이 WriteLine 메서드를 자격 없이 호출할 수 있습니다.
Console.WriteLine ' this can be used
System.Console.WriteLine ' instead of this
C#에서 using 문을 사용하는 것은 Visual Basic.NET Imports 문에 동일한 지원을 제공한다는 사실을 기억합니다. 또한 Imports 문은 다른 관리 유형의 이름을 입력할 때 명령문을 축약적으로 만드는 구실만을 한다는 사실을 이해해야 합니다.

맨 위로


Visual Basic.NET 컴파일러 사용
명령줄에서 다음 명령을 실행함으로써 그림?2의 소스 코드를 콘솔 응용 프로그램 EXE로 컴파일할 수 있습니다.
vbc.exe /target:exe hello.vb
				
이 예의 코드는 매우 간단하면서도 .NET 플랫폼을 위한 소프트웨어 개발의 몇 가지 중요한 측면을 보여줍니다. Visual Basic.NET 컴파일러로 프로젝트를 성공적으로 만들게 되면 둘 이상의 관리 유형 정의를 가진 바이너리를 얻게 됩니다. 이렇게 하면 이러한 관리 유형을 CLR의 제어 아래 로딩하고 실행할 준비가 갖추어지는 것입니다.
CLR의 프로그래밍 모델은 클래스, 인터페이스, 구조, 열거 등 네 가지 주요 관리 유형을 인식합니다. 그림?3은 각 관리 유형이 Visual Basic.NET에서 어떤 모습으로 나타나는지를 보여줍니다.
이전 버전의 Visual Basic과는 달리 Visual Basic.NET은 UDT(User-Defined Type) 또는 유형 키워드를 지원하지 않습니다. UDT는 구조 유형으로 대체되었습니다. 하나의 구조 유형은 이것이 값 유형이라는 점에서 UDT와 비슷합니다.구조 유형은 스택에 할당될 수도 있고, 다른 유형에 완전하게 내장될 수도 있습니다. 구조는 데이터를 저장하고 넘겨주는 보다 효율적인 방법을 제공하기 때문에 클래스에 대한 유용한 대안이 됩니다. 구조는 공용 메서드를 나타낼 수 있고 심지어 인터페이스를 구현할 수도 있기 때문에 구조 유형이 UDT에 비해 훨씬 많은 용도를 갖고 있다는 점을 알아 두는 것도 중요합니다. 적은 양의 개체를 만드는 데 사용되는 관리 유형으로서 구조를 이해할 필요가 있습니다.
CLR 및 Visual Basic.NET은 인터페이스 기반 프로그래밍에 대한 멋진 지원을 갖고 있습니다. Visual Basic 6.0과는 달리 더 이상 클래스 구조를 사용하여 인터페이스 정의를 꾸며낼 필요가 없습니다. 그림?3은 인터페이스를 정의하고 이를 클래스에서 구현하는 데 필요한 기본 구문을 보여줍니다. 이 간단한 예를 통해 인터페이스 기반 프로그래밍의 구문이 Visual Basic 6.0보다 훨씬 보기 좋다는 것을 알 수 있을 것입니다.
공유 구성원은 Visual Basic에 익숙한 많은 프로그래머에게는 새로울 CLR 프로그래밍 모델의 또 다른 핵심 개념입니다. 예를 들어 하나의 클래스는 인스턴스 메서드와 인스턴스 필드뿐만 아니라 공유 메서드와 공유 필드를 가질 수 있습니다. 이는 클래스에 단지 인스턴스 구성원만이 있는 Visual Basic 6.0과 다른 점입니다.
공유 구성원은 클래스에서 인스턴스를 만들지 않고서도 액세스할 수 있다는 점에서 인스턴스 구성원과 다릅니다. 그림?3을 통해 간단한 예를 들어봅시다. 공유 메서드로 표시되어 있는 Class1의 Method3을 살펴봅니다. 키워드인 Shared in Visual Basic.NET은 C#, C++, Java 등과 같은 언어의 정적인 키워드와 같은 의미를 갖고 있다는 점에 주의합니다.
클라이언트는 공유 메서드의 이름을 클래스 이름과 함께 다음과 같이 호출함으로써 공유 메서드를 액세스할 수 있습니다.
Class1.Method3
				  
하나 더 알고 있어야 할 사실은 CLR의 프로그래밍 모델은 Visual Basic.NET Module 유형에 대한 직접적인 매핑을 갖고 있지 않다는 것입니다. Visual Basic.NET 프로그래밍 언어에는 이전 버전의 Visual Basic에 있는 .BAS 모듈과 같은 것을 제공하기 위한 Module 유형이 들어 있습니다. 그러나 DLL이나 .EXE를 만들 때 Visual Basic.NET 컴파일러는 소스 코드의 각 모듈 유형을 CLR에 의해 로딩되고 실행될 수 있는 관리 클래스로 변환해 줍니다.
모듈은 개체를 만드는 데 사용할 수 없는 특별한 클래스 유형으로 보아야 합니다. 모듈은 단지 공유 구성원만을 포함할 수 있으며 인스턴스 구성원은 가질 수 없습니다. 한 모듈의 모든 구성원이 암시적으로 공유된다고 하더라도 Shared 키워드를 어느 한쪽에 추가하게 되면 컴파일 시간 오류가 발생하므로 항상 신중해야 합니다.
마지막으로 모듈 유형은 Visual Basic.NET의 클래스 유형에 비해 구문상의 편리함을 제공한다는 점을 알아둡니다. 모듈 이름을 사용하지 않고도 모듈에 정의된 공유 메서드를 호출할 수 있습니다. 클래스에서 공유 메서드를 호출할 경우에는 반드시 공유 이름을 사용하거나, 그렇지 않을 경우에는 클래스 이름과 함께 Imports 문을 추가해야 합니다.
CLR의 프로그래밍 모델에는 또한 몇 가지 익숙한 추상화(abstraction)가 들어 있습니다. 클래스와 구조는 저장소의 입력된 단위를 정의하는 필드를 사용하고 메서드를 사용하여 동작을 제공합니다. CLR은 또한 속성을 인식합니다. 이전 버전의 Visual Basic을 통해 알고 있듯이 속성은 클라이언트에게 표시된 필드로 나타나는 메서드(또는 일련의 메서드)입니다. 속성을 선언하는 문은 Visual Basic 6.0과 Visual Basic.NET 사이에서 바뀌지만, 이들을 사용하는 동기는 정확하게 같은 것입니다. 여기서 중요한 것은 속성의 추상화가 CLR의 원본으로 사용되는 프로그래밍 모델에 의해 인식된다는 점입니다.
CLR은 COM 및 Visual Basic 6.0과 마찬가지로 색인된 속성을 제공한다는 점을 알아 두는 것이 좋습니다. 그 결과 다음과 같은 클라이언트 코드를 보게 되는 경우가 가끔 생깁니다.
Dim s As String
s = Object1.Property1(10)
색인된 속성은 또한 클래스의 기본 속성으로 할당될 수 있습니다. C#에서 "indexer"라는 용어는 기본 설정으로 표시된 색인된 속성을 뜻합니다. 아래는 기본 색인된 속성을 액세스할 때 클라이언트 코드가 어떻게 표시되는지를 보여주는 예입니다.
Dim s As String
s = Object1(10)
속성은 색인되지 않으면 클래스에 대한 기본 설정으로 표시될 수 없습니다. 이는 이전 버전의 Visual Basic과 크게 달라진 점입니다. 아래는 비색인된 기본 속성을 텍스트 상자에서 검색하는 Visual Basic 6.0의 예입니다.
Dim var1 As Variant
var1 = frmMain.txtCustomer
이전 버전의 Visual Basic은 비색인된 기본 속성이 포함됨으로써 발생하는 불명확성이라는 문제를 갖고 있습니다. Visual Basic 컴파일러는 어떻게 사용자가 텍스트 상자의 기본 속성이나 참조를 실제 텍스트 상자에 할당하려고 하는지 알 수 있습니까?
Visual Basic의 이 불명확성을 해결하는 고전적인 방법은 Set 키워드를 사용하여 개체의 기본 속성 값의 할당과 개체 참조의 할당을 구분하는 것입니다. 예를 들어 참조를 기본 속성 값 대신 텍스트 상자 개체에 할당하려고 하는 경우에는 다음과 같은 코드를 작성합니다.
Dim var1 As Variant
Set var1 = frmMain.txtCustomer
방금 본 것과 같이 이전 버전의 Visual Basic은 비색인된 기본 속성으로 인한 불명확성 때문에 Set 키워드를 요구합니다. Visual Basic.NET은 비색인된 기본 속성을 제거하므로 Set 키워드는 더 이상 필요하지 않습니다. 사실상, Visual Basic.NET은 할당 작업을 위한 Set 키워드를 지원하지 않습니다. 이는 개체 참조를 할당하기 위해 Set 키워드를 쓰게 되면 컴파일 오류가 발생한다는 뜻입니다. Visual Basic 6.0을 Visual Basic.NET으로 마이그레이션하면 상당히 큰 구문상의 차이가 발생한다는 점을 인정해야 합니다.

맨 위로


위임 및 이벤트
위임은 CLR 프로그래밍 모델에 핵심적인 새로운 개념입니다. 위임은 유형 안전 기능 포인터로 작업할 수 있도록 해 주는 특별한 유형의 관리 클래스입니다. 각 위임 유형은 단일 메서드 서명에 기반한 것입니다. 하나의 위임의 인스턴스를 만들 경우에는 메서드 구현의 주소와 이에 상응하는 서명을 제공해야 합니다. 일단 위임 인스턴스를 만들고 나면 메서드를 실행하기는 아주 쉽습니다.
그림?4는 위임을 선언하고 사용하는 데 요구되는 가장 중요한 Visual Basic.NET 구문을 보여줍니다. 키워드 Delegate 및 AddressOf의 사용에 주의합니다. 또한 아래 예를 통해 나오는 결과는 같지만, 길이에 있어서 아주 긴 구문과 보다 간략한 구문이 있다는 것도 알 수 있습니다. 위임이 무엇이고 이들이 어떻게 작동하는 것인지 알게 되면, CLR이 이를 사용하여 어떻게 멀티캐스팅 및 이벤트와 같은 고급 기능들에 대해 복잡한 지원을 제공하는지 알 수 있습니다.
멀티캐스트 위임은 코드 한 줄을 사용하는 일련의 메서드 구현의 실행을 활용하는 기능 포인터의 모음이라고 할 수 있습니다. Delegate 키워드를 사용하여 위임을 만들 때 Visual Basic.NET 컴파일러가 단순한 위임과 반대되는 멀티캐스트 위임을 만든다는 사실을 기억해야 합니다. 이를 통해 다양한 메서드 구현을 하나의 위임에 연결할 수 있는 기능을 제공받을 수 있습니다.
다음 코드는 그림?4에 나오는 예의 한 가지 변형을 보여주는 것입니다.
Dim d1, d2, d3 As Delegate1
d1 = AddressOf Sub1
d2 = AddressOf Sub2
' create d3 which is a multicast of d1 and d2
d3 = CType(System.Delegate.Combine(d1, d2), Delegate1)
d3("Firing two method implementations at once")
세 번째 위임인 d3은 다른 두 개의 조합으로 만들어집니다. 예로 들고 있는 코드의 마지막 줄은 Sub1과 Sub2에 대한 메서드 구현을 실행합니다. 이 예에서는 멀티캐스트 위임을 사용하여 두 구현을 실행하고 있지만, 원하는 만큼 많은 메서드 구현을 연결하고 실행할 수 있습니다. CLR은 실제로 호출을 실행하는 플러밍(plumbing) 상세 사항과 관련된 문제를 가지고 있습니다. 위임 및 모든 메서드가 공통의 서명을 공유하고 있는지 확인할 필요가 있습니다.
이제 멀티캐스트 위임의 기본 아이디어가 이해되었으므로 CLR이 어떻게 관리 클래스의 이벤트를 지원하는지 알 수 있습니다. CLR 이벤트 아키텍처는 멀티캐스트 위임을 사용하여 메서드 구현을 하나 이상의 수신기 개체에 실행하는 소스 개체에 대한 아이디어에 기반하고 있습니다.
Visual Basic 6.0의 경우에서와 마찬가지로, Visual Basic.NET 클래스는 메서드, 필드, 속성뿐 아니라 이벤트를 가질 수 있습니다. 그림?5는 두 개의 수신기 클래스를 이벤트 소스 클래스와 함께 등록하는 데 요구되는 기본적인 코드를 보여줍니다. Visual Basic.NET에서 이벤트가 작동하는 방식은 구문에 있어서 Visual Basic 6.0에서와 비슷합니다. 예를 들어 Visual Basic.NET은 Event, RaiseEvent, WithEvents 등 비슷한 키워드를 제공합니다. Visual Basic.NET은 또한 수신기 메서드를 만드는 데 필요한 Handles 키워드를 제공합니다.
이벤트 프로그래밍에 필요한 구문이 대부분 동일한 데 비해, 아래에서 사용된 플러밍(plumbing)은 Visual Basic 6.0과 비교해 크게 바뀌었습니다. 이전 버전 Visual Basic의 이벤트는 COM 및 ConnetionPoint 인터페이스에 기반하고 있습니다. 앞서 말했듯이 CLR의 이벤트는 멀티 캐스트 위임에 기반하고 있습니다. 이벤트를 포함하고 있는 클래스는 알림을 수신기 개체에 보내는 이벤트 소스 개체를 만드는 데 사용될 수 있습니다.
Event, RaiseEvent, WithEvents, Handles와 같은 키워드의 사용은 Visual Basic.NET 컴파일러가 배후에 있는 위임 등록을 처리할 수 있는 많은 수의 기타 코드를 만들도록 지시합니다. 이는 이벤트를 올리거나 수신할 때 직접적으로 위임을 다룰 필요가 없다는 것을 뜻합니다. 이러한 추가적인 생산성은 Visual Basic.NET에 특정한 것이며 C#과 같은 다른 관리 언어에는 포함되지 않는다는 것을 알아 두십시오.

지금까지 CLR의 프로그래밍 모델을 구성하는 여러 가지 관리 유형을 살펴보았습니다. 기본적인 사항을 다루었으므로 이제 관리 실행 개체로 컴파일링되는 것이 무엇인지에 대해 보다 자세하게 다루도록 합니다.

맨 위로


Microsoft Intermediate Language 및 JIT 컴파일
CLR은 이름이 뜻하는 바와 같이 .NET 플랫폼을 대상으로 하는 모든 언어 간의 전에 없이 높은 수준의 통합을 허용하도록 만들어진 것입니다. 이는 Visual Basic.NET 컴파일러가 C# 같은 다른 관리 언어의 컴파일러와 함께 동일한 규칙을 따라야 한다는 것을 뜻합니다. 가장 중요한 규칙은 실행 명령이 MSIL(Microsoft Intermdediate Language)의 형태로 된 DLL 및 EXE로 컴파일되어야 합니다.
MSIL은 전통적인 어셈블리 코드와 비슷하면서도 상당히 다른 컴파일된 형식입니다. MSIL은 개체가 레지스터 안팎으로 드나들고 움직이는 저수준 명령을 갖고 있다는 점에서 어셈블리 코드와 비슷합니다. 그러나 이는 특정 운영 체제나 하드웨어 플랫폼에 전혀 기대지 않는다는 점에서는 상당히 다릅니다. 이는 MSIL이 들어 있는 EXE 또는 DLL이 목표 컴퓨터에서 구축된 후라고 해도 시스템 특정 어셈블리 명령으로 변환하기 위한 JIT(Just-in-Time) 컴파일을 거쳐야 한다는 것을 뜻합니다.
MSIL의 첫 번째 장점은 CLR로 하여금 JIT 컴파일 시에 관리 코드가 완전히 유형에서 안전한지 확인하도록 한다는 것입니다. CLR은 이 검증 프로세스에 의존하여 DLL 또는 EXE 내부에 분산된 코드가 포인터 또는 잘못된 유형 변환을 하지 않는지 확인합니다. 이를 통해 CLR은 일반적으로 자주 사용되는 시스템 공격에서 자신을 방어할 수 있습니다. 신뢰할 수 없는 소스에서 관리 코드를 다운로드하는 컴퓨터는 비관리 코드가 할 수 없는 방식으로 자신을 방어할 수 있습니다.
MSIL의 두 번째 장점은 EXE와 DLL을 특정 운영 체제 및 하드웨어 플랫폼에서 분리시킨다는 점입니다. Microsoft는 현재 Windows 2000, Windows NT®, Windows 98, Windows 95용의 CLR 버전을 출시할 계획을 갖고 있습니다. 그러나 MSIL은 DLL과 EXE에 Intel x86 프로세서에 기반한 플랫폼 이외의 플랫폼에서도 실행할 수 있는 잠재력을 제공하기 때문에 강력합니다.
가까운 미래에 Windows CE용 CLR 버전이 나오기를 기다리는 사람이 있을 것입니다. 또한 다른 운영 체제 및 하드웨어 플랫폼에서도 사용할 수 있는 CLR이 구현되기를 바라는 사람도 있을 것입니다. Handheld 장치 또는 Pocket PC 같은 하드웨어 플랫폼에서 Visual Basic 코드를 실행한다는 아이디어는 이미 현실로 가능해진 일입니다.

맨 위로


더 나은 COM으로서의 CLR
COM을 CLR로 대체한다는 Microsoft의 장기적인 결정에 대해 어느 정도 이해하고 있겠지만, 과거의 런타임 환경을 새로운 환경으로 마이그레이션하는 것의 근본적인 장점을 이해할 필요가 있습니다. CLR 및 .NET을 설계한 아키텍처는 COM 기반 응용 프로그램 작성 및 구축에 들어가는 어려움을 상당히 완화시키면서 COM의 최상의 측면을 수용할 수 있었습니다.
특히 CLR은 상호 운용성, 응용 프로그램 구축, 구성 요소 버전 관리 등과 관련한 COM의 가장 실망스러운 문제 중 여러 가지를 해결했습니다. 추측할 수 있듯이, CLR에 의해 도입된 새로운 프로그래밍 모델은 분산 응용 프로그램 코드의 작성 및 이해에 관련된 COM의 여러 가지 불필요하게 복잡한 부분을 없애는 데 기여합니다.
COM의 역사는 다양한 언어의 상호 운용성에 관련된 문제를 겪어 왔습니다. 비관리 언어 사이에 어느 정도의 상호 운용성이 존재하기는 하지만, 이는 이상적인 것과는 거리가 먼 것입니다. 예를 들어 C++ 프로그래머가 Visual Basic이나 스크립팅 언어에서는 사용할 수 없는 구성 요소 DLL을 만들어내는 것은 흔한 일입니다. 문자열, 배열, 포인터 등과 같은 개체를 다루는 많은 내장 C++ 유형을 다른 언어에서 사용하는 것은 불가능하거나 실용적이지 못한 일입니다.
CLR은 높은 수준의 상호 운용성을 보장합니다. CLR의 프로그래밍 모델은 그림?6에 나와 있는 유니버설 유형 시스템에 기반하고 있습니다. 모든 관리 언어는 이 핵심적인 내장 유형에 매핑되거나 계층화되어야 합니다.
Figure 6 Universal Type System
그림?6 유니버설 유형 시스템
그림 6과 같이, CLR 유형 시스템은 정수 또는 부동 소수점 등을 포함하고 있는 예측 가능한 일련의 기본적 유형을 정의합니다. CLR의 유형 시스템은 또한 String, Array, Exception 등과 같은 다른 유형의 표준 클래스를 정의하기도 합니다.
Visual Basic.NET 및 C# 같은 언어는 많은 내장 CLR 유형에 직접 매핑하는 키워드를 제공합니다. 예를 들어 Visual Basic.NET은 C#의 Int 키워드와 같은 역할을 하는 Integer 키워드를 제공합니다. 두 유형 모두 CLR의 System.Int32 유형에 직접 매핑합니다. 그림에서 볼 수 있듯이 CLR은 모든 관리 언어 사이에서 공유되는 유니버설 유형을 표준화함으로써 COM을 기반으로 향상되고 있습니다.
CLR은 일부 관리 언어에서는 지원되지 않는 몇 개의 유형과 기능을 제공한다는 점을 알아 두는 것이 좋습니다. 예를 들어 CLR의 유형 시스템은 서명되지 않은 정수에 대한 다양한 내장 유형을 제공합니다. 서명되지 않은 정수는 C#에서는 완전하게 지원되지만, Visual Basic.NET에서는 그렇지 않습니다. 이는 C# 프로그래머의 경우, 서명되지 않은 정수가 다른 언어에서 액세스할 수 없거나 어색한 방식으로 나타나는 구성 요소를 만들 수도 있다는 뜻입니다.
프로그래머가 다른 언어에서 액세스할 수 없는 구성 요소를 만드는 실수를 저지르지 않도록 하기 위해, Microsoft는 CLS(Common Language Specification)라고 하는 문서를 만들었습니다. CLS는 CLR 유형의 하위 집합을 정의하고 구성 요소 및 소비자 언어가 다른 관리 언어와 효율적으로 상호 운용될 수 있도록 지원해야 한다는 점을 명시합니다.
Visual Basic.NET은 CLS에 완벽하게 호환됩니다. 또한, CLR에 내장된 클래스 라이브러리는 Visual Basic.NET을 포함한 CLS과 호환되는 모든 언어에서 액세스 할 수 있습니다. 이는 과거에 기본 플랫폼의 많은 부분(Win32 API 및 OLE32.DLL)이 선택한 언어에서는 액세스할 수 없다는 것을 받아들여야만 했던 Visual Basic 사용 프로그래머에게 최고의 소식입니다. CLR 클래스 라이브러리에 대한 전면적인 액세스는 다른 관리 언어와 비교해 볼 때 Visual Basic으로 할 수 있는 일이라는 측면에서 활동 범위를 한 차원 올려주는 것이라고 할 수 있습니다.
그림?6에서 알 수 있듯이, CLR의 유형 시스템은 상속에 크게 의존하고 있습니다. 전체 유형 시스템은 단일 상속 계층 구조에 의존하고 있습니다. 개체를 만드는 데 사용되는 모든 관리 유형은 궁극적으로 단일 루트 유형 System.Object에서 나옵니다. 다른 클래스에서 상속을 명시적으로 받지 않으면서 클래스를 만들 경우 클래스는 암시적으로 System.Object에서 상속을 받는 것입니다. 따라서 아래와 같은 클래스 선언은
Public Class Class1
  ' class member declarations go here
End Class
다음 클래스 선언과 같은 뜻입니다:
Public Class Class1
       Inherits System.Object
  ' class member declarations go here
End Class
하나의 사용자 정의 클래스를 다른 사용자 정의 클래스에서 얻고자 하는 경우 구문은 다음과 같습니다.
Public Class Class2
             Inherits Class1
  ' class member declarations go here
End Class
Visual Basic.NET에서는 획득하는 클래스의 이름을 분리하고 줄 바꿈을 사용하여 키워드를 상속해야 합니다. 능숙한 C++ 프로그래머를 의도적으로 혼란시키기 위해 Visual Basic.NET 코드를 작성하려고 하는 경우에는 줄 바꿈 대신에 다음과 같은 방식으로 콜론을 사용할 수도 있습니다.

Public Class Class2 : Inherits Class1
  ' class member declarations go here
End Class
이 구문은 상속을 사용할 때 콜론이 필요한 C# 및 C++과 더 비슷합니다. 그러나 Visual Basic.NET의 경우 콜론은 단지 줄 바꿈의 역할만을 한다는 사실을 아는 것이 중요합니다. 필자의 경우에는 이러한 방식이 관리하고 읽기에 더 쉽다고 생각하기 때문에 이 방식을 선호했습니다. 사실 필자는 항상 C++ 사용자가 되기를 원했기 때문에 이를 사용합니다.
중요한 것은 인스턴스를 만드는 데 사용하는 관리 유형은 궁극적으로 System.Object에서 상속된다는 사실입니다. 여기에는 integers, longs, doubles 등과 같은 기본 유형이 포함됩니다. 이는 참조 유형이든 값 유형이든 상관 없이 모든 변수가 System.Object 유형으로 만들어질 수 있다는 것입니다. 또한 Visual Basic.NET 언어는 variant, IUnknown, IDispatch 등과 같은 이전의 비관리 유형의 기능을 System.Object로 옮겨놓았다는 사실을 기억해야 합니다.

맨 위로


보다 풍부한 구성 요소 메타데이터 형식
.NET Framework에서는 DLL이나 EXE와 같은 관리 바이너리를 "모듈"이라고 합니다. 모든 관리 언어에는 광범위한 구성 요소 메타데이터 집합을 해당 유형을 설명할 수 있는 각각의 모듈로 만들 수 있는 컴파일러가 있어야 합니다. 그림?7과 같이 모듈에는 해당 모듈에 속한 관리 유형을 위한 MSIL 코드와 구성 요소 메타데이터가 들어 있습니다.
Figure 7 A .NET Module
그림 7 .NET 모듈

한 모듈의 구성 요소 메타데이터는 공용 유형(예: 열거, 구조, 인터페이스, 클래스 등)에 대한 정보를 클라이언트 응용 프로그램에 공개하므로 COM DLL의 유형 라이브러리에 저장된 유형 정보와 유사합니다. 하지만 관리 구성 요소의 유형 정보가 COM이 사용하는 유형 정보보다 훨씬 더 풍부한 몇 가지 중요한 차이점이 있습니다.
먼저, 모든 구성 요소 메타데이터는 관리 형식 정보를 설명하는 단일한 고정확도 형식을 고수해야 합니다. 이렇게 하면 유형 라이브러리에 사용된 유형 정보 형식과 IDL(Interface Definition Language)에서 사용된 형식 사이의 정확도 손실로 인해 COM 개발자가 겪는 문제가 해결됩니다. 또한, IDL처럼 별도의 언어를 사용해 유형을 정의할 필요가 없으므로 .NET 개발이 COM 개발보다 더 쉽습니다. 사용자 정의 유형은 항상 Visual Basic.NET 또는 C# 등의 관리 언어를 사용하여 자세히 설명 가능합니다.
COM과 CLR의 또 다른 큰 차이점은 관리 구성 요소에는 클래스를 설명하는 메타데이터가 훨씬 더 많다는 것입니다. COM에서 클래스 유형 정보는 coclass의 관점에서 유형 라이브러리에 정의됩니다. COM coclass 유형은 지원하는 인터페이스의 관점에서만 클래스를 설명한다는 점에서 한계가 있습니다. COM은 구현과 인터페이스를 엄격하게 구분하며, coclass 정의에 대한 정보가 제한된 것도 이러한 이유 때문이라고 할 수 있습니다.
COM은 구현과 인터페이스를 형식적으로 구분해야 하지만 Visual Basic에서는 항상 모든 다중 사용 클래스 뒤에 기본 인터페이스를 자동으로 구축하므로 작업이 쉬워집니다. Visual Basic 클라이언트에 클래스 이름을 기초로 한 참조 변수가 있으면 Visual Basic 컴파일러는 조용히 해당 클래스에 대한 기본 인터페이스를 참조합니다. 따라서 Visual Basic은 COM에서 구현 유형과 인터페이스를 형식적으로 구분해야 한다는 사실을 숨길 수 있게 되었습니다.
CLR 설계자가 가지고 있는 class 관점은 COM보다는 Visual Basic과 더 가깝습니다. 관리 클래스에 대한 구성 요소 메타데이터는 해당 공용 메서드를 기본 인터페이스의 일부로 공개할 수 있습니다. 이렇게 하면 유연성이 훨씬 커집니다. COM과는 달리 독립 실행형 인터페이스를 정의하지 않아도 클래스에 대해 프로그래밍할 수 있습니다. 여기서 중요한 점은 공용 메서드를 사용하는 클래스가 허용되며 훨씬 쉬운 대체 방안일 경우 인터페이스에 대해 작업할 필요가 없다는 것입니다.
CLR 설계자가 독립 실행형 인터페이스에 대해 작업할 필요성이 없어지긴 했지만 관리 코드를 쓸 때 인터페이스 기반 프로그래밍이 중요하지 않다는 것은 아닙니다. 플러그 호환 클래스를 작성하려고 하거나 대규모 응용 프로그램의 한 하위 시스템에서 다른 하위 시스템을 분리하고자 하는 경우 명시적인 인터페이스를 기초로 한 프로그래밍이 아주 중요합니다. 또한, CLR 클래스 라이브러리는 인터페이스를 통해 자주 이 기능을 노출합니다. 중간 또는 고급 단계의 프로그래머라면 인터페이스 유형 정의, 실행 및 사용에 능숙해야 합니다.
COM과 CLR은 모두 공용 유형 정보를 공개하는 구성 요소가 필요하지만 CLR은 모듈이 있어야만 내부 유형 정보를 시스템에 공개할 수 있다는 점에서 COM과는 다릅니다. CLR은 개체를 작성 및 관리 런타임 시 이 내부 유형 정보를 사용합니다. 예제를 살펴 봅시다.
COM 유형 라이브러리에는 메모리에서 개체를 표시하는 방법을 설명하는 유형 정보가 전혀 없습니다. 대신, 개체의 매모리 할당 및 릴리스는 COM DLL의 책임입니다. COM DLL은 이 외에도 개체를 COM 호환 vtable과 함께 레이아웃할 책임이 있습니다. CLR에서는 이 책임이 구성 요소 DLL에서 기본 런타임 환경으로 옮겨갑니다.
CLR은 개체 메모리를 할당하고 릴리스하는 책임을 집니다. 클라이언트가 관리 클래스에서 개체를 만들도록 요청하면 CLR은 런타임 시 이 클래스의 내부 유형 정보를 검사하여 개체 메모리와 레이아웃 요건을 찾아냅니다. 이 정보를 사용해 CLR은 개체 작성 중 적절한 양의 메모리를 할당할 수 있습니다.
CLR은 내부 유형 정보를 사용하여 클라이언트가 개체에서 메서드를 실행할 수 있도록 해 주는 바인딩을 만듭니다. 이는 COM 바이너리와는 달리, 관리 바이너리에는 COM 스타일 vtable을 생성하거나 액세스하는 코드가 필요하지 않다는 것을 뜻합니다.
CLR은 COM 런타임보다 더 많은 책임이 있습니다. 따라서 CLR 설계자는 vtable을 처리하는 코드와 클래스 팩토리 등 COM 바이너리 고유의 복잡성과 추가 부담을 많이 덜 수 있습니다.

맨 위로


개체 수명을 관리하는 가비지 수집
이제 메모리 관리에 대한 주제로 COM과 CLR의 중요한 구조적 차이를 알아 보겠습니다. 이 차이는 개체 수명 관리와 많은 연관이 있으며 코드 작성 방법에 큰 영향을 미칩니다.
COM은 참조 계산을 사용해 개체 수명을 관리합니다. 사용자가 COM 개체 최신 참조를 릴리스하면 해당 개체는 이와 동시에 메모리에서 자체 삭제됩니다. 사용자 클래스의 Class_Terminate 구현에 사용자 정의 정리 코드가 있으면 이 코드는 결정된 방식으로 실행됩니다. 하지만 CLR의 관리 개체를 실행하는 경우에는 다릅니다.
CLR은 가비지 수집을 통해 개체 수명을 관리합니다. 이는 COM이 개체 수명 관리에 사용하는 참조 계산과는 크게 다릅니다. CLR은 항상 가비지 수집 힙에서 개체를 만듭니다. 이 개체는 클라이언트가 개체로 마지막 참조를 릴리스하더라도 메모리에서 즉시 제거되지 않습니다. 대신, 가비지 수집기가 이후의 불확정한 시간에 메모리에서 이 개체를 제거합니다.
사용자가 참조 계산보다 가비지 수집을 더 선호하는 가장 큰 두 가지 이유는 향상된 성능과 개체 사이에 순환 참조를 감지하고 구분하는 능력에 있습니다. CLR 설계자들은 이 두 가지 이유를 COM 사용 모델보다는 가비지 수집을 수명 관리에 사용할 충분한 근거로 판단했습니다.
일부가 가비지 수집보다 참조 계산을 더 선호하는 가장 큰 이유는 소멸자(Class_Terminate)가 적절한 시기에 예상 가능한 방식으로 실행된다는 것입니다. CLR은 참조 계산을 사용하지 않으므로 Visual Basic.NET은 Class_Terminate를 지원하지 않습니다. 대신, 관리 클래스는 메모리에서 개체가 제거될 때 실행되는 Finalize 메서드를 제공할 수 있습니다. 하지만 클라이언트가 개체를 릴리스하는 순간 클래스 소멸자가 실행되는 COM과는 많이 다르다는 점은 분명히 해야 합니다.
가비지 수집과 참조 계산 중 어느 쪽이 우수하냐에 대한 논쟁이 격렬하게 진행 중입니다. 이 논쟁은 많은 개발자들에게 있어 일종의 운동과 같은 형태로 발전했습니다. 어떤 수명 관리 스타일이 더 우수하다고는 말할 수 없습니다. 하지만 CLR은 가비지 수집을 사용하며 따라서 이 사실이 관리 코드 작성 방식에 영향을 준다는 점은 말할 수 있습니다.

맨 위로


어셈블리 및 코드 분배
앞서 언급한 것처럼 모듈은 구성 요소 메타데이터와 MSIL이 모두 들어 있는 바이너리 코드 단위입니다. 하지만 관리 코드를 배포하는 어셈블리라는 또 다른 추상화 계층이 있습니다. 이것은 구축, 버전 및 보안과 관련된 몇 가지 중요한 문제를 다루기 때문에 모듈을 보충하는 역할을 합니다.
어셈블리를 사용해 관리 코드를 구축하는 방법과 관련해 중요한 사항이 많습니다. 안타깝게도 세부 사항이 너무 많아서 본 자료에서는 모두 다룰 수가 없으므로, 중요한 요점의 개요만 소개하겠습니다.
어셈블리는 구축 단위를 구성하는 하나 이상의 모듈을 말합니다. 개별 어셈블리마다 manifest라는 구성 요소 메타데이터 카탈로그가 들어 있습니다. 어셈블리의 manifest에는 유형 표시, 구성 요소 버전, 보안에 대한 중요한 메타데이터가 있으므로 어셈블리 추상화가 중요합니다.
모든 관리 유형은 반드시 어셈블리 범위 내에 있어야 합니다. Visual Basic.NET에서 사용자가 만드는 프로젝트는 일반적으로 하나의 어셈블리를 나타냅니다. 또 다른 어셈블리의 프로젝트에서 관리 유형을 사용하려면 이 다른 어셈블리에 대한 참조가 프로젝트에 들어 있어야 합니다.
다른 사람들이 사용할 어셈블리를 만들 때에는 어셈블리 외부에서 볼 수 있는 유형을 결정해야 합니다. 키워드 Public과 Private를 사용하면 클래스 또는 인터페이스 등의 유형을 노출시키거나 숨길 수 있습니다. Visual Basic.NET는 Friend 키워드를 사용하는 공용 클래스에서 메서드를 꾸밀 수 있는데, 어셈블리 내에서만 메서드를 액세스할 수 있게 됩니다.
어셈블리를 보는 한 가지 방식은 어셈블리가 버전의 단위라는 것입니다. 각 유형을 public 또는 private으로 만드는 결정은 아주 중요합니다. 외부 클라이언트에게 공개하는 유형 및 유형 구성원에 대한 버전 문제만 고려하면 된다는 점을 기억하십시오. 어셈블리에 private인 유형은 기존 클라이언트 응용 프로그램을 고려하지 않고도 제거하거나 수정할 수 있습니다.
명령줄에서 VBC.EXE를 호출하면 사용자 프로젝트에서 사용하는 개별 외부 어셈블리에 대한 스위치(/reference or /r)를 전달해야 합니다. 예를 들면, 다음은 콘솔 응용 프로그램이 외부 어셈블리 유형을 사용할 때 Visual Basic.NET 컴파일러에 대한 호출입니다.

vbc.exe /target:exe /reference:MyLibrary.dll hello.vb

명시적으로 참조할 필요가 없는 어셈블리는 MSCORLIB.DLL입니다. 이 어셈블리에는 모든 프로젝트가 사용하는 System.Object와 같은 핵심 관리 유형이 들어 있으므로 사용자가 일부러 추가하지 않더라도 Visual Basic.NET 컴파일러에는 이 어셈블리에 대한 참조가 자동으로 포함됩니다. 하지만 다른 어셈블리는 반드시 명시적으로 참조해야 하며 그렇지 않으면 코드가 컴파일되지 않습니다. 사용자가 프로젝트에 참조를 만들면 Visual Studio.NET은 적절한 인수를 Visual Basic.NET 컴파일러에 전달합니다.
많은 경우 어셈블리는 단일 DLL이나 단일 EXE 파일로 구성됩니다. 기본적으로 Visual Basic.NET 컴파일러를 사용해 만드는 DLL이나 EXE는 모두 모듈이며 동시에 어셈블리입니다. 하지만 더 복잡한 구축 시나리오에서는 여러 DLL과 다양한 리소스 파일이 들어 있는 어셈블리를 만들고자 할 수도 있습니다. Visual Basic.NET 컴파일러에는 어셈블리가 아닌 모듈을 만들 수 있는 명령줄 스위치가 있습니다. 이 스위치를 사용하면 어셈블리 링커 유틸리티(AL.EXE)를 사용하여 다중 모듈 어셈블리를 만들 수 있습니다.
CLR은 두 가지 유형의 어셈블리를 인식합니다. 먼저, 개인 어셈블리는 단일 응용 프로그램과 구축되고 사용됩니다. 개인 어셈블리는 이 어셈블리를 사용하는 응용 프로그램과 같은 디렉터리나 하위 디렉터리에서 구축해야 합니다. 둘째, 공유 어셈블리는 여러 응용 프로그램이 사용할 수 있습니다. 클라이언트 응용 프로그램이 공유 응용 프로그램을 사용하려면 공유 어셈블리가 반드시 특수 어셈블리 캐시에 설치되어 있어야 합니다.

Figure 8 Private Assembly with One DLL
그림 8 DLL이 하나인 개인 어셈블리

그림?8그림?9는 고급 어셈블리 보기입니다. 그림?8은 하나의 DLL로 구성된 개인 어셈블리이고, 그림?9는 세 개의 DLL을 기반으로 한 좀더 복잡한 공유 어셈블리의 예입니다.

Figure 9 Shared Assembly
그림 9 공유 어셈블리

맨 위로


DLL과의 결별
CLR은 응용 프로그램 구축과 구성 요소 버전 검사의 경우 COM에 비해 많은 장점을 제공합니다. 예를 들어, COM은 ProgID, CLSID, IID 및 유형 라이브러리 등의 레지스트리 항목을 요구하기 때문에 취약하고 구축이 어려운 것으로 알려져 있습니다. CLR은 어셈블리나 관리 형식에 이러한 레지스트리 항목을 요구하지 않습니다. CLR은 런타임 시 로드 가능한 모듈을 찾고 형식을 확인하는 데 훨씬 풍부한 유연성과 적응성을 제공합니다.
또한 CLR은 특히 구성 요소 버전 검사의 경우 COM에 비해 뚜렷하게 개선되었습니다. 이것은 CLR이 병렬 구축 즉, 동일한 어셈블리의 여러 버전을 로드하여 작업하는 기능을 지원하기 때문입니다. CLR은 두 가지 다른 응용 프로그램이 동일한 프로세스 내에서 같이 실행되고 있는 경우라 하더라도 동일한 DLL의 두 가지 다른 버전을 로드하여 사용할 수 있습니다.
병렬 구축은 클래스(CLSID)를 시스템 당 한 번만 구축할 수 있는 COM에 비해 훨씬 향상된 기능입니다. 이것은 이전 버전과의 호환성을 유지하지 못하는 DLL의 새 버전을 만드는 것이 이제 훨씬 간편해졌다는 뜻입니다. DLL의 복수 버전을 구축하기만 하면 새 클라이언트와 기존 클라이언트를 동시에 만족시킬 수 있습니다. 구 버전 위에 새 버전의 DLL을 설치하여 기존 클라이언트 응용 프로그램을 파괴하던 시대는 갔습니다.
CLR은 고도의 버전 검사 지원을 제공합니다. 그러나 이 지원은 공유 어셈블리에 코드를 구축할 때만 사용할 수 있다는 것이 중요합니다. COM 버전 검사에 비해 훨씬 향상되었다는 이유가 무엇인지 이해할 수 있도록 간단하게 작동 원리를 설명하겠습니다.
공유 어셈블리를 참조하는 클라이언트 응용 프로그램을 컴파일할 때 어셈블리의 이름과 버전 번호는 클라이언트 어셈블리의 목록에 기록됩니다. COM과는 달리 클라이언트 응용 프로그램은 컴파일한 DLL 버전을 항상 인식하고 있습니다. 더욱이 CLR을 사용하면 개발자나 관리자가 클라이언트 응용 프로그램의 버전 검사 정책을 조정하여 공유 어셈블리의 어떤 버전을 로드할 것인지 결정할 수 있습니다. 클라이언트 응용 프로그램은 컴파일된 정확한 버전을 로드하도록 구성하거나 가장 최신의 호환 버전을 로드하도록 구성할 수 있습니다.
어셈블리에 대한 이런 간단한 설명만으로도 CLR이 응용 프로그램 구축과 구성 요소 버전 검사에 있어 훨씬 개선된 환경을 제공한다는 것을 알 수 있습니다. 여러분은 아마 많은 Microsoft 직원들이 지옥 같은 DLL과의 결별이라고 하는 말을 들었을지도 모릅니다. 제가 보기에는 이것이 응용 프로그램을 CLR과 Visual Basic.NET으로 마이그레이션할 때 생기는 가장 명백한 장점 중 하나입니다.

맨 위로


Visual Basic 6.0에서 Visual Basic.NET으로 마이그레이션
아시다시피, Visual Basic 6.0과 COM이 아닌 Visual Basic.NET과 CLR로 마이그레이션을 결정할 때 고려해야 할 수 많은 설계 문제와 구현 세부 사항이 존재합니다. 마이그레이션은 비용이 소모되며 이득을 가져옵니다. 또한 개발 팀의 마이그레이션과 반대되는 기존 Visual Basic 6.0 프로젝트의 마이그레이션 간의 차이점도 고려해야 합니다.
CLR의 프로그래밍 모델이 개발자가 처음 보게 되는 Visual Basic의 많은 새 개체 지향 기능을 지원한다는 점을 염두에 두십시오. 이 기사에서 다루지 못하는 훨씬 많은 새 프로그래밍 기능과 개념이 있습니다. 초보자를 위해 Visual Basic.NET에는 구조적 오류 처리, 공유 클래스 구성원, 매개 변수화된 생성자, 메서드 초과 로드 및 구현 상속에 대한 지원이 포함되었습니다.
평균적인 프로그래머가 Visual Basic 6.0에서 Visual Basic.NET으로 마이그레이션하는 데 필요한 요소를 분명하게 알아 두십시오. 이런 새 개체 지향 기능을 익히는 데는 시간이 걸릴 것입니다. 많이 배워야만 새 기능을 모두 적절히 사용할 수 있습니다.
Visual Basic.NET으로 마이그레이션하는 것은 구문 작성 방법만 바꾸는 것이 아닙니다. 가능한 경우 언제나 내장된 클래스 라이브러리를 사용하는 것이 좋습니다. 이 클래스 라이브러리는 문자열 처리, 사용자 인터페이스 구성, 데이터베이스 액세스, XML 처리 및 소켓 프로그래밍과 같은 분야에서 광범위한 기능을 제공합니다.
CLR의 클래스 라이브러리를 사용하려면 Visual Basic에 익숙한 프로그래머의 태도가 근본적으로 변화되어야 합니다. 텍스트를 조작할 때 VBA 런타임 라이브러리의 UCase, InStr 및 StrComp와 같은 익숙한 함수를 사용할 생각이 먼저 들 것입니다. 그러나 이런 유혹을 뿌리치고 CLR 클래스 라이브러리에서 동일한 기능을 찾아야 합니다. 당연하게도 VBA 런타임, ADO 및 MSXML과 같은 기존 라이브러리에서 CLR 클래스 라이브러리의 유사 기능으로 프로그래머를 마이그레이션하려면 해당하는 비용이 듭니다.
일단 Visual Basic.NET의 새 기능에 속도가 붙고 CLR 클래스 라이브러리에 익숙해지기 시작하면 이러한 것들이 배포된 응용 프로그램을 구축하는 최상의 플랫폼을 제공한다는 사실에 동의하리라 생각합니다. 이 시점에 도달하면 여러분이 새 프로젝트를 시작할 때마다 Visual Basic.NET을 사용하고 싶어할 것이라고 자신 있게 말할 수 있습니다.
그러나 현재의 Visual Basic 6.0 프로젝트를 Visual Basic.NET으로 이전해야 하는지 결정하는 것은 쉬운 일이 아닙니다. Visual Basic 6.0에서 Visual Basic.NET으로 프로젝트를 이식하는 것은 그리 간단한 작업은 아닙니다. 응용 프로그램이나 구성 요소 라이브러리를 마이그레이션 하려면 기존 형식을 다시 설계하고 기존 메서드 구현을 다시 작성해야 합니다. 비관리 라이브러리에 대한 참조를 제거하고 그것을 CLR 클래스 라이브러리 참조로 대체하게 되면 마이그레이션 비용이 더욱 커집니다.
어떤 회사는 기존 Visual Basic 6.0 프로젝트를 Visual Basic.NET으로 이식하는 것이 별 가치가 없다는 결론을 내리게 될 것입니다. 그러면 두 가지 중에 하나를 선택해야 합니다. Visual Basic.NET으로 프로젝트를 처음부터 다시 작성하거나 Visual Basic 6.0의 프로젝트를 그대로 두는 것입니다. Visual Basic 6.0으로 작성한 몇 가지 응용 프로그램과 구성 요소 라이브러리를 그대로 두기로 결정한 경우 CLR과 COM의 상호 운용성 계층이 안정적이며 사용이 꽤 쉽다는 점에 만족하게 될 것입니다.
CLR과 COM의 상호 운용성 계층은 관리 코드와 비관리 코드를 함께 사용하여 응용 프로그램 코드를 작성할 기회를 제공합니다. 즉, Visual Basic.NET 코드를 Visual Basic 6.0 코드와 혼합하여 사용할 수 있다는 뜻입니다. 앞으로 기본 기능 컬럼에서 이러한 문제를 훨씬 심도 있게 다루어 나갈 계획입니다.

맨 위로


결론
CLR과 관련 프로그래밍 모델에 대해 확실히 이해하기 전에는 Visual Basic.NET을 완전히 이해할 방법은 없습니다. CLR의 기본 형식 시스템과 개체 지향 기능을 익히는 것이 중요합니다. 이런 기본 사항에 대해 학습하면 Visual Basic.NET이나 C#과 같은 관리 언어를 완전히 익힐 수 있습니다.
이 기사에서 얼마나 많은 COM 구현 세부 요소가 새롭고 더 현대적인 CLR의 구현으로 바뀌었는지 설명했습니다. 그러나, COM의 정신은 CLR과 .NET Framework에서도 그대로 살아 있습니다. 구성 요소에 기반한 응용 프로그램 코드의 작성, 재사용, 구축 및 버전 검사가 바로 그것입니다. 이것을 염두에 둔다면 CLR을 COM의 최신 버전으로 생각해도 될 것입니다.

Ted Pattison은 DevelopMentor(http://www.develop.com/)의 강사이자 연구원입니다. 이곳에서 그는 Visual Basic 과정을 공동 관리하고 있습니다. Ted의 저서인 Programming Distributed Applications with COM and Microsoft Visual Basic 6.0의? 제 2판이 2000년 6월 Microsoft Press에서 출판되었습니다.

? 최종수정일: 2001년 1월 8일

Top of Page Top of Page


Microsoft