*이 내용은 개인 학습 내용을 정리하는 것이 목적입니다.
1.1 COM의 등장
1.1.1 메인프레임 시대
- 메인프레임에서 모든 작업을 처리. 프로그램의 크기가 커서 유지보수가 어려운 단점.
1.1.2 클라이언트 / 서버 시대
- 메인프레임 방식으로는 비싼 유지보수비용, 업무요구에 대한 신속한 대처등 문제가 있음.
-> 업무를 작은규모의 서버들에게 분할하여 처리. 이 시기엔 데스크탑의 성능도 향상되어 클라이언트에
서 데이터를 적절히 가공하는 일도 하게 됨.
1.1.3 3계층 클라이언트 / 서버 시대
- 클라이언트-서버 관계를 클라이언트-별도어플리케이션서버-데이터베이스서버 3개로 분할.
1.1.4 컴포넌트기반 분산 객체 기술의 등장
- 분산 클라이언트/서버에서는 어플리케이션의 유기적인 통합과 커뮤니케이션이 필요함
-> 컴포넌트 기반 분산 객체 기술이 등장
1) 컴포넌트 소프트웨어의 조건
- 언어독립적이어야 한다.
언어별로 다른 메모리 사용과 커뮤니케이션 방식을 가짐. -> 표준이 필요함
- 위치투명성을 제공해야 한다
위치에 관계없이 컴포넌트를 사용할 수 있어야 한다.
- 버전관리가 쉬워야 함
- 특정업체에 종속적이지 않아야 함
2) ORB (Object Request Broker)
- 객체에 대한 서비스 요청을 중계하는 중계자.
-> 클라이언트는 ORB를 통해 서비스 요청을 하므로 서버 컴포넌트가 어디있는지 알 필요 없다. 이것
은 위치 투명성의 특징을 가질 수 있도록 함.
3) 인터페이스 정의 언어 (IDL, Interface Definition Language)
- 서로 다른 객체끼리 통신을 위해서는 인터페이스가 필요. 이러한 인터페이스 정의를 위해 IDL이 필요.
1.1.5 COM의 역사
1) COM/DCOM은 OLE에서 부터 시작.
- OLE : Object Linking and Embedded. 객체를 연결하고 포함하는 기술. 초기 OLE는 DDE(Dynamic
Data Exchange)를 기반 기술로 하였으나 단점이 많아 OLE 2.0부터는 COM으로 대체됨.
-> OLE자동화와 OLE컨트롤(VBX를 대체)이 추가되었다.
- OLE자동화와 OLE컨트롤 : VB같은 매크로 레벨 언어에서 COM의 인터페이스에 접근이 어려움
-> VB에서 디스패치 인터페이스를 정의하여 COM컴포넌트를 VB에서 사용하기 위해서는 디스패치
인터페이스의 속성과 메소드를 통해 서비스를 제공하도록 함.
- 자동화서버, 자동화 컴포넌트 : OLE의 자동화 서비스를 제공하는 쪽
자동화클라이언트, 자동화 컨트롤러 : OLE의 자동화 서비스를 사용하는 쪽
- 자동화 기술은 매크로나 스크립트 언어에서는 유리하나, C++처럼 인터페이스에 직접 접근 가능한 언
어에서는 유리하지 않음.(속도의 문제). -> 이중 인터페이스로 해결 (자동화, 직접접근)
- 리모트OLE자동화로 3계층 클라이언트/서버를 시작하였으나, DCOM에서 본격적으로 시작됨
- 트랜잭션처리나 컴포넌트관리등은 DCOM만으로는 어려워 이런 서비스를 제공하기 위해 MTS가 생김
-> MTS가 윈도우 OS와 통합되어 COM+
1.2 COM컴포넌트 인터페이스
1.2.1 인터페이스 정의
- 다른 언어로 구현된 클라이언트/서버간에 커뮤니케이션을 위해서 interface를 사용한다.
-> interface : 컴포넌트가 자신의 서비스를 클라이언트에 노출하는 방법
- 모든 COM 컴포넌트는 하나의 IUnknown 인터페이스를 필수적으로 제공해야 함.
1.2.2 인터페이스 메모리 구조
- 인터페이스의 메모리 구조
|
|
|
인터페이스 함수테이블 또는 가상함수테이블 |
|
컴포넌트의 인터페이스 함수 구현 |
|
------> |
vptr |
-----> |
queryInterface함수포인터 |
----> |
HRESULT QueryInterface(){...} |
|
interface 포인터 |
데이터 |
|
AddRef 함수 포인터 |
----> |
ULONG AddRef(){...} |
|
|
Release 함수 포인터 |
----> |
ULONG Release(){...} |
|||
|
|
|
Method1 함수 포인터 |
----> |
HRESULT Method1(){...} |
|
|
|
|
Method2 함수 포인터 |
----> |
HRESULT Method2(){...} |
|
|
|
|
Method3 함수 포인터 |
----> |
HRESULT Method3(){...} |
|
COM인터페이스의 메모리 구조는 C++컴파일러가 추상적인 클래스에 대해 생성한 메모리 구조와 일치
1.2.3 인터페이스 구현과 상속
- COM은 다형성은 지원하지만 상속성은 지원하지 않는다.
-> 상속성에는 인터페이스 상속과 구현 상속이 있다.
* 인터페이스 상속 : 순수 가상함수의 상속
구현 상속 : 가상함수와 비가상함수의 상속을 말함
* 순수가상함수 : 가상함수이나, 함수의 정의부분 없이 선언만 있음
가상함수 : 파생클래스에서 가상함수를 받는 함수가 없다면, 기본 클래스 함수가 호출되고, 있을 경우
파생클래스의 가상함수를 호출시켜주는 매체가 되는 함수
비가상함수 : 일반멤버 함수
(출처 : http://girtowin.tistory.com/30)
- 구현상속은 크게 두가지 단점이 있다.
i) 언어종속적이다 (COM에서 사용하기 어렵다)
ii) 기초클래스가 손상되기 쉬움.
예 )
class Base{ public: virtual void Func1(){ cout << "func1" << endl; } virtual void Func2(){ cout << "func2" << endl; } virtual void Func3(){ cout << "func3" << endl; Func2(); } };
class Child{ public: void Func1(){ cout << "child1" << endl; } void Func2(){ cout << "child2" << endl; } };
//main Child c1; c1.Func1(); c1.Func2(); c1.Func3(); |
위와 같이 호출하면, 결과는 다음과 같다.
child1 child2 func3 child2 |
Func3에서는 Base의 Func2를 호출하려 하였으나, 실제로는 Child의 Func2가 호출된다. Base클래스
의 기능이 달라진다.
- 위와 같은 이유로, COM에서는 인터페이스 상속을 사용한다.
1.3 COM컴포넌트와 GUID
1.3.1 COM컴포넌트의 종류
1) 실행 위치에 따른 분류
- In-process Server
클라이언트와 같은 프로세스에서 실행됨. DLL로 구현됨
- Out-process Server
클라이언트와 다른 프로세스에서 실행됨. EXE로 구현됨
2) Out-process Server는 다시 두 분류로 나눌 수 있음
- local server
서버가 클라이언트와 같은 시스템에서 동작
- remote server
서버가 클라이언트와 다른 시스템에서 동작
1.3.2 GUID
1) interface이름만으로 해당 인터페이스의 고유성을 나타내기 어려움
- 중복되지 않을 고유 번호가 필요하고 이것이 GUID. 128비트의 구조체
출처 - CBD, Component Development with Visual C++,ATL
댓글