Level : WORDPRESS BOOK LINKEDIN PATENT Send Mail 동냥하기 hajunho.com

반응형


**COM(Component Object Model)**은 마이크로소프트가 개발한 소프트웨어 기술로, 서로 다른 프로그래밍 언어나 컴퓨터 간에 재사용 가능한 바이너리 소프트웨어 구성 요소를 만들고 통신할 수 있게 합니다. COM은 운영 체제와 응용 프로그램 간의 상호 운용성을 제공하는 핵심 기술 중 하나입니다.

### COM의 역할

1. **재사용 가능한 개체 생성**:
   - COM은 다양한 응용 프로그램에서 재사용 가능한 객체를 만드는 방법을 제공합니다. 이는 객체 지향 프로그래밍의 장점을 극대화합니다.
   
2. **프로그래밍 언어 독립성**:
   - COM 객체는 언어 중립적이므로, C++, C# 등 다양한 언어에서 동일한 COM 객체를 사용할 수 있습니다.
   
3. **바이너리 호환성**:
   - 컴파일된 바이너리 수준에서 상호 운용이 가능하여, 런타임에 동적으로 객체를 생성하고 사용할 수 있습니다.
   
4. **객체 수명 관리**:
   - COM은 참조 카운팅을 통해 객체의 수명을 관리하며, 더 이상 사용되지 않는 객체를 자동으로 해제합니다.

5. **분산 컴퓨팅 지원**:
   - DCOM(Distributed COM)을 통해 네트워크를 넘어 분산 시스템에서도 객체 간의 상호 작용을 지원합니다.

### COM의 구조와 위치

COM은 여러 계층으로 구성되어 있으며, 각 계층은 특정 기능을 제공합니다. 주된 계층은 다음과 같습니다:

1. **COM 라이브러리 (Runtime) 계층**:
   - 이 계층은 COM의 기본적인 기능을 제공합니다. 객체 생성, 참조 카운팅, 인터페이스 쿼리 등을 관리합니다.
   - 주요 컴포넌트:
     - **CoInitialize** / **CoUninitialize**: COM 라이브러리의 초기화 및 종료를 처리합니다.
     - **CoCreateInstance**: 새로운 COM 객체를 생성합니다.
     - **IUnknown** 인터페이스: 모든 COM 객체의 기본 인터페이스로, 참조 카운팅과 인터페이스 쿼리를 담당합니다.

2. **COM 오브젝트 계층**:
   - 실제로 재사용 가능한 객체들이 위치한 계층입니다.
   - 다양한 COM 개체들은 이 계층에서 정의됩니다.
   - 인터페이스 및 구현체는 이 계층에서 제공됩니다.

3. **COM 인터페이스 계층**:
   - COM 객체가 외부와 통신하는 방법을 정의하는 계층입니다.
   - COM 인터페이스는 명확히 정의된 메소드를 포함하고 있으며, 각 인터페이스는 고유의 식별자를 가집니다.

4. **서비스/미들웨어 계층** (예: OLE, ActiveX):
   - COM을 활용한 다양한 서비스 또는 미들웨어입니다.
   - **OLE(Object Linking and Embedding)**: 객체를 문서나 다른 사용자 인터페이스에 포함하고 연결하는 서비스.
   - **ActiveX**: 웹 브라우저와 같은 응용 프로그램에서 재사용 가능한 소프트웨어 컴포넌트를 실행하기 위한 프레임워크.

### COM의 위치

컴포넌트 오브젝트 모델(COM)은 윈도우 운영 체제의 핵심 부분으로, 운영 체제의 다른 서비스 및 기능과 긴밀하게 통합되어 있습니다. 주요 위치와 역할은 다음과 같습니다:

1. **윈도우 운영 체제의 일부**:
   - COM 라이브러리는 운영 체제의 기본 라이브러리로 포함되어 있으며, 윈도우의 다양한 시스템 서비스 및 기능에서 사용됩니다.

2. **레지스트리**:
   - 각 COM 객체는 윈도우 레지스트리에 클래스 ID(클래스 식별자)와 프로그래밍 ID로 등록됩니다. 이를 통해 런타임에 객체를 생성하고 사용할 수 있습니다.

3. **애플리케이션 간 통합**:
   - 마이크로소프트 오피스와 같은 소프트웨어 패키지에서 각기 다른 서비스나 기능을 연결하거나 임베드하기 위해 널리 사용됩니다.

4. **네트워크를 통한 분산 컴퓨팅**:
   - COM은 DCOM(Distributed COM)을 통해 네트워크 상에서도 객체 간 통신을 가능하게 합니다.

### 결론

COM은 윈도우 운영 체제에서 중요한 역할을 수행하며, 다양한 애플리케이션과 서비스 간의 상호 운용성을 제공합니다. 이를 통해 프로그래머는 강력하고 재사용 가능한 소프트웨어 구성 요소를 만들고, 다양한 언어와 플랫폼에서 이를 활용할 수 있습니다.

Windows SDK와 COM의 관계

비록 Windows SDK와 COM은 서로 다른 개념이지만, Windows SDK는 COM을 포함한 다양한 윈도우 기술들을 개발하기 위해 필요한 도구와 라이브러리를 제공합니다. 즉, 윈도우 SDK 내에는 COM 객체를 생성하고 사용할 수 있는 API와 샘플 코드, 도구들이 포함돼 있습니다.

