작성날짜 : 2011-04-23 |
출처 : http://cafe.daum.net/smbitpro?t__nil_cafemy=item
참고 사이트 : http://msdn.microsoft.com/ko-kr/library/ms173099.aspx
Assembly
.NET 어셈블리는 .NET Framework 응용 프로그램을 구성하는 기본 컴포넌트입니다. 컴포넌트 기반의 프로그래밍을 하면 여러분들이 아는 것처럼 재 사용성을 높일 수 있습니다. .NET 어셈블리는 EXE파일 혹은 DLL파일 형태를 지닐 수 있으며 하나 이상의 모듈을 포함할 수도 있습니다. .
그리고, .NET 어셈블리는 배포를 단순화를 통해 많은 배포 문제를 해결하였습니다. .NET 어셈블리는 자기 기술적인 메타 데이터를 갖고 있고 레지스트리 항목에 종족되지 않는 구성 요소로 디자인이 되었기 때문에 Side-by-Side 실행이 가능합니다. 기존 Win32 COM에서는 버전 관리 문제를 비롯하여 DLL충돌 문제가 있었지만 .NET 어셈블리는 강력한 이름을 제공하면 이를 기반으로 DLL 충돌 문제를 해결하였습니다. 이로써 같은 명칭의 여러 어셈블리를 설치 가능할 뿐만 아니라 이를 사용하는 응용들은 자신들에 맞는 어셈블리를 사용할 수 있습니다. .NET 어셈블리를 배포하는 방법에는 기본적으로 사용하는 응용 프로그램의 전용으로 배포하는 방법과 여러 응용 프로그램이 공용으로 사용할 수 있게 배포할 수 있습니다.
구성 요소를 살펴봅시다.
첫 번째 구성요소로 어셈블리 매니페스트가 있습니다. 어셈블리 매니페스트는 어셈블리의 버전 요구 사항과 보안 ID를 지정하는 데 필요한 모든 메타데이터와 어셈블리의 범위를 정의하고 참조를 확인하는데 필요한 모든 메타 데이터를 포함하고 있습니다.
그리고, 어셈블리에 정의된 형식들에 대한 형식 메타 데이터와 실제 수행해야 할 코드인 MSIL코드와 리소스로 구성이 됩니다.
어셈블리를 구성하는 방법은 논리적 어셈블리와 물리적 바이너리 매핑 관계를 1:1로 대응 시키는 단일 파일 어셈블리와 여러 개의 모듈들을 논리적 관련을 통해 하나의 어셈블리를 구성하는 다중 파일 어셈블리가 있습니다. 어셈블리를 물리적 관점에서 어셈블리를 보면 리소스 파일, 매니페스트, DLL, 모듈 등으로 인식할 수가 있을 것이며 논리적 관점에서 보면 클래스, 대리자, 인터페이스, 리소스 등으로 볼 수 있습니다.
전용 어셈블리는 사용하는 응용 프로그램과 함께 어셈블리를 배포하여 해당 응용 프로그램에 의해서만 이용되는 어셈블리를 말합니다. 배포되는 위치는 응용 프로그램과 동일 디렉토리이거나 하위 디렉토리가 됩니다.
그리고, .NET에서 어셈블리 배포 방법의 기본으로 전용을 선택하고 있어 Visual Studio .NET을 가지고 개발을 할 때 특정 어셈블리를 참조를 하고 컴파일을 하면 자동으로 참조하는 어셈블리를 복사를 해 주어 개발자에게 편의성을 제공하고 있습니다.
CLR에 의해 전용 어셈블리의 위치를 찾는 과정을 프로빙이라 합니다. 제일 먼저 응용 프로그램 디렉토리를 우선적으로 검사를 하고 없으면 구성파일이 있는지 확인을 하게 됩니다. 그리고, 구성 파일이 있으면 구성 파일에 명시된 디렉토리를 검사하게 됩니다.
공유 어셈블리는 어셈블리를 컴퓨터 시스템의 어셈블리 캐시에 설치를 함으로써 여러 응용 프로그램에 의해 사용될 수 있습니다. 보통 전역 어셈블리 캐시 위치는 Windows 디렉토리의 Assembly 하위 디렉토리에 위치하게 됩니다. 그리고, DLL충돌을 막기 위해 공유 어셈블리에는 강력한 이름을 할당해야 합니다. 강력한 이름은 어셈블리 이름과 버전 번호 및 문화권, 어셈블리 ID, 공개 키, 디지털 서명 등으로 구성이 됩니다. 전역 어셈블리 캐시에는 동일한 이름의 DLL이더라도 강력한 이름이 다르면 배포가 가능합니다. 이를 통해 같은 이름의 서로 다른 버전을 사용하는 응용 프로그램들이 자신에게 알맞은 어셈블리를 사용할 수 있는 것입니다.
이제 어셈블리를 만들어 보도록 합시다. 먼저 개발 도구를 통해 IStudy.dll을 하나 만들어 봅시다. 프로젝트 템플릿에서 클래스 라이브러리를 선택하시고 프로젝트 명은 IStudy라 할게요. 먼저 모두 지우고 파일명도 IStudy.cs로 변경하겠습니다.
namespace AboutAssembly { public interface IStudy { // 간단히 interface IStudy를 정의해 볼께요. void Study(); } } |
컴파일을 해서 폴더를 보시면 IStudy.dll이 보이죠.
이와 같이 만들어진 어셈블리를 단일 파일 어셈블리라 말합니다.
이번에는 하나의 모듈을 만들고 해당 모듈을 포함하는 다중 파일 어셈블리를 만들어 봅시다. 모듈은 추상 클래스 Man이 정의된 Man.cs를 가지고 하겠습니다.
추상 클래스이고 name 필드와 생성자 name필드에 대한 접근자인 Name속성 그리고, 재 정의된 ToString이 있습니다.
namespace AboutAssembly { public abstract class Man { string name; public Man(string _name) { name = _name; } public string Name { get { return name; } } public override string ToString() { return String.Format("이름 : {0}", name); } } } |
모듈은 명령 프롬프트에서 csc /target:module Man.cs를 통해 만들 수 있습니다. 보시면 Man.netmodule 파일을 보실 수 있을 것입니다.
이번에는 Man.netmodule을 포함하는 Stu.dll을 만들어 볼게요.
Stu.cs도 미리 정의해 놓았습니다.
Stu클래스는 Man클래스를 상속받고 IStudy를 구현하였습니다. num필드와 생성자, num필드에 대한 접근자인 Num속성과IStudy에 구현 약속된 Study메서드를 구현하였고 ToString메서드를 재 정의하였습니다.
namespace AboutAssembly { public class Stu : Man, IStudy { int num; public Stu(int _num, string _name):base(_name) { num = _num; } public int Num { get { return num; } } public void Study() { Console.WriteLine(this.ToString()); Console.WriteLine("{0}시간 공부 중...",num); } public override string ToString() { return base.ToString() + String.Format("번호 : {1}", num); } } } |
IStudy.dll을 같은 위치로 옮겨 놓을게요.
프롬프트에서
Csc /target:library /reference:IStudy.dll /addmodule:Man.netmodule Stu.cs
하시면 Stu.dll이 만들어 지는 것을 알 수 있습니다.
이번에는 이를 사용하는 간단한 응용을 만들어 봅시다.
먼저, IStudy.dll과 Stu.dll을 참조 추가를 해야죠.
그리고, 간단히 사용하는 코드를 작성해 봅시다.
Man m = new Stu(3, "홍길동"); IStudy istudy = m as IStudy; if (istudy != null) { istudy.Study(); } |
동작해 보면 잘 동작함을 알 수 있습니다.
그리고, 폴더를 확인해 보시면 참조한 dll파일이 자동 추가되는 것을 알 수 있습니다.
이로써, 배포의 기본 방식이 전용 어셈블리로 채택하고 있음을 알 수 있습니다.
이번에는 공유 어셈블리를 간단히 살펴볼게요.
클래스 라이브러리 프로젝트를 새로 추가합시다. 프로젝트 명은 PublicAssembly라 할게요.
namespace PublicAssembly { public class Example { public static void Foo() { Console.WriteLine("Hello"); } } } |
프로젝트 메뉴에 속성을 선택해 보세요.
어셈블리 정보 버튼을 누르시면 정보 창이 보이죠.
여기에서 어셈블리의 강력한 이름 정보들을 정할 수 있습니다.
그리고, 서명 탭을 선택해서 어셈블리 서명을 할 수 있습니다. 키 파일을 하나 만들께요.
컴파일을 하시고 작성된 어셈블리 파일을 전역 어셈블리 캐시로 이동 시킬께요.
그리고, 공용 어셈블리를 사용하는 응용 프로그램을 하나 만들어 봅시다. 프로젝트 명은UsingPublicAssembly이라 할게요. 공용 어셈블리를 참조를 추가를 합시다. 전역 어셈블리 캐시 디렉토리에서 참조하려고 하면 참조가 되지 않습니다. 방금 만든 프로젝트 폴더에서 참조를 하세요.
그리고 간단히 사용하는 코드를 작성합시다.
using PublicAssembly;
namespace UsingPublicAssembly { class Program { static void Main(string[] args) { Example.Foo(); } } } |
컴파일을 하고 동작시켜보면 잘 동작합니다.
솔루션 탐색기에서 프로젝트 폴더를 열어서 보면 참조한 dll파일이 복사되지 않음을 알 수 있죠.
공개 키 값을 포함하는 어셈블리의 경우 공용 어셈블리로 취급하여 복사하지 않습니다.
이번에는 방금 작성한 공용 어셈블리 내용을 조금 수정해 봅시다.
namespace PublicAssembly { public class Example { public static void Foo() { Console.WriteLine("Yahoo"); } } } |
그리고, 어셈블리 정보에 버전을 변경 후
전역 어셈블리 캐시에 설치합시다. 보시면 DLL명이 같아도 강력한 이름만 다르다면 중복 설치가 됨을 알 수 있습니다.
그리고, 이를 이용하는 응용 프로그램을 하나 만들어 봅시다. 프로젝트 명은 UsingPublicAssembly2라 할께요. 어셈블리 참조 추가하시고
using PublicAssembly;
namespace UsingPublicAssembly2 { class Program { static void Main(string[] args) { Example.Foo(); } } } |
실행해 보면 잘 동작함을 알 수 있습니다.
전에 만든 응용을 동작하면 수정된 버전의 어셈블리를 참조하여 동작함을 알 수 있습니다. 솔루션 창에서 어셈블리를 선택하여 어셈블리 속성 중 특정 버전을 True로 설정하시고 다시 동작해 보면 처음에 참조한 어셈블리를 참조하여 동작됨을 알 수 있습니다. 이로써 이름 충돌도 피하고 Side-by-Side 실행이 가능함을 알 수가 있죠. 이 외에도 지연 서명이나 게시자 정책 등 어셈블리에 대한 사항들이 있으니 MSDN을 참고하여 살펴보시기 바랍니다.
'Programming > .NET' 카테고리의 다른 글
[ADO.NET] XmlReader 소개 (0) | 2015.06.05 |
---|---|
[.NET] Delegate 실습, 크로스 스레드 해결방법 (0) | 2015.05.28 |
[.NET] Delegate (대리자) - 2 (0) | 2015.05.19 |
[.NET] DataRepeater Control (0) | 2015.05.19 |
[.NET] Reflection (C#) (0) | 2015.05.19 |