분명히 참조(Reference)에 추가했고, bin 폴더에 DLL 파일도 있는데 FileNotFoundException이나 TypeLoadException이 발생하는 경험 한 번쯤 있으시죠? 이 현상을 DLL 지옥(DLL Hell)이라 부릅니다.
특히, .NET Framework 환경에서는 참조된 어셈블리의 버전, 공개 키 토큰(Public Key Token), 위치(Probing Path) 등이 복잡하게 얽혀있어 원인 추적이 매우 까다롭습니다.
오늘은 바로 이 DLL 지옥의 한 줄기 빛, 어셈블리 바인딩 로그 뷰어(Assembly Binding Log Viewer, Fusion Log Viewer)를 사용하여 범인을 추적하는 과정을 상세히 알아보겠습니다.
Fuslogvw.exe(어셈블리 바인딩 로그 뷰어) - .NET Framework
어셈블리 바인딩 로그 뷰어인 Fuslogvw.exe사용합니다. 이 뷰어는 어셈블리 바인딩 세부 정보를 보여 줍니다. 이는 런타임에 .NET에서 어셈블리를 찾을 수 없는 이유를 진단하는 데 도움이 됩니다.
learn.microsoft.com
언제 사용하나요? (중요!)
이 도구는 .NET Framework (4.8 이하) 환경에서 발생하는 어셈블리 로딩 문제를 진단하기 위한 전통적인 방법입니다. Modern .NET (Core, 5, 6, 7, 8...) 환경에서는 다른 방식을 사용하며, 이 글의 마지막 부분에서 함께 다루겠습니다.
범인 추적 4단계: 실전 가이드
가상의 미디어 플레이어 PhoenixPlayer.exe가 특정 버전 Newtonsoft.Json.dll을 찾지 못해 실행되지 않는 상황을 가정해 봅시다.
1단계: 로깅 활성화 (함정 설치)
먼저 .NET 런타임에게 "지금부터 모든 어셈블리 바인딩 과정을 낱낱이 기록해줘"라고 명령해야 합니다.
Windows 시작 메뉴에서 Developer Command Prompt for VS 2022를 관리자 권한으로 실행한 후, 아래 명령어를 입력합니다.
reg add "HKLM\Software\Microsoft\Fusion" /v "ForceLog" /t "REG_DWORD" /d "1" /f
2단계: 문제 재현 (범인 유인)
이제 문제가 되는 앱(PhoenixPlayer.exe)을 실행하여 오류가 발생하는 상황을 단 한 번만 재현합니다. 런타임은 이 과정에서 발생하는 모든 어셈블리 탐색 과정을 로그로 남기게 됩니다.
3단계: 로그 뷰어 실행 (CCTV 확인)
다시 '개발자 명령 프롬프트' 창으로 돌아와 아래 명령어를 입력합니다.
fuslogvw
어셈블리 바인딩 로그 뷰어 창이 열리면, [새로 고침(Refresh)] 버튼을 누르세요. 방금 실패한 로그 기록이 목록에 나타날 것입니다.
4단계: 기록 분석
목록에서 Newtonsoft.Json이라는 이름이 포함된 '실패' 항목을 찾아 더블클릭합니다. HTML 형식의 상세 보고서가 웹 브라우저에 열리며, 이 안에 모든 단서가 담겨 있습니다.
[로그 예시]
*** Assembly Binder Log Entry (2/25/2026 @ 10:30:00 AM) ***
The operation failed.
Bind result: hr = 0x80131040. The located assembly's manifest definition does not match the assembly reference.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Projects\PhoenixPlayer\bin\Debug\PhoenixPlayer.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
(Fully-specified)
LOG: Appbase = file:///C:/Projects/PhoenixPlayer/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : PhoenixPlayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Projects\PhoenixPlayer\bin\Debug\PhoenixPlayer.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
LOG: Attempting download of new URL file:///C:/Projects/PhoenixPlayer/bin/Debug/Newtonsoft.Json.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Major Version
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
[로그 해석]
로그 내용 분석은, gemini에게 부탁했어요.
Calling Assembly: "어떤 프로그램을 찾는가?" 👉 PhoenixPlayer.exe
LOG: DisplayName: "찾고 있는 정보" 👉 Newtonsoft.Json, Version=12.0.0.0
LOG: Probing ...: "어디를 분석했는지?" 👉 C:\Projects\PhoenixPlayer\bin\Debug\ 폴더를 뒤졌음.
WRN & ERR: "실패 원인" 👉 Comparing the assembly name resulted in the mismatch: Major Version. 즉, 버전(Major Version)이 달라서 실패했다는 원인을 어셈블리 로그에서 찾을 수 있었습니다. (아마 bin 폴더에는 13.0.0.0 버전이 있었겠죠.)
잊지 마세요! 로깅 비활성화
문제 해결 후에는 반드시 아래 명령어로 로깅 기능을 꺼야 합니다. 켜진 상태로 두면 시스템 성능에 영향을 줄 수 있습니다.
reg delete "HKLM\Software\Microsoft\Fusion" /v "ForceLog" /f
Modern .NET (.NET Core, 5+) 에서는 어떻게 하나요?
.NET Core 이상부터는 fuslogvw.exe를 사용하지 않습니다. 대신, 환경 변수를 설정하여 훨씬 더 간편하게 추적할 수 있습니다.
| 특징 | 전통적 방법 (Fusion Log Viewer) | 현대적 방법 (.NET 5+) |
| 대상 플랫폼 | .NET Framework (≤ 4.8) | Modern .NET (Core, 5, 6, 7, 8...) |
| 작동 원리 | 레지스트리 Hook, GAC 탐색 로그 기록 | 런타임 호스트 자체 진단 출력 |
| 사용 도구 | fuslogvw.exe (GUI 도구) | 환경 변수, 콘솔 출력 |
| 핵심 설정 | reg add ... | set COREHOST_TRACE=1 |
| 현재 상태 | 레거시 유지보수용 | 표준 디버깅 절차 |
[Modern .NET 사용법]
1. 명령 프롬프트에서 환경 변수를 설정합니다: set COREHOST_TRACE=1
2. 같은 창에서 앱을 실행합니다: dotnet PhoenixPlayer.dll
3. 콘솔 창에 어셈블리 바인딩 과정이 텍스트로 자세히 출력됩니다.
결론 :
fuslogvw.exe는 오래된 도구지만, 여전히 .NET Framework 기반의 레거시 시스템에서 발생하는 DLL 지옥을 해결하는 데 매우 강력하고 확실한 도구입니다. 반면 Modern .NET에서는 훨씬 더 간편한 방식으로 진단이 가능하죠.
원인 모를 FileNotFoundException을 마주치게 된다면 한번 사용해 보시길 바랍니다.
'IT > Backend | All' 카테고리의 다른 글
| C#으로 게임을? MonoGame이 여전히 매력적인 이유 (feat. Stardew Valley) (0) | 2026.02.26 |
|---|---|
| 테스트 더블 |"가짜"라도 다 같은 가짜가 아니다. 5가지 테스트더블, 상황에 맞게 선택하기 (0) | 2026.02.25 |
| Apache Jmeter | 서버에서 jmeter 실행 (0) | 2025.11.24 |
| 🧪테스트주도개발(TDD) 하기 | Apache Jmeter를 이용한 부하테스트 (1) | 2025.11.19 |
| 비동기 처리의 핵심 | 스레드, 멀티스레드, 큐 (0) | 2025.11.14 |