예시:

  • Windows SDK에는 COM 초기화와 관련된 함수인 CoInitializeEx, CoCreateInstance 등과 같은 함수들이 포함된 헤더 파일과 라이브러리들이 존재합니다.
  • 또한, COM을 사용하여 ActiveX 컨트롤을 작성하거나 OLE(Object Linking and Embedding)를 사용하는 애플리케이션을 만들기 위해 필요한 모든 개발 도구와 자원들이 포함되어 있습니다.

결론

  • Windows SDK: 윈도우 운영 체제에서 실행되는 응용 프로그램을 개발하기 위한 포괄적인 개발 툴킷.
  • COM: 윈도우 및 기타 마이크로소프트 플랫폼에서 재사용 가능한 바이너리 구성 요소를 만들고 관리하기 위한 기술.



### 1. 인터페이스 정의

COM 객체는 인터페이스를 통해 상호작용합니다. 인터페이스는 순수 가상 함수로 구성된 클래스입니다.

먼저, 인터페이스를 정의합니다. 인터페이스에는 고유한 인터페이스 식별자(IID)가 필요합니다.

```cpp
#include <Unknwn.h>
#include <guiddef.h>

// 인터페이스 정의
class IMyInterface : public IUnknown {
public:
    virtual HRESULT STDMETHODCALLTYPE MyMethod() = 0;
};

// {12345678-1234-1234-1234-1234567890AB}
DEFINE_GUID(IID_IMyInterface, 
0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB);
```

### 2. 클래스 정의 및 구현

인터페이스를 구현하는 클래스를 정의하고, 클래스 ID(CLSID)를 부여합니다.

```cpp
#include <objbase.h>

class MyCOMObject : public IMyInterface {
    ULONG m_refCount;

public:
    MyCOMObject() : m_refCount(1) {}

    // IUnknown 인터페이스 구현
    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override {
        if (riid == IID_IUnknown || riid == IID_IMyInterface) {
            *ppvObject = static_cast<IMyInterface*>(this);
            AddRef();
            return S_OK;
        }
        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }

    ULONG STDMETHODCALLTYPE AddRef() override {
        return InterlockedIncrement(&m_refCount);
    }

    ULONG STDMETHODCALLTYPE Release() override {
        ULONG refCount = InterlockedDecrement(&m_refCount);
        if (refCount == 0) {
            delete this;
        }
        return refCount;
    }

    // IMyInterface 구현
    HRESULT STDMETHODCALLTYPE MyMethod() override {
        // 메소드 구현
        return S_OK;
    }
};

// {87654321-4321-4321-4321-BA0987654321}
DEFINE_GUID(CLSID_MyCOMObject, 
0x87654321, 0x4321, 0x4321, 0x43, 0x21, 0xBA, 0x09, 0x87, 0x65, 0x43, 0x21);
```

### 3. 공장 클래스 구현

COM 객체를 생성하기 위한 클래스를 구현합니다.

```cpp
class MyClassFactory : public IClassFactory {
    ULONG m_refCount;

public:
    MyClassFactory() : m_refCount(1) {}

    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override {
        if (riid == IID_IUnknown || riid == IID_IClassFactory) {
            *ppvObject = static_cast<IClassFactory*>(this);
            AddRef();
            return S_OK;
        }
        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }

    ULONG STDMETHODCALLTYPE AddRef() override {
        return InterlockedIncrement(&m_refCount);
    }

    ULONG STDMETHODCALLTYPE Release() override {
        ULONG refCount = InterlockedDecrement(&m_refCount);
        if (refCount == 0) {
            delete this;
        }
        return refCount;
    }

    HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject) override {
        if (pUnkOuter != nullptr) {
            return CLASS_E_NOAGGREGATION;
        }

        MyCOMObject* pObject = new MyCOMObject();
        if (pObject == nullptr) {
            return E_OUTOFMEMORY;
        }

        HRESULT hr = pObject->QueryInterface(riid, ppvObject);
        pObject->Release();
        return hr;
    }

    HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) override {
        if (fLock) {
            InterlockedIncrement(&m_refCount);
        } else {
            InterlockedDecrement(&m_refCount);
        }
        return S_OK;
    }
};
```

COM DLL에서 필수적으로 구현해야 하는 DLL 등록 메서드는 `DllGetClassObject`입니다. 이 메서드는 특정 CLSID에 대한 클래스 팩토리를 생성하는 데 사용됩니다. 아래 예제에서는 `MyClassFactory`를 사용하여 이 메서드를 구현하는 방법을 보여드립니다.

### DLL 등록 메서드 구현

```cpp
#include <windows.h>
#include <objbase.h>

extern "C" HRESULT __stdcall DllGetClassObject(
    REFCLSID rclsid, 
    REFIID riid, 
    LPVOID* ppv
) {
    // CLSID 확인
    if (rclsid == CLSID_MyCOMObject) {
        // 클래스 팩토리를 생성하고 QueryInterface를 통해 요청된 인터페이스를 반환
        MyClassFactory *pFactory = new MyClassFactory();
        if (!pFactory) {
            return E_OUTOFMEMORY;
        }

        HRESULT hr = pFactory->QueryInterface(riid, ppv);
        pFactory->Release();
        return hr;
    }

    // 지원되지 않는 CLSID
    return CLASS_E_CLASSNOTAVAILABLE;
}

extern "C" HRESULT __stdcall DllCanUnloadNow() {
    // 이 함수는 DLL이 메모리에서 언로드될 수 있는지 여부를 반환합니다.
    // 예제로서, 항상 S_FALSE를 반환하여 언로드되지 않도록 합니다.
    // 실제 응용 프로그램에서는 참조 카운트를 확인해야 합니다.
    return S_FALSE;
}

```

