COM 컴포넌트 모델의 인터페이스와 Windows 상호운용 구조
COM의 바이너리 인터페이스, IUnknown 참조 카운팅, GUID, DCOM과 COM+의 동작 구조를 정리한다.
2026-08-14 · 최초 발행 2026-01-12
바이너리 인터페이스로 컴포넌트를 연결하는 COM
COM(Component Object Model)은 Microsoft가 만든 컴포넌트 기반 소프트웨어 아키텍처다. 핵심은 소스코드가 아니라 바이너리 수준의 인터페이스다. 따라서 C++, VB, Delphi처럼 서로 다른 언어로 만든 컴포넌트도 약속된 인터페이스를 통해 통신하고 재사용할 수 있다.
COM은 인터페이스 중심으로 동작하며, 컴포넌트가 어느 위치에서 실행되는지도 호출자에게는 같은 인터페이스로 드러난다.
| 특성 | 내용 |
|---|---|
| 언어 독립성 | C++, VB, Delphi 등 다양한 언어 지원 |
| 위치 투명성 | 인프로세스, 로컬, 원격에서 동일한 인터페이스 사용 |
| 버전 호환성 | 인터페이스 불변성 원칙 |
| 바이너리 표준 | 소스코드 없이 컴포넌트 재사용 |
런타임과 클래스 팩토리로 객체를 찾는 구조
클라이언트는 COM 런타임을 거쳐 클래스 팩토리에 객체 생성을 요청한다. 생성된 COM 객체는 IUnknown과 필요한 개별 인터페이스를 제공한다.
COM 객체와 주변 구성요소는 다음 역할로 나뉜다.
| 구성요소 | 역할 |
|---|---|
| COM Object | 인터페이스를 구현하는 객체 |
| Interface | 메서드 집합 정의 |
| Class Factory | 객체 생성 팩토리 |
| SCM | 서비스 제어 관리자 |
| Registry | 컴포넌트 등록 정보 |
| Type Library | 인터페이스 메타데이터 |
IUnknown이 맡는 인터페이스 조회와 수명 관리
모든 COM 인터페이스는 IUnknown을 기반으로 한다. 모든 COM 객체가 구현해야 하며, QueryInterface, AddRef, Release를 통해 다른 인터페이스를 얻고 객체의 참조 수를 관리한다.
| 메서드 | 기능 | 반환 |
|---|---|---|
| QueryInterface | 다른 인터페이스 포인터 획득 | HRESULT |
| AddRef | 참조 카운트 1 증가 | ULONG |
| Release | 참조 카운트 1 감소 | ULONG |
참조 카운팅은 객체가 더 이상 필요하지 않은 시점을 결정한다. 객체를 생성한 뒤 인터페이스를 추가로 요청하면 참조 수가 증가하고, 호출자가 Release를 수행하면서 참조가 모두 사라지면 객체가 소멸한다.
GUID로 클래스와 인터페이스를 구분한다
COM은 전역적으로 고유한 식별자인 GUID를 사용한다. GUID는 128비트 식별자이며 {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} 형식을 따른다. 알고리즘에 기반해 고유성을 보장한다.
COM 환경에서는 식별 대상에 따라 서로 다른 GUID 유형을 사용한다.
| 식별자 | 용도 | 예시 |
|---|---|---|
| CLSID | 클래스 식별 | CLSID_Application |
| IID | 인터페이스 식별 | IID_IUnknown |
| LIBID | 타입 라이브러리 식별 | LIBID_Office |
| CATID | 컴포넌트 카테고리 | CATID_Control |
실행 위치에 따라 달라지는 COM 서버
COM 서버는 클라이언트와 같은 프로세스에 로드될 수도 있고, 별도 프로세스나 원격 컴퓨터에서 실행될 수도 있다.
In-Process Server (DLL)
DLL 형태의 서버는 클라이언트 프로세스 안에 로드된다. 같은 주소 공간을 사용하므로 가장 빠르지만 격리는 제공하지 않는다.
Local Server (EXE)
EXE 형태의 로컬 서버는 별도 프로세스로 실행된다. 클라이언트는 프록시를 거쳐 LPC(Local Procedure Call)로 서버의 스텁과 통신하며, 프로세스 수준의 격리를 얻는다.
Remote Server (DCOM)
원격 서버는 다른 컴퓨터에서 실행되는 COM 서버다. 통신에는 네트워크를 통한 RPC를 사용하며, 이 분산 통신 모델을 DCOM(Distributed COM)이라고 한다.
IDL에서 계약을 정의하고 MIDL로 산출물을 만든다
COM 인터페이스는 IDL(Interface Definition Language)로 정의할 수 있다. 다음 예시는 IUnknown을 상속한 계산기 인터페이스다.
[
object,
uuid(12345678-1234-1234-1234-123456789ABC),
pointer_default(unique)
]
interface ICalculator : IUnknown
{
HRESULT Add([in] int a, [in] int b, [out, retval] int* result);
HRESULT Subtract([in] int a, [in] int b, [out, retval] int* result);
HRESULT Multiply([in] int a, [in] int b, [out, retval] int* result);
HRESULT Divide([in] int a, [in] int b, [out, retval] int* result);
}
MIDL 컴파일러는 IDL 정의를 바탕으로 헤더 파일, 타입 라이브러리, 프록시와 스텁 코드를 생성한다.
COM 위에서 확장된 기술
OLE(Object Linking and Embedding)는 복합 문서를 위한 기술이다. 문서 안에 객체를 삽입하거나 연결할 수 있으며, Word 문서에 Excel 차트를 삽입하는 용도로 사용된다.
ActiveX는 웹 기반 COM 컨트롤이다. 브라우저 플러그인과 리치 클라이언트에 사용되며, 코드 서명이 필요하다.
Automation은 IDispatch를 통해 스크립팅 언어가 COM 객체를 사용할 수 있도록 한다. 런타임 바인딩을 특징으로 하며 VBScript와 JavaScript에서 COM 호출에 사용된다.
네트워크 너머의 COM, DCOM
DCOM은 네트워크 기반의 분산 COM이며 TCP/IP 위에서 RPC를 사용한다. 로컬 COM과 같은 인터페이스로 원격 객체에 접근할 수 있다는 점이 특징이다.
DCOM 보안은 인증, 접근 제어, 암호화, 위장으로 구분해 볼 수 있다.
| 수준 | 설명 |
|---|---|
| 인증 | NTLM, Kerberos |
| 권한 | ACL 기반 접근 제어 |
| 암호화 | 패킷 암호화 옵션 |
| 위장 | 클라이언트 컨텍스트 |
COM+가 더한 엔터프라이즈 서비스
COM+는 COM에 엔터프라이즈 서비스를 추가한 기술이며, 이전 이름은 MTS(Microsoft Transaction Server)다. 관리는 Component Services MMC에서 수행한다.
| 서비스 | 기능 |
|---|---|
| 분산 트랜잭션 | DTC를 통한 2PC 트랜잭션 |
| 객체 풀링 | 객체 재사용으로 성능 향상 |
| JIT 활성화 | 필요 시 객체 활성화 |
| 역할 기반 보안 | 선언적 보안 설정 |
.NET 환경에서 이어지는 COM 상호운용
COM과 .NET은 메타데이터, 배포, 버전 관리, 메모리 관리 방식이 다르다. .NET은 COM Interop을 통해 기존 COM 구성요소와 연결할 수 있다.
| 항목 | COM | .NET |
|---|---|---|
| 메타데이터 | Type Library | Assembly Manifest |
| 배포 | 레지스트리 등록 | XCOPY/GAC |
| 버전 관리 | 복잡 (DLL Hell) | Side-by-Side |
| 메모리 관리 | 참조 카운팅 | 가비지 컬렉션 |
| 상호운용 | - | COM Interop |
.NET에서 COM 객체를 사용할 때는 RCW(Runtime Callable Wrapper)를 사용하고, COM에서 .NET을 사용할 때는 CCW(COM Callable Wrapper)를 사용한다.
COM은 IUnknown 기반의 인터페이스 조회와 참조 카운팅을 통해 언어 독립적인 컴포넌트 재사용을 제공한다. OLE, ActiveX, DCOM, COM+으로 확장된 이 구조는 .NET으로 대체되는 추세에도 Windows 운영체제와 Office 등 Microsoft 제품의 기반으로 남아 있다.