본문 바로가기

IT 살이/04. 기술 - 프로그래밍

로딩되는 CLR 버전 결정하기

얼마전에 달봉이 여자 친구가 업체로부터 질문을 하나 받았다는 것이다. 내용을 보면 .NETv1.?에서 개발한 스마트클라이언트 애플리케이션을 .NETv1.? .NETv2.0이 설치된 클라이언트 PC에서 다운해서 구동시켰더니 이전과는 다른 거동을 하더라는 것이다.

그 다른 내용이 무엇이든지 간에 이렇게 다른 버전의 CLR이 설치되어 있는 PC에서 특정 버전의 CLR을 사용하려면 어떻게 해야 하는지 그 동안 달봉이는 궁금했다.

1. CLR Facade : MSCOREE.DLL

CLR
의 실제 DLL MSCORWKS.DLL 이다. 만약 멀티 프로세서를 사용하는 PC에서라면 MSCORSVR.DLL이 사용된다. 그리고 하나의 PC에는 여러 버전의 CLR이 설치될 수 있다. .NET 프레임워크가 설치된 PC에는 MSCOREE.DLL도 설치되어 있는데, 이것은 특정 PC에서 어떤 DLL의 CLR과 어떤 버전의 CLR을 사용할 것인가를 결정하는 일을 한다. DLL 파일을  "shim"이라고 부른다.

"shim"은 우리나라 말로도 그냥 ""이라고 한다. 영한 사전을 찾아보면 이렇게 나와있다. "틈새를 메우거나 물건을 수평으로 하기 위해 사용하는 나뭇조각이나 금속 조각 등". 파티션으로 사무실 공간을 나눠서 사용하는데, 그 파티션과 파티션을 연결하는 얇은 줄기같은 것들을 본 일이 있을 것이다. 이것을 ""인 것이다.

MSCOREE.DLL은 외부의 세계에서 CLR에 접근하려고 할때 제일 먼저 통과하는 관문(Facade)역할을 한다고 해서 CLR Facade라고 그림에도 표현되어 있다.

1352473588

MSCOREE 와 그의 친구들


MSCorEE.dll(shim)

이 하는 Facade 역할을 그림으로 그려보면 다음과 같다.

1106181055

Facade로서의 MSCorEE.dll

MSCorEE.dll이 하는 일은 로딩될 CLR의 버전을 결정하는 일이다. 앞에서 말한대로 MSCorEE.dll 자체는 CLR을 구현하고 있지는 않다.

하나의 머신에는 여러 버전의 CLR이 설치되어 있을 수 있지만, MSCorEE.dll은 가장 마지막 버전의 CLR과 함께 배포된 버전 하나만 설치된다. 따라서 최종 버전의 MSCorEE.dll은 이전에 설치된 CLR 버전을 알 수 있게 되는 것이다.

MSCorEE.dll은 호출한 호스팅 애플리케이션이 어떤 버전의 CLR로 빌드되었는지를 먼저 확인해서, 그 애플리케이션을 빌드한 CLR을 자동 로딩시킨다.

( 따라서 달봉이 여자 친구가 말한 것처럼,  애플리케이션을 빌드한 CLR 버전을 일부러 로딩시키려고 할 필요가 없다. 근데 이 기능이 제대로 작동하지 않는다는 얘기가 있다. )


그러나 MSCorEE.dll이 로딩할 CLR 버전을 결정할때 사용자가 참여할 수 있는 방법이 있다. 아래에 그 방법을 설명하고 있다.


2. 로딩될 CLR 버전 결정

사용자는 어떤 버전의 CLR을 로딩시켜야 할지에 대한 정보을 레지스트리, 환경 설정 정보를 통해서 MSCORE.DLL에게 전달할 수 있다.

1) 레지스트리 값 참조

[HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework]
Version=v1.0.3215
InstallRoot=C:\windows\Microsoft.NET\Framework\



MSCOREE.DLL
이 로딩할 CLR DLL을 찾기위해서, 단순히 두 값을 결합한 값을 이용한다.
"C:\windows\Microsoft.NET\Framework\v1.0.3215"
디렉토리에 있는 CLR DLL을 로딩한다.

2) 애플리케이션의 환경 설정 파일(.config) 이용

만약 실행되는 애플리케이션의 설정 파일에 CLR의 버전에 대한 설정이 있다면 레지스트리 값을 대신해서 사용된다. 다음은 MSDN에서 참조한 내용이다.

<!-- 1.0 버전의 CLR을 사용할때 -->
<configuration>
  <startup>
     <requiredRuntime version="v1.0.3705" safemode="true"/>
  </startup>
</configuration>

<!-- 1.1( 또는 이후) 버전의 CLR을 사용할때  -->
<configuration>
  <startup>
     <supportedRuntime version="v1.1.4322"/>
     <supportedRuntime version="v1.0.3705"/>
  </startup>
</configuration>

<startup> 요소의 자식으로는 다음 두가지 올 수 있다.

<requiredRuntime>
1.0
대의 CLR을 사용해서 개발된 애플리케이션에서만 사용할 수 있다만약 1.1 버전 이후의 프레임워크로 만드어진 애플리케이션은 <supportedRuntime> 요소를 사용해야 한다.

<supportedRuntime>
앞의 예제 코드에서는 애플리케이션이 v1.1.4322 v1.0.3705을 지원한다는 것을 나타낸다. 애플리케이션이 지원하는 CLR 버전을 지정할때 사용한다. <supportedRuntime> 요소는 1.1 이후의 버전의 CLR을 사용하여 빌드한 애플리케이션에 대해서 사용할 수 있다. 1.0대 버전으로 빌드한 애플리케이션은 <requiredRuntime> 요소를 사용해야 한다. 애플리케이션의 설정 파일에 <supportedRuntime> 요소가 없다면 애플리케이션을 빌드할때 사용된 버전이 사용된다.

만약 앞의 예제처럼 여러 버전이 설정되어 있다면 처음 설정된 버전의 CLR이 우선적으로 로딩될 기회를 갖는다. 만약 그 버전이 없다면 다음으로 명시된 버전의 CLR이 로딩된다.

IE
브라우저의 호스팅을 받아 시작하는 애플리케이션은 <startup>요소와 그  자식 요소들 <requiredRuntime>, <supportedRuntime>을 무시한다.


참조 문서

Essential .NET Volume 1
The Common Language Runtime
- Don Box with Chris Sells

CLR via C#
- Jeffrey Richter