### 코드 설명

1. **`DllGetClassObject` 메서드**:
   - **`rclsid`**: 생성할 클래스의 CLSID를 나타냅니다.
   - **`riid`**: 요청된 인터페이스의 IID입니다.
   - **`ppv`**: 요청된 인터페이스를 반환하기 위한 포인터입니다.
   - 메서드 내부에서는 주어진 `rclsid`가 지원되는 CLSID인지 확인합니다. 이 경우 `CLSID_MyCOMObject`를 확인합니다.
   - 지원되는 CLSID인 경우, 새로운 `MyClassFactory` 객체를 생성하고, `QueryInterface`를 호출하여 요청된 인터페이스를 반환합니다.
   - 지원되지 않는 CLSID인 경우, `CLASS_E_CLASSNOTAVAILABLE` 오류 코드를 반환합니다.

2. **`DllCanUnloadNow` 메서드**:
   - 이 메서드는 COM 라이브러리를 메모리에서 언로드할 수 있는지 여부를 결정합니다.
   - 참조 카운트를 기반으로 메모리에서 DLL을 언로드할 수 있는지 여부를 반환하는 것이 일반적입니다. 이 예제에서는 항상 `S_FALSE`를 반환하므로, DLL이 언로드되지 않습니다.

### 컴파일 및 사용

이제 DLL을 빌드하고, 이를 등록(regsvr32 사용)한 후, 클라이언트 코드를 작성하여 COM 객체를 사용할 수 있습니다.

1. **컴파일**: Visual Studio 또는 다른 C++ 컴파일러를 사용하여 DLL을 빌드합니다.
2. **등록**: DLL을 시스템에 등록하기 위해 `regsvr32` 유틸리티를 사용합니다.

```sh
regsvr32 MyCOMObject.dll
```

3. **언등록**: 필요시 등록을 해제하기 위해 다음 명령을 사용합니다.

```sh
regsvr32 /u MyCOMObject.dll
```

이 과정을 통해 COM DLL을 성공적으로 등록하고 사용할 수 있습니다. 이제 COM 객체를 클라이언트 응용 프로그램에서 생성하고 사용할 준비가 되었습니다.

COM(Component Object Model)은 소프트웨어 컴포넌트를 객체 기반으로 작성하고, 이 객체들이 서로 상호작용할 수 있게 하는 마이크로소프트의 기술입니다. COM은 단순히 GUID가 있는 DLL 이상의 복잡도를 갖고 있으며, 여러 가지 핵심 개념과 원칙을 포함합니다. 하지만, GUID와 DLL은 COM의 중요한 요소입니다. 아래에서 자세히 설명하겠습니다.

### COM의 주요 개념과 요소

1. **GUIDs (Globally Unique Identifiers)**
   - **CLSIDs (Class IDs)**: COM 개체를 유니크하게 식별하는 데 사용됩니다. CLSID는 특정 COM 클래스의 인스턴스를 생성하기 위한 고유 식별자입니다.
   - **IIDs (Interface IDs)**: 인터페이스를 유니크하게 식별하는 데 사용됩니다. 하나의 COM 클래스는 여러 인터페이스를 구현할 수 있으며, 각 인터페이스는 고유한 IID를 갖습니다.

2. **Interfaces**
   - COM 객체는 명확히 정의된 인터페이스를 통해 상호작용합니다. 인터페이스는 순수 가상 메서드의 집합으로, 객체의 기능을 추상화하며 호출자가 구현 세부 사항을 전혀 알 필요가 없게 합니다.

3. **IUnknown**
   - 모든 COM 인터페이스는 `IUnknown` 인터페이스를 기반으로 합니다. `IUnknown`은 세 가지 메서드를 포함합니다: `QueryInterface`, `AddRef`, `Release`.

4. **DLLs (Dynamic Link Libraries)**
   - COM 개체의 바이너리 구현체는 DLL에 포함됩니다. DLL은 COM 개체의 클래스 구현, 인터페이스, 클래스 팩토리를 포함할 수 있습니다.

5. **Class Factory**
   - COM은 클래스 팩토리를 통해 객체를 생성합니다. 클래스 팩토리는 `IClassFactory` 인터페이스를 구현하며, `DllGetClassObject` 함수로 제공됩니다.

6. **Registry**
   - COM 개체는 시스템 레지스트리에 등록되며, 여기에는 CLSID와 해당 DLL 경로, ProgID 등이 포함됩니다. 클라이언트는 레지스트리를 통해 CLSID를 검색하고, 해당 CLSID의 인스턴스를 생성합니다.

### COM의 작동 방식

1. **클라이언트 요청**
   - 클라이언트는 특정 인터페이스를 구현하는 COM 객체의 인스턴스를 요청합니다.
   
2. **레지스트리 조회**
   - 클라이언트의 요청에 따라 운영 체제는 레지스트리에서 객체의 CLSID와 해당 DLL 경로를 검색합니다.
   
3. **DLL 로드 및 클래스 팩토리 생성**
   - 운영 체제는 해당 DLL을 로드하고, `DllGetClassObject` 함수를 호출하여 클래스 팩토리를 생성합니다. 클래스 팩토리는 요청된 인터페이스의 인스턴스를 생성합니다.
   
4. **객체 사용**
   - 클라이언트는 반환된 인터페이스 포인터를 통해 COM 객체와 상호작용합니다.

### 예시

