참고:
본 글은 COM(Component Object Model)의 개념을 재정리하기 위해 스터디용으로 작성되었습니다.
COM Threading Model의 필요성
- in-process server를 제외한 COM 서버는 기본적으로 단일 COM 개체에 여러 클라이언트 스래드가 접근 가능한 다중스래드 환경에 노출되어 있다. 바로 이 클라이언트의 접근 동기화를 위해 COM threading model이 존재한다.

COM Threading Models
- single-threading model, apartment-threading model, free-threading(multi-threaded) model, mixed-threading(apartment 및 free-threading 지원) model, neutral model의 총 5가지 모델이 존재한다(명칭이 혼란스럽다. free-threading, mixed-threading model, neutral model 역시 apartment를 통한 threading 모델이다. 여기서는 apartment-threading model까지 포함한 이들을 가리켜 Apartment 연관 모델이라 지칭하겠다).
- COM 라이브러리를 사용하기 전에 반드시 호출해야 하는 CoInitializeEx()이 바로 이 모델 지정에 사용된다.
- 클라이언트와 COM 서버의 threading model이 서로 다르더라도 COM run-time 라이브러리가 이들 간 통신을 thread-safe하게 조절하지만, 성능 저하가 발생한다.
Single-Threading Model : 모든 클라이언트의 요청이 단일 스래드 큐에 쌓인다. 오직 단일 스래드 application에만 적합한데, 해당 COM 컴포넌트를 생성한 스래드 이외의 스래드에서는 인터페이스 포인터에 직접적인 접근이 불가능하기 때문이다. 이들 타 스래드에서의 호출, 즉 proxy/stub을 경유한 호출은 메시지 큐에 쌓이고, 언제나 우선 순위가 뒤로 밀린다(해당 COM 컴포넌트를 생성한 스래드에 비해).

Apartment 연관 모델
- 본 모델에서의 모든 클라이언트는 proxy/stub 경유없이 직접적으로 인터페이스 포인터를 얻을 수 있다. apartment란 스래드 병행성(concurrency)을 위한 논리적 구조물으로서, 스래드가 CoInitializeEx()를 호출할 때 생성된다. apartment는 하나 또는 그 이상의 쓰래드와 하나 또는 그 이상의 COM 개체와 연관되어, apartment내의 모든 쓰래드는 해당 apartment에서 생성된 모든 COM 개체가 노출하는 인터페이스 포인터에 직접 접근 가능하다. 프로세스는 여러 STA(Single Threaded Apartment: 하나의 쓰래드만 포함)를 가질 수 있지만 MTA(Multi Threaded Apartment: 여러 쓰래드 포함 가능)는 단 하나만 가질 수 있다.

Apartment-Threading Model(STA) : COM 개체를 생성 및 호출하는 쓰래드가 오직 하나이며, COINIT_APARTMENTTHREADED를 매개변수로 CoInitializeEx()을 호출할 때 생성된다. STA에서 생성된 COM 개체의 인터페이스 포인터는 오직 해당 STA의 쓰래드에서만 접근 가능하며,  타 쓰래드는 marshaling을 통해 노출된 인터페이스 포인터를 통해서만 해당 COM 개체에 접근 가능하다. 이 경우, 각 호출간 동기화는 STA 쓰래드의 (window) message queue를 통해 이룬다.

Free-Threading Model : MTA로 구현하는 본 모델은 하나의 apartment에 여러 쓰래드가 입주 가능하며 COINIT_MULTITHREADED 매개변수를 사용하여 생성한다. COM 개체 사용에 marshaling이 필요없어 최고의 성능을 보이지만, 본 모델을 지원할 COM 개체는 thread-safe하게 구현되어야 하며 동기화 코드가 내장되어 있어야 한다.

Mixed-Threading Model : 여러 STA와 하나의 MTA가 자리잡는 구조이다.

Neutral Model : 앞서 나온 apartment 모델과는 달리 쓰래드가 apartment에 참여하지 않는 COM 개체만 입주한 모델이다. 따라서 어느 apartment의 쓰래드건 NA 안의 COM 개체에 접근 가능하다. 이와 같은 apartment를 가리켜 NA(Neutral Apartment)라 칭하며, 앞서 나온 모델 구현의 복잡성을 줄이기 위에 COM+에서 도입되었다. COM 객체를 생성한 쓰래드는 항상 경량의 proxy를 받아 이를 통해 호출을 한다. 항상 자신을 호출한 쓰래드에서 호출을 받으므로 쓰래드 전환이 필요없어 성능 향상되며, 동기화는 COM+에서 지원한다. 본 모델이 나온 이상 free나 mixed 모델을 사용할 필요가 없어졌다.

Threading Model 관련 Registry  키
in-proces 서버는 registry에 자신의 threading model을 지정해야 하는데, 보통 in-proces server는 CoInitializeEx() 호출을 하지 않기 때문이다. 클라이언트는 in-process 서버를 생성할 경우 registry를 뒤져 marshaling 코드가 필요한지 여부를 알아낸다. 다음과 같은 위치에 해당 섹션이 존재한다.
HKEY_CLASSES_ROOT\CLSID\[component CLSID]\InProcServer32
위 섹션의 ThreadingModel 키 값으로는 None (Single-threading model), Apartment (STA), Free (MTA), Both (mixed model), 그리고 neutral이 올 수 있다.
reference:
Desktop Applications with Microsoft Visual C++ 6.0 MCSD Training Kit,
Understanding COM+, David S. Platt
MSDN
Posted by 어쨌건간에