비고
이 문서는 .NET Framework에만 적용됩니다. .NET 6 이상 버전을 포함하여 .NET의 최신 구현에는 적용되지 않습니다.
.NET Framework 애플리케이션을 성공적으로 배포하려면 공용 언어 런타임이 애플리케이션을 구성하는 어셈블리를 찾아 바인딩하는 방법을 이해해야 합니다. 기본적으로 런타임은 애플리케이션이 빌드된 어셈블리의 정확한 버전과 바인딩하려고 시도합니다. 이 기본 동작은 구성 파일 설정으로 재정의할 수 있습니다.
공용 언어 런타임은 어셈블리를 찾고 어셈블리 참조를 확인하려고 할 때 여러 단계를 수행합니다. 각 단계는 다음 섹션에서 설명합니다. 검색이라는 용어는 런타임이 어셈블리를 찾는 방법을 설명할 때 자주 사용됩니다. 이름 및 문화권에 따라 어셈블리를 찾는 데 사용되는 추론 집합을 나타냅니다.
비고
Windows SDK에 포함된 어셈블리 바인딩 로그 뷰어(Fuslogvw.exe)를 사용하여 로그 파일에서 바인딩 정보를 볼 수 있습니다.
바인딩 시작
어셈블리를 찾고 바인딩하는 프로세스는 런타임이 다른 어셈블리에 대한 참조를 확인하려고 할 때 시작됩니다. 이 참조는 정적 또는 동적일 수 있습니다. 컴파일러는 빌드 시 어셈블리 매니페스트의 메타데이터에 정적 참조를 기록합니다. 동적 참조는 다음과 같은 Assembly.Load다양한 메서드를 호출한 결과로 즉석에서 생성됩니다.
어셈블리를 참조하는 기본 방법은 어셈블리 이름, 버전, 문화권 및 공개 키 토큰(있는 경우)을 비롯한 전체 참조를 사용하는 것입니다. 런타임은 이 정보를 사용하여 이 섹션의 뒷부분에 설명된 단계에 따라 어셈블리를 찾습니다. 런타임은 참조가 정적 어셈블리인지 동적 어셈블리에 대한 것인지에 관계없이 동일한 확인 프로세스를 사용합니다.
어셈블리 이름만 지정하는 등 어셈블리에 대한 부분 정보만 호출 메서드에 제공하여 어셈블리에 대한 동적 참조를 만들 수도 있습니다. 이 경우 애플리케이션 디렉터리만 어셈블리를 검색하고 다른 검사는 수행되지 않습니다. 어셈블리를 로드하는 다양한 메서드(예: Assembly.Load 또는 AppDomain.Load.)를 사용하여 부분 참조를 만듭니다.
마지막으로, 다음과 같은 Assembly.Load 메서드를 사용하여 동적 참조를 만들고 부분 정보만 제공할 수 있습니다. 그런 다음 애플리케이션 구성 파일에서 qualifyAssembly< 요소를 사용하여> 참조를 한정합니다. 이 요소를 사용하면 코드 대신 애플리케이션 구성 파일에서 전체 참조 정보(이름, 버전, 문화권 및 해당하는 경우 공개 키 토큰)를 제공할 수 있습니다. 애플리케이션 디렉터리 외부의 어셈블리에 대한 참조를 완전히 정규화하거나 전역 어셈블리 캐시에서 어셈블리를 참조하려고 하지만 코드 대신 구성 파일에서 전체 참조를 지정하는 편의를 원하는 경우 이 기술을 사용합니다.
비고
이 유형의 부분 참조는 여러 애플리케이션 간에 공유되는 어셈블리와 함께 사용하면 안 됩니다. 구성 설정은 어셈블리가 아닌 애플리케이션별로 적용되므로 이 유형의 부분 참조를 사용하는 공유 어셈블리를 사용하려면 공유 어셈블리를 사용하는 각 애플리케이션이 해당 구성 파일에 적격 정보를 포함해야 합니다.
런타임은 다음 단계를 사용하여 어셈블리 참조를 확인합니다.
애플리케이션 구성 파일, 게시자 정책 파일 및 컴퓨터 구성 파일을 포함하여 적용 가능한 구성 파일을 검사하여 올바른 어셈블리 버전을 결정합니다. 구성 파일이 원격 컴퓨터에 있는 경우 런타임은 애플리케이션 구성 파일을 먼저 찾아 다운로드해야 합니다.
어셈블리 이름이 이전에 바인딩되었는지 여부를 확인하고 , 바인딩된 경우 이전에 로드한 어셈블리를 사용합니다. 어셈블리를 로드하는 이전 요청이 실패한 경우 어셈블리를 로드하지 않고 요청이 즉시 실패합니다.
비고
어셈블리 바인딩 실패의 캐싱은 .NET Framework 버전 2.0의 새로운 기능입니다.
전역 어셈블리 캐시를 확인합니다. 어셈블리가 있는 경우 런타임은 이 어셈블리를 사용합니다.
다음 단계를 사용하여 어셈블리를 조사합니다.
구성 및 게시자 정책이 원래 참조에 영향을 미치지 않고 메서드를 사용하여 Assembly.LoadFrom 바인딩 요청을 만든 경우 런타임은 위치 힌트를 확인합니다.
구성 파일에 코드베이스가 있는 경우 런타임은 이 위치만 확인합니다. 이 프로브가 실패하면 런타임은 바인딩 요청이 실패하고 다른 검색이 발생하지 않음을 확인합니다.
검색 섹션에 설명된 추론을 사용하여 어셈블리를 검색합니다. 검색 후 어셈블리를 찾을 수 없는 경우 런타임은 Windows Installer에 어셈블리를 제공하도록 요청합니다. 이는 주문형 설치 기능으로 작동합니다.
비고
강력한 이름이 없는 어셈블리에 대한 버전 확인은 없으며, 강력한 이름이 없는 어셈블리에 대한 전역 어셈블리 캐시의 런타임 검사도 없습니다.
1단계: 구성 파일 검사
어셈블리 바인딩 동작은 세 개의 XML 파일에 따라 서로 다른 수준에서 구성할 수 있습니다.
애플리케이션 구성 파일입니다.
게시자 정책 파일입니다.
컴퓨터 구성 파일.
이러한 파일은 동일한 구문을 따르고 바인딩 리디렉션, 코드 위치 및 특정 어셈블리에 대한 바인딩 모드와 같은 정보를 제공합니다. 각 구성 파일에는 바인딩 프로세스를 리디렉션하는 assemblyBinding< 요소가 포함될> 수 있습니다. assemblyBinding< 요소의> 자식 요소에는 dependentAssembly< 요소가 포함>됩니다. dependentAssembly< 요소의> 자식에는 assemblyIdentity< 요소, bindingRedirect 요소 및 codeBase 요소가 포함>됩니다.<><>
비고
구성 정보는 세 가지 구성 파일에서 찾을 수 있습니다. 모든 요소가 모든 구성 파일에서 유효하지는 않습니다. 예를 들어 바인딩 모드 및 프라이빗 경로 정보는 애플리케이션 구성 파일에만 있을 수 있습니다. 각 파일에 포함된 정보의 전체 목록은 구성 파일을 사용하여 앱 구성을 참조하세요.
애플리케이션 구성 파일
먼저 공용 언어 런타임은 애플리케이션 구성 파일에서 호출 어셈블리의 매니페스트에 저장된 버전 정보를 재정의하는 정보를 확인합니다. 애플리케이션 구성 파일은 애플리케이션과 함께 배포할 수 있지만 애플리케이션 실행에는 필요하지 않습니다. 일반적으로 이 파일의 검색은 거의 즉각적이지만 웹 기반 시나리오와 같이 애플리케이션 기반이 원격 컴퓨터에 있는 경우 구성 파일을 다운로드해야 합니다.
클라이언트 실행 파일의 경우 애플리케이션 구성 파일은 애플리케이션의 실행 파일과 동일한 디렉터리에 있으며 .config 확장명을 가진 실행 파일과 동일한 기본 이름을 줍니다. 예를 들어 C:\Program Files\Myapp\Myapp.exe 구성 파일은 C:\Program Files\Myapp\Myapp.exe.config입니다. 브라우저 기반 시나리오에서 HTML 파일은 <링크> 요소를 사용하여 구성 파일을 명시적으로 가리켜야 합니다.
다음 코드는 애플리케이션 구성 파일의 간단한 예제를 제공합니다. 파일에 디버그 정보를 기록할 수 있도록 TextWriterTraceListener을/를 Listeners 컬렉션에 추가하는 예제입니다.
<configuration>
<system.diagnostics>
<trace useGlobalLock="false" autoflush="true" indentsize="0">
<listeners>
<add name="myListener" type="System.Diagnostics.TextWriterTraceListener, system version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" initializeData="c:\myListener.log" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
게시자 정책 파일
둘째, 런타임은 게시자 정책 파일(있는 경우)을 검사합니다. 게시자 정책 파일은 구성 요소 게시자가 공유 구성 요소에 대한 수정 또는 업데이트로 배포합니다. 이러한 파일에는 어셈블리 참조를 새 버전으로 안내하는 공유 구성 요소의 게시자가 발급한 호환성 정보가 포함되어 있습니다. 애플리케이션 및 컴퓨터 구성 파일과 달리 게시자 정책 파일은 전역 어셈블리 캐시에 설치해야 하는 자체 어셈블리에 포함됩니다.
다음은 게시자 정책 구성 파일의 예입니다.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="asm6" publicKeyToken="c0305c36380ba429" />
<bindingRedirect oldVersion="3.0.0.0" newVersion="2.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
어셈블리를 만들려면 다음과 같은 명령과 함께 Al.exe(어셈블리 링커) 도구를 사용할 수 있습니다.
Al.exe /link:asm6.exe.config /out:policy.3.0.asm6.dll /keyfile: compatkey.dat /v:3.0.0.0
compatkey.dat
는 강력한 이름 키 파일입니다. 이 명령은 전역 어셈블리 캐시에 배치할 수 있는 강력한 이름의 어셈블리를 만듭니다.
비고
게시자 정책은 공유 구성 요소를 사용하는 모든 애플리케이션에 영향을 줍니다.
게시자 정책 구성 파일은 애플리케이션(즉, 어셈블리 매니페스트 또는 애플리케이션 구성 파일에서)에서 가져온 버전 정보를 재정의합니다. 애플리케이션 구성 파일에 어셈블리 매니페스트에 지정된 버전을 리디렉션하는 문이 없는 경우 게시자 정책 파일은 어셈블리 매니페스트에 지정된 버전을 재정의합니다. 그러나 애플리케이션 구성 파일에 리디렉션 문이 있는 경우 게시자 정책은 매니페스트에 지정된 버전이 아닌 해당 버전을 재정의합니다.
게시자 정책 파일은 공유 구성 요소가 업데이트되고 해당 구성 요소를 사용하는 모든 애플리케이션에서 공유 구성 요소의 새 버전을 선택해야 할 때 사용됩니다. 애플리케이션 구성 파일이 안전 모드를 적용하지 않는 한 게시자 정책 파일의 설정은 애플리케이션 구성 파일의 설정을 재정의합니다.
안전 모드
게시자 정책 파일은 일반적으로 서비스 팩 또는 프로그램 업데이트의 일부로 명시적으로 설치됩니다. 업그레이드된 공유 구성 요소에 문제가 있는 경우 안전 모드를 사용하여 게시자 정책 파일의 재정의를 무시할 수 있습니다. 애플리케이션 구성 파일에만 있는 publisherPolicy apply="yes<|no"/> 요소에 의해 안전 모드가 결정됩니다. 게시자 정책 구성 정보를 바인딩 프로세스에서 제거할지 여부를 지정합니다.
전체 애플리케이션 또는 선택한 어셈블리에 대해 안전 모드를 설정할 수 있습니다. 즉, 애플리케이션을 구성하는 모든 어셈블리에 대한 정책을 끄거나 일부 어셈블리에 대해서는 켤 수 있지만 다른 어셈블리에는 사용하지 않도록 설정할 수 있습니다. 애플리케이션을 구성하는 어셈블리에 게시자 정책을 선택적으로 적용하려면 publisherPolicy apply=no/<를 설정하고>< 요소를 사용하여 > 영향을 받을 어셈블리를 지정합니다. 애플리케이션을 구성하는 모든 어셈블리에 게시자 정책을 적용하려면 종속 어셈블리 요소가 없는 publisherPolicy apply=no/<를 설정합니다>. 구성에 대한 자세한 내용은 구성 파일을 사용하여 앱 구성을 참조하세요.
컴퓨터 구성 파일
셋째, 런타임은 컴퓨터 구성 파일을 검사합니다. Machine.config이라고 하는 이 파일은 런타임이 설치된 루트 디렉터리의 Config 하위 디렉터리에 있는 로컬 컴퓨터에 있습니다. 이 파일은 관리자가 해당 컴퓨터에 로컬인 어셈블리 바인딩 제한을 지정하는 데 사용할 수 있습니다. 컴퓨터 구성 파일의 설정이 다른 모든 구성 설정보다 우선합니다. 그러나 모든 구성 설정을 이 파일에 배치해야 한다는 의미는 아닙니다. 관리자 정책 파일에 의해 결정된 버전은 최종 버전이며 재정의할 수 없습니다. Machine.config 파일에 지정된 재정의는 모든 애플리케이션에 영향을 줍니다. 구성 파일에 대한 자세한 내용은 구성 파일을 사용하여 앱 구성을 참조하세요.
2단계: 이전에 참조된 어셈블리 확인
이전 호출에서도 요청된 어셈블리가 요청된 경우 공용 언어 런타임은 이미 로드된 어셈블리를 사용합니다. 애플리케이션을 구성하는 어셈블리의 이름을 지정할 때 파급 효과가 있을 수 있습니다. 어셈블리 이름 지정에 대한 자세한 내용은 어셈블리 이름을 참조하세요.
어셈블리에 대한 이전 요청이 실패한 경우 어셈블리를 로드하지 않고 어셈블리에 대한 후속 요청이 즉시 실패합니다. .NET Framework 버전 2.0부터 어셈블리 바인딩 오류가 캐시되고 캐시된 정보를 사용하여 어셈블리 로드를 시도할지 여부를 결정합니다.
비고
바인딩 오류를 캐시하지 않은 .NET Framework 버전 1.0 및 1.1의 동작으로 되돌리려면 구성 파일에 disableCachingBindingFailures< 요소를 포함합니다>.
3단계: 전역 어셈블리 캐시 확인
강력한 이름의 어셈블리의 경우 바인딩 프로세스는 전역 어셈블리 캐시를 확인하여 계속됩니다. 전역 어셈블리 캐시는 컴퓨터의 여러 애플리케이션에서 사용할 수 있는 어셈블리를 저장합니다. 전역 어셈블리 캐시의 모든 어셈블리에는 강력한 이름이 있어야 합니다.
4단계: 코드베이스 또는 검색을 통해 어셈블리 찾기
호출하는 어셈블리 참조 및 구성 파일의 정보를 사용하여 올바른 어셈블리 버전을 확인한 후 전역 어셈블리 캐시(강력한 이름의 어셈블리에 대해서만)에서 확인한 후 공용 언어 런타임은 어셈블리를 찾으려고 시도합니다. 어셈블리를 찾는 프로세스에는 다음 단계가 포함됩니다.
<애플리케이션 구성 파일에서 codeBase> 요소를 찾은 경우 런타임은 지정된 위치를 확인합니다. 일치 항목이 발견되면 해당 어셈블리가 사용되고 검색이 발생하지 않습니다. 어셈블리를 찾을 수 없으면 바인딩 요청이 실패합니다.
그런 다음 런타임은 이 섹션의 뒷부분에 지정된 규칙을 사용하여 참조된 어셈블리를 검색합니다.
비고
디렉터리에 어셈블리의 여러 버전이 있고 특정 버전을 참조하려는 경우, <프로빙> 요소의 privatePath
특성 대신 <codeBase> 요소를 사용해야 합니다.
검색< 요소를 사용할> 경우, 런타임은 참조된 단순 어셈블리 이름과 일치하는 어셈블리를 찾으면 즉시 검색을 중지합니다. 이때 그 일치가 올바른지 여부는 고려되지 않습니다. 올바른 일치 항목이면 해당 어셈블리가 사용됩니다. 올바른 일치 항목이 아니면 검색이 중지되고 바인딩이 실패합니다.
코드베이스를 통해 어셈블리 찾기
코드베이스 정보는 구성 파일에서 <codeBase> 요소를 사용하여 제공할 수 있습니다. 이 코드베이스는 런타임이 참조된 어셈블리를 검색하기 전에 항상 확인됩니다. 최종 버전 리디렉션을 포함하는 게시자 정책 파일에 codeBase< 요소도 포함된> 경우 해당 <codeBase> 요소는 사용되는 요소입니다. 예를 들어 애플리케이션 구성 파일이 codeBase< 요소를 지정>하고 애플리케이션 정보를 재정의하는 게시자 정책 파일도 codeBase< 요소를 지정>하는 경우 게시자 정책 파일의 <codeBase> 요소가 사용됩니다.
codeBase< 요소에 지정된> 위치에서 일치하는 항목이 없으면 바인딩 요청이 실패하고 추가 단계가 수행되지 않습니다. 런타임에서 어셈블리가 호출 어셈블리의 조건과 일치한다고 판단되면 해당 어셈블리를 사용합니다. 지정된 <codeBase> 요소에 의해 지정된 파일이 로드되면 런타임은 이름, 버전, 문화권 및 공개 키가 호출 어셈블리의 참조와 일치하는지 확인합니다.
비고
애플리케이션의 루트 디렉터리 외부에서 참조되는 어셈블리에는 강력한 이름이 있어야 하며 전역 어셈블리 캐시에 설치하거나 codeBase< 요소를 사용하여> 지정해야 합니다.
탐색을 통해 어셈블리 찾기
애플리케이션 구성 파일에 codeBase< 요소가 없는> 경우 런타임은 네 가지 조건을 사용하여 어셈블리를 검색합니다.
애플리케이션을 실행하는 루트 위치인 애플리케이션 기반입니다.
문화, 참조된 어셈블리의 문화 특성입니다.
참조된 어셈블리의 이름입니다.
privatePath
루트 위치 아래의 하위 디렉터리에 대한 사용자 정의 목록인 <탐색> 요소의 특성입니다. 애플리케이션 구성 파일 및 애플리케이션 도메인에 대 한 속성을 사용 하 여 관리 코드에서 AppDomainSetup.PrivateBinPath 이 위치를 지정할 수 있습니다. 관리 코드에 지정된 경우 관리 코드privatePath
가 먼저 검색되고 그 다음에 애플리케이션 구성 파일에 지정된 경로가 표시됩니다.
애플리케이션 기반 및 문화권 디렉터리 검색
런타임은 항상 컴퓨터의 URL 또는 애플리케이션의 루트 디렉터리일 수 있는 애플리케이션의 기반에서 검색을 시작합니다. 참조된 어셈블리가 애플리케이션 기반에서 찾을 수 없고 문화권 정보가 제공되지 않는 경우 런타임은 어셈블리 이름을 가진 모든 하위 디렉터리를 검색합니다. 검색된 디렉터리는 다음과 같습니다.
[애플리케이션 기반] / [어셈블리 이름].dll
[애플리케이션 베이스] / [어셈블리 이름] / [어셈블리 이름].dll
참조된 어셈블리에 문화권 정보를 지정하면 다음 디렉터리만 검색됩니다.
[애플리케이션 기반] / [culture] / [어셈블리 이름].dll
[애플리케이션 기반] / [culture] / [어셈블리 이름] / [어셈블리 이름].dll
privatePath 특성을 사용하여 검색
참조된 어셈블리에 대해 명명된 문화권 하위 디렉터리와 하위 디렉터리 외에도, 런타임은 privatePath
요소의 < 속성을 사용하여 지정된 디렉터리를 검색합니다. 특성을 사용하여 privatePath
지정된 디렉터리가 애플리케이션 루트 디렉터리의 하위 디렉터리여야 합니다. 검색된 디렉터리는 문화권 정보가 참조된 어셈블리 요청에 포함되는지 여부에 따라 달라집니다.
런타임은 참조된 단순 어셈블리 이름과 일치하는 어셈블리를 처음 찾을 때 올바른 일치 여부와 관계없이 검색을 중지합니다. 올바른 일치 항목이면 해당 어셈블리가 사용됩니다. 올바른 일치 항목이 아니면 검색이 중지되고 바인딩이 실패합니다.
문화권이 포함된 경우 다음 디렉터리를 탐색합니다.
[애플리케이션 기반] / [binpath] / [culture] / [어셈블리 이름].dll
[응용 프로그램 기반] / [binpath] / [culture] / [어셈블리 이름] / [어셈블리 이름].dll
문화 정보가 포함되어 있지 않을 경우, 다음 디렉터리가 확인됩니다.
[애플리케이션 기반] / [binpath] / [어셈블리 이름].dll
[애플리케이션 기반] / [binpath] / [어셈블리 이름] / [어셈블리 이름].dll
탐색 예제
다음 정보가 제공됩니다.
참조된 어셈블리 이름: myAssembly
애플리케이션 루트 디렉터리:
http://www.code.microsoft.com
<구성 파일의 probing> 요소는 bin을 지정합니다.
문화권: de
런타임은 다음 URL을 검색합니다.
http://www.code.microsoft.com/de/myAssembly.dll
http://www.code.microsoft.com/de/myAssembly/myAssembly.dll
http://www.code.microsoft.com/bin/de/myAssembly.dll
http://www.code.microsoft.com/bin/de/myAssembly/myAssembly.dll
이름이 같은 여러 어셈블리
다음 예제에서는 이름이 같은 여러 어셈블리를 구성하는 방법을 보여 있습니다.
<dependentAssembly>
<assemblyIdentity name="Server" publicKeyToken="c0305c36380ba429" />
<codeBase version="1.0.0.0" href="v1/Server.dll" />
<codeBase version="2.0.0.0" href="v2/Server.dll" />
</dependentAssembly>
다른 위치 검색됨
어셈블리 위치는 현재 바인딩 컨텍스트를 사용하여 확인할 수도 있습니다. 이는 메서드를 사용할 때 Assembly.LoadFrom 와 COM interop 시나리오에서 가장 자주 발생합니다. 어셈블리가 메서드를 LoadFrom 사용하여 다른 어셈블리를 참조하는 경우 호출 어셈블리의 위치는 참조된 어셈블리를 찾을 위치에 대한 힌트로 간주됩니다. 일치 항목이 발견되면 해당 어셈블리가 로드됩니다. 일치하는 항목이 없으면 런타임은 검색 의미 체계를 계속 사용한 다음 Windows Installer를 쿼리하여 어셈블리를 제공합니다. 바인딩 요청과 일치하는 어셈블리가 제공되지 않으면 예외가 발생합니다. 이 예외는 관리 코드에서 발생하는데, 형식이 TypeLoadException 참조된 경우거나 로드 중인 어셈블리를 찾을 수 없을 때 FileNotFoundException입니다.
예를 들어, Assembly1이 Assembly2를 참조하고 Assembly1이 http://www.code.microsoft.com/utils
에서 다운로드된 경우, 해당 위치는 Assembly2.dll를 찾을 위치에 대한 힌트로 간주됩니다. 그런 다음 런타임은 http://www.code.microsoft.com/utils/Assembly2.dll
및 http://www.code.microsoft.com/utils/Assembly2/Assembly2.dll
에서 어셈블리를 탐색합니다. 이러한 위치 중 하나에서 Assembly2를 찾을 수 없는 경우 런타임은 Windows Installer를 쿼리합니다.
참고하십시오
.NET