위에서 설명한 바와 같이, COM은 결국 여러 요소가 결합된 복합적인 시스템입니다. 예를 들어, 다음은 COM 객체를 만들고 사용하는 전반적인 과정입니다.

1. **GUID 정의**: 인터페이스와 클래스를 유니크하게 식별하기 위해 사용됩니다.
2. **인터페이스 정의**: 객체의 기능을 정의합니다.
3. **클래스 구현**: 인터페이스를 구현하는 클래스를 작성합니다.
4. **클래스 팩토리 구현**: 객체를 생성하는 팩토리를 작성합니다.
5. **DLL 등록**: 레지스트리에 COM 객체를 등록합니다.
6. **클라이언트 사용**: 클라이언트는 레지스트리를 통해 객체를 검색하고 사용합니다.

### 요약

COM은 GUID가 있는 DLL이라고 간단히 정의할 수 있지만, 그 이상의 복잡성과 기능을 포함합니다. COM은 인터페이스 기반의 프로그래밍 모델을 제공하며, GUID, DLL, 레지스트리, 클래스 팩토리 등의 다양한 개념이 결합된 시스템입니다. 이를 통해 다양한 언어와 프로세스 간의 상호 운용성을 제공합니다.

 

COM(Component Object Model) 개체는 주로 DLL(Dynamic Link Library)에 포함되지만, LIB(Static Library) 형태로도 존재할 수 있습니다. 다만, COM의 주요 특징인 동적 객체 생성 및 참조 카운팅 같은 기능을 제대로 구현하려면 DLL 형태를 사용하는 것이 보편적입니다. 아래에서는 COM 개체의 DLL과 LIB 형태에 대해 설명하겠습니다.

### DLL vs LIB

1. **DLL (Dynamic Link Library)**:
   - **동적 연결**: 프로그램이 실행되는 동안 동적으로 라이브러리를 로드하고 사용할 수 있습니다.
   - **공유 가능**: 여러 프로그램이 동시에 동일한 DLL을 사용할 수 있습니다. 이는 메모리 사용을 최적화하고, 코드의 재사용성을 높입니다.
   - **참조 카운팅 및 라이프사이클 관리**: COM 개체는 참조 카운팅을 통해 객체의 수명 주기를 관리합니다. 동적으로 로드되는 DLL은 이러한 기능을 더 유연하게 제공합니다.
   - **배포 용이성**: 프로그램 업데이트 시, DLL 파일만 교체하면 되므로 유지보수가 용이합니다.

2. **LIB (Static Library)**:
   - **정적 연결**: 프로그램이 컴파일될 때 라이브러리의 코드가 실행 파일에 직접 포함됩니다.
   - **단일 바이너리**: 프로그램 실행 파일에 라이브러리 코드가 포함되므로 실행 파일이 다소 커질 수 있습니다.
   - **참조 카운팅 어려움**: 참조 카운팅 및 객체의 수명 주기를 관리하는 데 많이 사용하는 COM의 특징을 제대로 활용하기 어려울 수 있습니다. 참조 카운팅과 같은 동적 기능은 주로 DLL에서 더 효과적입니다.
   - **독립 실행 파일**: 외부 DLL에 의존하지 않는 단일 실행 파일을 만들 수 있습니다.

### COM 개체를 LIB 형태로 만드는 경우

일반적으로, COM은 주로 DLL을 통해 구현되지만, 특정 시나리오에서는 LIB 형태로도 사용할 수 있습니다. 예를 들어, 단일 프로세스 내에서만 객체를 활용하거나, 참조 카운팅의 필요성 없이 객체를 사용할 경우입니다.

### COM 개체의 LIB 형태 예시

아래는 COM 개체를 STATIC LIB 형태로 구현하는 단순한 예제입니다.

1. **인터페이스 정의** (header 파일, MyCOMInterface.h):

```cpp
// MyCOMInterface.h
#include <Unknwn.h>

// 인터페이스 정의
class IMyInterface : public IUnknown {
public:
    virtual HRESULT STDMETHODCALLTYPE MyMethod() = 0;
};

// {12345678-1234-1234-1234-1234567890AB}
DEFINE_GUID(IID_IMyInterface, 
0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB);

```

2. **클래스 구현** (소스 파일, MyCOMObject.cpp):

```cpp
// MyCOMObject.cpp
#include "MyCOMInterface.h"
#include <atomic>

class MyCOMObject : public IMyInterface {
    std::atomic<ULONG> m_refCount;

public:
    MyCOMObject() : m_refCount(1) {}

    // IUnknown 인터페이스 구현
    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override {
        if (riid == IID_IUnknown || riid == IID_IMyInterface) {
            *ppvObject = static_cast<IMyInterface*>(this);
            AddRef();
            return S_OK;
        }
        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }

    ULONG STDMETHODCALLTYPE AddRef() override {
        return m_refCount.fetch_add(1) + 1;
    }

    ULONG STDMETHODCALLTYPE Release() override {
        ULONG refCount = m_refCount.fetch_sub(1) - 1;
        if (refCount == 0) {
            delete this;
        }
        return refCount;
    }

    // IMyInterface 구현
    HRESULT STDMETHODCALLTYPE MyMethod() override {
        // 메소드 구현
        return S_OK;
    }
};

extern "C" HRESULT CreateMyCOMObject(REFIID riid, void** ppv) {
    MyCOMObject* pObject = new MyCOMObject();
    if (!pObject) {
        return E_OUTOFMEMORY;
    }
    HRESULT hr = pObject->QueryInterface(riid, ppv);
    pObject->Release();
    return hr;
}
```

