이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다.
저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나
토론을 할 수도 있습니다.
간만에 유틸리티 관련 포스트를 올리네요... 다 제 게으름 탓입니다. 아웅...
Fusion Log Viewer: Fuslogvw.exe
오늘 소개할 유틸리티는 Fusion Log Viewer(fuslogvw.exe) 라는 유틸리티인데, 이 유틸리티에 대한 글을 써야겠다고 마음먹은 지는 6개월 정도 되었을 거다. 필자의 게으름에 존경심이 우러나오지 않는가? -_-;
Fusion Log Viewer 유틸리티는 닷넷 런타임 로더가 어셈블리를 찾아서 로드 할 때 남기는 로그를 보여주는 유틸리티이다. 어셈블리 로드 시에 발생하는 TypeLoadException, FileNotFoundException 등의 문제를 해결하는데 대단히 유용한 유틸리티이다. 또한, 닷넷 런타임이 어느 디렉터리에서 어셈블리를 로드 하는가를 로그로서 보여주므로 스마트 클라이언트 시나리오에서 어셈블리가 어떤 URL에서 로드 되는지 확인할 때도 매우 유용한 도구라고 할 수 있겠다.
Fusion Log
Fusion 이 뭘까? Fusion 기술이란 어셈블리를 로드 하여 바인딩 하는 닷넷 런타임의 로더와 GAC (Global Assembly Cache)를 관리하는 기술의 통칭이다(fusion.dll에 구현되어 있다). 왜 이름이 이렇게 되어 있는지 필자도 정확하지 않지만, Unmanaged 코드에 의해 Managed 어셈블리가 로드 되기 때문에 이따위 이름을 붙여놓지 않았을까 추측하고 있다. 뭐 Fusion 이란 이름은 몰라도 전혀 상관 없으므로 무시해도 된다. 하지만 어셈블리가 로드 될 때, fusion.dll 이 수행하는 여러 작업에 대한 로그가 기록될 수 있고 이 로그를 문제해결의 단서로 사용할 수 있다는 것만 알아 두면 된다.
닷넷 런타임이 Assembly.Load 혹은 Assembly.LoadFrom 메쏘드 호출에 의해 직접적으로 어셈블리를 로드 하거나, 어셈블리 참조에 의해 간접적으로 어셈블리를 로드 할 때는 주어진 어셈블리의 이름, 버전, Culture, PublicKeyToken 정보를 이용하여 GAC을 검사한다든가, 어플리케이션 도메인의 베이스 디렉터리를 검사하는 행위를 수행한다. 이러한 행위에 대해 로그가 기록되므로 닷넷 런타임이 어디를 어떤 순서로 뒤지는지 정확히 알 수 있게 된다. 이를 통해 왜 그리고 어떤 이유로 어셈블리를 로드 하지 못하는가를 알아 낼 수 있는 것이다.
다음은 브라우저 임베디드 스마트 클라이언트 시나리오에서 발생한 Fusion Log 의 예제이다.
*** 어셈블리 바인더 로그 엔트리 (2006-05-04 @ 오후 4:08:01) ***
작업을 수행하지 못했습니다.
바인딩 결과: hr = 0x80070002. 지정된 파일을 찾을 수 없습니다.
다음 위치에서 어셈블리 관리자 로드: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll
다음 실행 파일에서 실행: C:\Program Files\Internet Explorer\iexplore.exe
--- 자세한 오류 로그가 아래에 표시됩니다.
=== 미리 바인딩된 상태 정보 ===
로그: 사용자 = WORKMAN\ksyu33
로그: DisplayName = Proxy, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
로그: Appbase = http://localhost.com/SmartClientBasic
로그: 초기 PrivatePath = bin
로그: 동적 베이스 = NULL
로그: 캐시 베이스 = NULL
로그: AppName = NULL
호출 어셈블리: ClientModule, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null.
===
로그: 이 바인딩은 default 로드 컨텍스트에서 시작됩니다.
로그: 응용 프로그램 구성 파일 C:\Documents and Settings\ksyu33\Local Settings\Temporary Internet Files\Content.IE5\8HIFIJK1\smartclient.dll[1].config을(를) 사용합니다.
로그: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\machine.config에서 컴퓨터 구성 파일을 사용합니다.
로그: 참조에 정책이 지금 적용되지 않습니다(전용, 사용자 지정, 부분, 위치 기반 어셈블리 바인딩).
로그: 새 URL http://localhost.com/SmartClientBasic/Proxy.DLL을(를) 다운로드합니다.
로그: 새 URL http://localhost.com/SmartClientBasic/Proxy/Proxy.DLL을(를) 다운로드합니다.
로그: 새 URL http://localhost.com/SmartClientBasic/bin/Proxy.DLL을(를) 다운로드합니다.
로그: 새 URL http://localhost.com/SmartClientBasic/bin/Proxy/Proxy.DLL을(를) 다운로드합니다.
로그: 새 URL http://localhost.com/SmartClientBasic/Proxy.EXE을(를) 다운로드합니다.
로그: 새 URL http://localhost.com/SmartClientBasic/Proxy/Proxy.EXE을(를) 다운로드합니다.
로그: 새 URL http://localhost.com/SmartClientBasic/bin/Proxy.EXE을(를) 다운로드합니다.
로그: 새 URL http://localhost.com/SmartClientBasic/bin/Proxy/Proxy.EXE을(를) 다운로드합니다.
로그: 모든 URL을 검색하려고 했지만 실패했습니다.
리스트1. Fusion Log 예제
리스트1의 로그 예는 바인딩이 실패했을 때 생성되는 로그를 보여준다. 기본적으로 바인딩 결과가 맨 위에 표시되며, 이 경우 지정된 파일을 찾을 수 없는 오류이다. 그리고 iexplore.exe 프로세스 상에서 발생한 오류임을 보여주고 있다. 브라우저 임베디드 스마트 클라이언트이므로 브라우저 프로세스인 iexplore.exe 프로세스가 표시되고 있는 것이다.
리스트1에서 "미리 바인딩된 상태 정보"는 닷넷 런타임이 바인딩 하기 전(pre binding)에 바인딩을 위해 수집한 정보들을 의미한다. 현재 사용자, 어셈블리 이름(버전, culture, publickeytoken 포함), 어플리케이션 베이스 디렉터리, PrivatePath 등등의 정보들이 여기에 속하며, 어떤 어셈블리에 의해 로드가 되는 지도 표시된다(호출 어셈블리 부분이다). 또한 어떤 configuration 파일이 사용되었는지도 표시됨에 주목하자.
그 후에 표시되는 정보는 로드 하고자 하는 어셈블리(이 경우 Proxy.dll 임)를 닷넷 런타임이 찾아가는 과정을 보여주고 있다. StrongName이 주어진 경우(publickeytoken이 null 이 아닌 경우임)에는 GAC를 먼저 뒤지지만 Proxy.dll 이 서명되어 있지 않았기 때문에(pre-binding 정보에 의해 알 수 있다), AppBase로 부터 차례로 다운로드를 시도하고 있음을 알 수 있다. 최종적으로 Proxy.DLL을 찾지 못해서 오류가 발생한 것이다.
Fuslogvw.exe
리스트1과 같은 로그를 보려면 어찌해야 하는가? 그 해답이 바로 Fusion Log Viewer 인 fuslogvw.exe 유틸리티인 것이다. 이 유틸리티는 .NET Framework SDK 내에 포함되어 있다. Visual Studio 역시 이 SDK 를 포함하므로 Visual Studio 만 설치되어 있다면 이 유틸티티를 사용할 수 있다. 위치는 <Visual Studio 설치 디렉터리>\SDK\bin 디렉터리에 존재한다. 살포시 수행시켜 보면 화면1과 같은 모습을 볼 수 있을 것이다.
화면1. Fusion Log Viewer 수행 화면 및 Settings 다이얼로그
Log Settings
기본적으로 로깅은 Disable 되어 있을 것이다. 따라서 로깅을 활성화 하기 위해 Settings 버튼을 통해 설정을 바꾼다. 이 역시 화면1에 나타나 있다. 먼저 Log disabled 는 기본 설정사항으로 로그를 남기지 않도록 하는 옵션이다. 그리고 Log in exception text 옵션은 어셈블리 바인딩 과정에서 예외(exception)가 발생하면 예외 메시지에 리스트1과 같은 로그를 추가하는 옵션이다. Log in exception text 옵션을 선택하고 어셈블리 바인딩 과정에서 TypeLoadException 혹은 FileNotFoundException 이 발생했다면, 예외 메시지의 끝 부분에 리스트1과 같은 로그가 추가된다는 말이다. 하지만 이 옵션을 선택하면 Fuslogvw.exe 유틸리티로는 로그를 볼 수 없음에 유의하자.
Log bind failures to disk 를 선택하면 바인딩 오류가 발생한 경우에만 디스크에 로그가 남는다. 이러한 설정 후, 발생되는 모든 어셈블리 바인딩 오류는 로그가 파일로서 기록되게 된다(기록되는 위치는 곧 설명할 것이다. 조급해 하지 말아라). 화면1에서 설정한 디렉터리에 가보면, 각 프로세스 별로 디렉터리가 생성되어 있고 이들 디렉터리 아래에는 로그 정보를 담은 HTML 파일들이 쭈욱 생성되어 있을 것이다. Log all binds to disk 를 선택하면 모든 바인딩에 대한 로그가 파일로서 기록된다. 닷넷 런타임 로더가 어떤 순서로 그리고 어떤 디렉터리들에서 어셈블리를 찾는가 확인하거나 공부하고 싶다면 이 옵션을 선택하는 것도 나쁘지 않다. 다만, 성능 상에 문제를 유발할 수 있으므로 서버에서 이 설정을 켜는 것은 권장하지 않는다. Fuslogvw.exe를 통해 로그를 볼 수 있는 옵션은 "Log bind failures to disk"와 "Log all binds to disk" 뿐이다.
로그는 기본적으로 IE의 캐시 폴더에 생성되는데, IE에 의해 캐시 폴더의 내용이 사라지는 경우가 발생하므로 "Enable custom log path" 체크 박스를 선택하고 로그 폴더를 설정하는 것이 정신건강에 좋다. 물론 가끔씩 로그 폴더를 지워주는 것도 잊지 말아야 한다.
Usage
설정은 다 설명했고.... 사용법에 대해 살펴보자. Fuslogvw.exe의 사용법은 매우 간단하다. 화면1에서 대부분의 UI는 설명이 불필요하지만, Log Location 그룹박스와 Log Category 그룹박스에 대해서만 추가 설명을 하도록 하겠다. Log Location은 보여줄 로그를 찾는 위치를 결정한다. 디폴트는 앞서 언급한 IE의 캐시 디렉터리에서 보여줄 로그를 찾는 것을 말하며, Custom은 Log Settings 대화상자에서 설정한 custom log path 에서 보여줄 로그 파일을 찾는다. Enable custom log path를 선택했다면 Log Location은 Custom 이 되어야만 로그를 볼 수 있다.
Log Categories 는 어셈블리 바인딩에서 기본 MSIL 을 담는 어셈블리에 대한 바인딩 로그와 미리 JIT 컴파일 된 Native 이미지 어셈블리에 대한 바인딩 로그를 볼 것인가를 결정한다. 닷넷 어셈블리는 런타임에 메쏘드 단위로 MSIL 코드를 JIT 컴파일하여 Navtive 코드를 생성한 후에 코드가 수행되도록 되어 있다. 닷넷을 하는 사람이라면 누구라도 다 아는 사실일 것이다. 이러한 JIT 컴파일을 미리 수행해 둘 수 있는데, 이러한 과정을 수행하는 도구가 바로 NGEN.exe 이다. 그래서 미리 JIT 컴파일 된 어셈블리를 NGEN 된 어셈블리라고 한다. 닷넷 런타임 로더는 어셈블리를 로드 할 때 NGEN 된 어셈블리 이미지가 존재하는지 먼저 찾는다. 만약 존재하지 않는 경우에, MSIL이 포함된 어셈블리를 찾게 된다. 이렇게 NGEN 된 어셈블리를 찾는 과정 역시 로그가 남게 되며, Log Categories 에서 Native Images를 선택하면 이 로그들을 볼 수 있는 것이다.
NGEN 에 대해서는 설명할 내용이 상당히 많으므로 여기서는 이만큼만 언급하고 넘어가도록 하겠다. 나중에 NGEN에 대한 포스트를 준비할 것을 약속하는 바이다. 뭐 이 사이트에 자주 오시는 분들은 아시겠지만... 약속은 지키지만 언제까지 지킨다는 것은 기약이 없다... 메~렁~
Registry Setting in .NET Framework 1.x
지금까지 설명한 Fuslogvw.exe 유틸리티는 닷넷 프레임워크 2.0을 기준으로 한 것이다. 이전 버전인 1.x 역시 fuslogvw.exe를 포함하고 있지만 화면1에서 보인 Log Settings 대화 상자는 존재하지 않는다. 대신 레지스트리를 통해 이러한 설정을 수행해야 한다. 레지스트리 키는 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion 이며 이 키에 값들을 추가/삭제 해야만 한다.
Log in exception text 옵션은 레지스트리 키에 EnableLog (DWORD) 값을 1로 설정해야 하며, Log bind failures to disk 옵션은 레지스트리 키에 LogFailures (DWORD) 값을 1로 설정해야 한다. Log all binds to disk 옵션은 ForceLog (DWORD) 값을 1로 설정해야 한다. 이들 레지스트리 값들은 셋 중 하나만이 표시되어야 하며, 세가지 모두 표시되지 않으면 Log disabled 옵션과 같다.
로그 파일의 경로를 설정하기 위해서는 레지스트리 키에 LogPath(REG_SZ) 값을 추가하고 경로를 설정하면 된다.
Epilog
Fiddler, Reflector 와 더불어 필자가 애용하는 유틸리티들 중 하나로서 Fuslogvw.exe 를 소개했다. 특히, 스마트 클라이언트 시나리오에서 어셈블리가 어떻게 다운로드 되고, 닷넷 런타임 로더가 어떤 디렉터리에서 어셈블리를 찾는가를 추적하는데 대단히 유용한 유틸리티이므로 반드시, 꼭, 정말로, 진짜로, 필수적으로 사용해 보기를 권하는 바이다.
Comments (read-only)
#※참고로.....Reflector와 유사한..고로 ..함께 사용하면 유용한 유틸을 소개합니다. / king / 5/12/2006 11:58:00 AM
#re: Fuslogvw.exe : 어셈블리 바인딩 정보 뷰어 / 즈믄 / 5/21/2006 5:54:00 PM
역시나 강좌 잘 보고 갑니다.. 얼마전에 우연찮게 한번 사용해 본적이 있습니다...
해결치 못한 오류로 헤딩하고 있을때죠..ㅋㅋㅋ
그 해결치 못한 오류는 저의 정리되지 않은 짧은 지식에서 비롯된거라....(해결하고 나니.. 늘 그러듯이.. 목잡고 쓰러질 만한 예상치 못한... 기본적인 것을~~~ ㅠ..ㅠ)
그런데. 그때는 님 강좌에서 소개하신 것처럼 자세한 내용을 알지 못한 상태에서 사용해서 그런지.. stand alone에서는 잘 나오던데.. 그냥.. aspx에서는 나오지 않더군요..
테스트 환경은 framework v1.1이라 위의 설정에 대한건 제가 registry를 수정하면서 다시 한번 해봐야 겠습니다.
그리고 NGEN에 대한 POST도 기대 하겠습니다.ㅋㅋㅋ (부담 100배....우헹헹헹 ^_________^V)
#re: Fuslogvw.exe : 어셈블리 바인딩 정보 뷰어 / wishy / 5/24/2006 9:30:00 AM
잘 읽었습니다..^^