3. **정적 라이브러리 생성**:
   - 위의 소스 파일을 정적 라이브러리 ...

- 생략 -

 

COM(Component Object Model)은 동적인 객체 생성, 언어 독립성, 그리고 재사용성을 위해 설계되었으며, 특히 서로 다른 응용 프로그램 간의 상호 운용성을 제공하는 데 매우 유용한 기술입니다. 그러나 특정 상황에서는 COM을 굳이 사용할 필요가 없을 수도 있습니다. 특히 다음과 같은 경우에는 LIB 또는 DLL만으로도 충분할 수 있습니다:

### 언제 LIB 또는 DLL로 충분한가?

1. **단일 애플리케이션 내 사용**:
   - 라이브러리나 객체가 단일 애플리케이션 내에서만 사용되는 경우, COM의 복잡성을 피하고 LIB 또는 DLL을 사용하는 것이 더 간편합니다.

2. **언어 독립성 필요 없음**:
   - 모든 코드가 동일한 언어(C++ 또는 다른 언어)로 작성되었고, 다른 언어에서 호출할 필요가 없는 경우.

3. **단순한 라이브러리 사용**:
   - 단순히 몇 가지 유틸리티 함수나 클래스가 필요하고, 참조 카운팅이나 인터페이스 기반의 설계가 불필요한 경우.

4. **동적 객체 생성 불필요**:
   - 객체의 생성과 사용 주기가 고정되어 있고, 런타임에 동적으로 객체를 생성할 필요가 없는 경우.

### COM을 사용해야 하는 경우?

1. **다양한 언어/애플리케이션 간 상호 운용**:
   - 서로 다른 언어로 작성된 코드나, 여러 애플리케이션 간에 재사용 가능한 객체를 제공해야 하는 경우.
   
2. **동적 객체 생성 필요**:
   - 런타임에 동적으로 객체를 생성하고, 인터페이스를 통해 객체와 상호 작용해야 하는 경우.

3. **기존 COM 인프라 활용**:
   - 이미 COM을 사용하고 있는 시스템이나 애플리케이션과의 상호 작용이 필요한 경우.

### 마이크로소프트 인증 및 등록

COM 개체를 만들기 위해 마이크로소프트의 특별한 인증이 필요한 것은 아닙니다. 기본적으로 COM 개체는 다음 과정을 거칩니다:

1. **인터페이스와 클래스 정의**: 필요한 인터페이스와 클래스를 정의합니다.
2. **라이브러리 작성**: 이 정의에 따라 DLL(LIB일 수도 있음)을 작성합니다.
3. **레지스트리 등록**: 레지스트리에 CLSID와 인터페이스 정보를 등록합니다.

그러나 COM 개체나 서버를 인증함으로써 얻을 수 있는 추가적인 보안 및 안정성 검증을 받을 수는 있습니다. 이는 **디지털 서명**을 통해 이루어집니다. 디바이스 드라이버의 경우와는 달리, COM 개체 자체를 마이크로소프트에 승인받아야 하는 절차는 존재하지 않습니다. 디바이스 드라이버는 운영체제의 핵심 부분과 상호 작용하기 때문에 보다 엄격한 승인 절차를 거치게 됩니다.

### 디지털 서명 및 코드 서명 인증서

- **디지털 서명**: 일반적으로 코드 서명 인증서를 사용하여 COM DLL이나 EXE를 디지털 서명합니다. 이렇게 하면 소프트웨어의 출처를 확인할 수 있고, 악의적인 변조 여부를 검사할 수 있습니다.
- **코드 서명 인증서**: 다양한 인증기관(Certificate Authority, CA)으로부터 코드 서명 인증서를 발급받아 사용할 수 있습니다.

### 결론

- **LIB 또는 DLL**: 단순히 단일 애플리케이션 내에서 사용하거나, 언어 독립성 및 동적 객체 생성이 필요 없으면 LIB 또는 DLL이 적절합니다.
- **COM**: 상호 운용성, 동적 객체 생성, 언어 독립성이 필요할 때 사용합니다. 특별한 마이크로소프트 인증이 필요한 것은 아니며, 디지털 서명을 통해 추가적인 보안 검증을 받을 수 있습니다.

 

Java는 본질적으로 플랫폼 독립적인 언어이기 때문에, Java로 DLL(Dynamic Link Library)을 직접 작성할 수는 없습니다. Java 애플리케이션을 네이티브 코드로 컴파일하여 DLL을 생성할 수 있는 도구도 있지만, 이는 Java 언어의 본래 목적에 맞지 않는 경우가 많습니다.

그러나 Java로 COM 객체를 작성하고, 이를 사용하기 위해 몇 가지 방법을 사용할 수 있습니다. 주로 **Java Native Interface (JNI)**와 **JACOB(Java COM Bridge)** 같은 라이브러리를 활용합니다. 여기서는 Java로 COM 객체를 작성하는 간단한 예제를 보여드리고, 이를 DLL 형태로 네이티브 코드에 래핑하는 방법을 설명하겠습니다.

### 1. Java Native Interface (JNI) 사용

JNI를 사용하면 Java 애플리케이션이 네이티브 코드(C/C++)를 호출하거나, 네이티브 코드에서 Java 코드를 호출할 수 있습니다. 이를 통해 C++로 작성된 COM DLL을 사용하게 할 수 있습니다.

#### 단계 1: Java 클래스 작성

먼저, 네이티브 메서드를 선언한 Java 클래스를 작성합니다.

```java
public class MyCOMBridge {
    // Load the native library
    static {
        System.loadLibrary("MyCOMBridge");
    }

    // Native method declaration
    public native void myNativeMethod();

    public static void main(String[] args) {
        MyCOMBridge bridge = new MyCOMBridge();
        bridge.myNativeMethod();
    }
}
```

#### 단계 2: JNI 헤더 파일 생성

Java `javah` 도구를 사용하여 JNI 헤더 파일을 생성합니다.

```sh
javac MyCOMBridge.java
javah -jni MyCOMBridge
```

#### 단계 3: C++로 네이티브 코드 작성

생성된 헤더 파일을 포함하여 네이티브 메서드를 구현합니다. 예를 들어, C++로 작성된 COM 클래스를 사용합니다.

```cpp
#include <jni.h>
#include "MyCOMBridge.h"

// Example of a COM interface and class definition
#include <objbase.h>
#include "MyCOMObject.h"

JNIEXPORT void JNICALL Java_MyCOMBridge_myNativeMethod(JNIEnv *env, jobject obj) {
    // COM Initialization
    CoInitialize(NULL);

    // Create a COM object instance
    IMyCOMObject* pMyObject = NULL;
    HRESULT hr = CoCreateInstance(CLSID_MyCOMObject, NULL, CLSCTX_INPROC_SERVER, IID_IMyCOMObject, (void**)&pMyObject);

    if (SUCCEEDED(hr)) {
        // Call a method on the COM object
        pMyObject->SomeMethod();
        pMyObject->Release();
    }

    // COM Uninitialization
    CoUninitialize();
}
```

#### 단계 4: 네이티브 코드 컴파일

생성한 네이티브 코드를 컴파일하여 DLL을 만듭니다.

```sh
g++ -I<path-to-java-include> -I<path-to-java-include-win32> -shared -o MyCOMBridge.dll MyCOMBridge.cpp
```

### 2. JACOB(Java COM Bridge) 사용

JACOB 라이브러리는 Java 애플리케이션에서 COM 객체를 직접 사용할 수 있게 도와줍니다. JACOB을 사용하면, COM 객체를 직접 Java에서 다룰 수 있습니다.

#### 단계 1: JACOB 라이브러리 설정

먼저, JACOB 라이브러리를 다운로드하고 프로젝트에 포함시킵니다. JACOB은 Java 애플리케이션이 COM 객체에 접근할 수 있게 도와줍니다.

#### 단계 2: Java 코드 작성

JACOB 라이브러리를 사용하여 COM 객체를 생성하고 호출하는 코드를 작성합니다.

```java
import cohttp://m.jacob.com.*;
import com.jacob.activeX.*;

public class COMTest {
    public static void main(String[] args) {
        // Initialize COM
        ComThread.InitMTA();

        try {
            ActiveXComponent comObject = new ActiveXComponent("YourCOM.ObjectProgID");
            Dispatch.call(comObject, "YourMethodName");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Uninitialize COM
            ComThread.Release();
        }
    }
}
```

### 결론

Java는 본래 플랫폼 독립적이기 때문에 직접적으로 DLL을 작성하기에는 적합하지 않습니다. 그러나:

- **JNI**를 사용하여 네이티브 코드(C/C++)와 상호작용하여 간접적으로 COM 객체를 사용할 수 있습니다.
- **JACOB** 라이브러리를 사용하여 Java 코드에서 직접 COM 객체를 사용할 수 있습니다.


Python은 다양한 라이브러리를 활용하여 COM 객체를 직접 생성하고 사용할 수 있습니다. 가장 널리 사용되는 라이브러리 중 하나가 **pywin32**입니다. pywin32는 Python 환경에서 Windows API와 COM을 사용할 수 있는 기능을 제공합니다. 

### Python으로 COM 객체 생성하기

Python에서는 상대적으로 간단하게 COM 객체를 생성하고 사용할 수 있습니다. 아래에서는 Python으로 COM 객체를 생성하는 방법에 대해 설명하겠습니다.

#### 필요 라이브러리 설치:

먼저 pywin32 라이브러리를 설치해야 합니다.

```sh
pip install pywin32
```

#### Python으로 COM 객체 작성:

Python으로 COM 객체를 작성하는 예제를 보여드리겠습니다. 이 예제에서는 간단한 COM 클래스(예: `MyPythonCOMObject`)를 만들어 COM 서버로 등록합니다.

1. **COM 클래스 정의**

먼저 Python에서 COM 객체를 정의합니다.

```python
import pythoncom
from win32com.server import register
from win32cohttp://m.server.policy import DesignatedWrapPolicy

class MyPythonCOMObject:
    _public_methods_ = ['MyMethod']
    _reg_progid_ = "MyPythonCOMObject.ProgID"
    _reg_clsid_ = "{12345678-1234-1234-1234-1234567890AB}"  # GUID 생성 필요

    def MyMethod(self):
        print("MyMethod called")
        return "Hello from MyPythonCOMObject"

# COM 서버로 등록
if __name__ == '__main__':
    register.UseCommandLine(MyPythonCOMObject)
```

2. **COM 서버 등록**

위 코드를 실행하여 Python COM 객체를 등록합니다. 이는 Python 스크립트를 실행하여 COM 서버로 등록할 수 있습니다.

```sh
python my_com_object.py --register
```

3. **COM 객체 사용**

이제 등록된 COM 객체를 다른 애플리케이션에서 사용할 수 있습니다. 예를 들어, Python 스크립트나 다른 COM 클라이언트에서 COM 객체를 사용할 수 있습니다.

#### COM 객체 사용 예제:

- Python에서 사용:

```python
import pythoncom
from win32com.client import Dispatch

com_object = Dispatch("MyPythonCOMObject.ProgID")
result = com_object.MyMethod()
print(result)
```

- VBScript에서 사용:

```vbscript
Dim comObject
Set comObject = CreateObject("MyPythonCOMObject.ProgID")
MsgBox comObject.MyMethod()
```


### Python으로 COM DLL 만들기 (C++ 사용 없이)

Python은 본래 DLL 파일을 출력하지 않지만, Python으로 작성된 COM 서버는 pywin32와 같은 라이브러리를 통해 COM 개체로서 작동할 수 있습니다. 또한, py2exe와 같은 도구를 사용하면 Python 스크립트를 EXE 파일로 패키징할 수 있습니다.

### 결론

Python을 사용하면 pywin32 라이브러리를 통해 비교적 간단하게 COM 객체를 작성하고 등록할 수 있습니다. 이를 통해 COM 객체를 다양한 애플리케이션에서 사용할 수 있습니다. C++과 같은 네이티브 언어를 사용하지 않고도 Python만으로 COM 객체를 생성, 등록, 사용이 가능하므로 매우 편리한 방법입니다.

COM 보다는 Cython 이 나아보인다.

Cython을 사용하는 것이 개발 스트레스를 줄이는 데 매우 도움이 될 수 있습니다. 이는 특히 Python과 C/C++ 코드를 통합하는 작업에서 더욱 두드러집니다. Cython은 COM 객체보다 더 간단하고 직관적인 인터페이스를 제공하여 Python 개발자가 네이티브 성능을 필요한 부분에서 쉽게 활용할 수 있게 합니다. 아래에서 Cython의 장점과 COM 객체와 비교한 차이점들을 간략하게 소개하겠습니다.

### Cython의 장점

1. **간단한 문법**:
   - Python 느낌의 문법으로 C/C++ 코드와 상호작용할 수 있습니다.
   - 기존 Python 코드를 약간 수정하는 것만으로도 성능 향상을 기대할 수 있습니다.

2. **성능 최적화**:
   - Python의 인터프리터 오버헤드를 줄이고, 네이티브 성능을 이용할 수 있습니다.
   - C 데이터 타입을 활용하여 더 빠른 실행 속도를 얻을 수 있습니다.

3. **유연성**:
   - C, C++, 그리고 Python 코드를 쉽게 혼합하고 통합할 수 있습니다.
   - 기존 C/C++ 라이브러리를 손쉽게 재사용할 수 있습니다.

4. **쉬운 배포**:
   - setup.py 스크립트를 활용하여 쉽게 패키징하고, 다른 사용자에게 배포할 수 있습니다.
   - Python 패키지 관리 시스템(pip)을 통해 설치하고 사용할 수 있습니다.

5. **낮은 학습 곡선**:
   - Python 개발자는 비교적 짧은 시간 내에 Cython을 익히고 사용할 수 있습니다.

### COM 객체와 Cython의 비교

1. **복잡성**:
   - COM: COM 객체는 인터페이스 정의, 레지스트리 등록, 클래스 팩토리 구현 등을 필요로 하며, 이는 초기 설정과 사용에 있어 복잡성을 증가시킵니다.
   - Cython: Cython은 상대적으로 간단하고 직관적이며, Python 파일과 함께 네이티브 코드를 작성할 수 있습니다.

2. **상호 운용성**:
   - COM: 여러 언어와 프로세스 사이의 상호 운용성을 제공합니다. 다양한 프로그래밍 언어에서 사용될 수 있습니다.
   - Cython: 주로 Python과 C/C++ 간의 상호 운용성에 집중합니다. Python 생태계 내에서의 사용이 용이합니다.

3. **성능**:
   - COM: 강력한 성능을 제공할 수 있지만, COM 인터페이스를 호출하는 데 따른 오버헤드가 존재할 수 있습니다.
   - Cython: 네이티브 성능을 거의 그대로 제공하며, Python 인터프리터 오버헤드를 크게 줄입니다.

4. **디버깅**:
   - COM: 디버깅이 상대적으로 어렵고, COM 등록 문제 등 다양한 문제를 해결해야 할 수 있습니다.
   - Cython: 디버깅이 비교적 간단하며, Python 디버깅 도구를 그대로 사용할 수 있습니다.

5. **통합**:
   - COM: COM 객체는 Windows 플랫폼에 더 적합하며, 등록 및 배포에 비교적 많은 작업이 필요합니다.
   - Cython: 크로스 플랫폼(Windows, macOS, Linux)에서도 잘 지원되며, setup.py를 통해 쉽게 빌드 및 배포할 수 있습니다.

### 결론

- **쉬운 통합 및 높은 성능**: Cython은 Python 코드에 C/C++의 성능을 쉽게 통합할 수 있는 강력한 도구입니다.
- **단순한 문법과 사용성**: Cython은 간단한 문법과 강력한 기능을 제공하여 빠르게 성능을 향상시킬 수 있습니다.
- **복잡성 감소**: COM 객체에 비해 설정과 사용이 훨씬 간단하며, 개발자의 스트레스를 줄일 수 있습니다.

따라서 Python과 C/C++의 인터페이스를 만들고, 성능 향상 및 네이티브 코드 사용이 중요한 경우, **Cython**이 **COM 객체**보다 더 나은 선택이 될 수 있습니다.


2013 년, 2014 년 애드센스 수익과 관련 썰


 

별 거 안해도 돈을 많이 주던 시절이 있었다. 네이버 지식 in 도 초창기에는 돈을 주었기에 나는 매달 10만원 정도 받았던 것 같다. 구글 수익과 합하면 30~40만원 정도였다.

그러나 네이버도 구글도 어느 정도 사람이 모이면 돈을 적게 주고, 대신 모임을 개최한다.

 

난 유투브를 동영상 저장용으로 쓰는데 유투브가 처음 나오고 나서 바로 해서 그런지 구독자가 2천명은 되었었기에 유투버 모임에 초대되어 갈 수 있었다.

 

그 모임에 내 나이는 평균 이상이었고, 어린 친구들이 정말 돈을 많이 벌 것 같다는 생각이 사활을 걸고 참여하는 경우가 많았다.

 

정말 안타깝다.

 

구글, 네이버, 심지어 카카오까지(티스토리는 제외) 통계를 조작하고, 돈은 줄 만한 사람에게 준다. 내가 2008년 부터 삼성전자 다녀서 그런지 삼성전자에서 주말 이틀 출근만 해도 컨텐츠 관리하며 개고생해서 버는 돈보다 훨씬 많은 돈을 받았기 때문에 신경을 안 썼다. 물론, 티스토리는 애드센스 때문에 많이 하지만, 나의 최종 결정은 티스토리의 기능이 이미 구글의 블로거를 넘어섰고, 모바일에서는 유료앱이 달랑 1개 있는데 그것도 기능이 좋긴 하지만 티스토리가 제공하는 앱이 훨씬 좋기 때문이다. 1년간은 이전하고 광고를 나도 광고를 달 생각이다. 왜냐면 티스토리에 다는 광고는 사실 좀 파격적이기 때문이다. 구글 블로거야 걔네들이 서버를 운영하니까 돈 주는 것을 마음대로 조작한다고 쳐도. 티스토리의 경우 티스토리가 서버를 운영하니까 수익이 당연히 좋게 줄 수 밖에 없다. 네이버도 마찬가지. 그런데 다른 회사의 광고 모듈을 달게 한다는 것 자체가 대단한 파격이다. 물론, 거기에 따른 이유를 내가 모르는 것도 아니지만 네이버처럼 추잡하게 하지는 않는다. 추잡한 것은 어떤 것이냐? 해외에서는 차나 휴대폰 싸게 팔고 자국민에게 비싸게 팔면 이완용 짓거리랑 뭐가 다를게 있냐고 이미 알고 있을 것이다. 우리나라가 산유국은 아니지만 정유국인데 무지하게 기름값이 비싸다. 미국은 산유 되는 곳도 있긴 하지만 정유가 가능하기에 한국 반값이라는 것을 이해한지 십수년도 넘었다. 그런데 우리나라는 아니다. 네이버도 마찬가지. 동영상 광고 수익 때문에 유투브에서 막아 놨다. 여기까지는 사실 기업이니 이해가 가능한데, 한국만 막아놨다. 왜냐면 네이버가 외국에서 실패했기 때문이다. 8년전 내가 미국에 있을 때 무슨 미국 지역 전문가 모집한다고 네이버에서 떠들었는데 내가 이미 지식인 하면서 수작을 아는 터라 주변 IT 인들에게 이거 사기라고 많이 말을 해줬다. 믓튼, 미국 진출 실패해서 결국 자국민에게만 불편하게 하고 스킵도 오래도록 되지 않는 동영상을 보여주는 것이다. 한마디로 이.완.용, 매.국.노. 그러니 문화 사업을 할 수 밖에 없다. 그러니 경찰에 개인 정보를 동의 없이 넘겨줄 수 밖에 없다. 카카오는 그나마 이슈라도 되었는데 네이버는 이슈도 안된다. 댓글 조작이나 이슈되지. 왜냐? 네이버가 카카오 찔렀기 때문이다. 경쟁 없애려고. 모두 잘 알겠지만 제보 없이는 아무것도 안된다. 이 블로그에서 모두 풀 생각이다.

 

뭐... 잡썰이 더 길어 졌는데.

 

백만을 찍는 유투브 영상을 보면 이벤트를 하는데 사실 그 안에 들어가는 돈을 보면 백만원이 안된다. 나 같으면 산타하고 그러면 찾아 가서 수천만원치 쿨하게 지원해주겠는데 그런게 될 수 없는 구조라는 것이다.

 

길게 쓰려면 한없이 길어질 것 같아서. 결론만 말한다.

 

개인이 수입억 버는 것은 알려지지 않았을 때 그렇게 벌 수 있다. 사업체 형태여야 한다. 자, 일반화까지는 아니지만 나중에 할 이야기에 대해서 이슈를 던져 보겠다.

 

개인 프리랜서도 그렇다. 개인이 프리랜서 하면 3.3% 떼고 주고 무시하고 그런데 사업체 끼면 사업자 대 사업자기 때문에 부가가치세 10% 더 받고 대우도 다르다.

 

어디나 그렇다. 당신이 개인이라는 것이 알려지는 순간 회사는 멈추지 않을 만큼만 돈을 주게 된다.

 

그래서 많은 유투버들이 합치게 된다. 출구 전략을 세우게 된다.

 

그만큼의 고민을 하려면 지금 하는 학업이나 일을 그만두고 해야할 정도다.

 

개인 의견이지만 난 솔직하게 쓴다.

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기