Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
부모글 보이기/감추기
(연관된 글이 1개 있습니다.)
3.2 PDB 파일에 따른 Debug 정보 - .NET 2.0 Web Application Project + Library 유형의 프로젝트

C# 라이브러리 유형의 "BaseLibrary" 프로젝트는 이전 토픽에서 설명했던 프로젝트를 그대로 사용합니다. .NET 2.0 Web Application Model Project 유형은 VS.NET 2005에 기본 웹 사이트 프로젝트 모델이 아닌 새로 나온 유형의 프로젝트입니다.
이에 대해서는 다음의 토픽에서 설명해 놓았으므로 참조하시기 바랍니다.

https://www.sysnet.pe.kr/2/0/288

Web Application 프로젝트의 이름은 "WebApplication1"입니다. Default.aspx/Default.aspx.cs 파일을 포함하고 있으며 내용은 다음과 같습니다.

        private void Form1_Load(object sender, EventArgs e)
        {
            BaseLibrary.ThrowClass throwClass = new BaseLibrary.ThrowClass();
            throwClass.TestMethod();
        }

이번에도 역시 환경을 어떻게 구성하는지에 따라서 우리가 얼마나 유용한 오류 정보를 얻을 수 있는지 알아볼 텐데요. 실제 서비스를 하는 경우를 가정하고 예를 들어보겠습니다. 즉, 사용자가 웹 프로젝트를 돌아다니다가 보는 오류가 난 화면이 아닌 이벤트 뷰어에 남겨진 내용을 기준으로 살펴보겠습니다.

첫 번째로 BaseLibrary.pdb / WebApplication1.pdb 파일이 bin 폴더에 함께 있는 경우에 예외가 발생하면 다음과 같은 내용의 이벤트 로그가 남겨집니다. 그중에서 Stack Trace 부분만을 살펴보겠습니다.

Stack trace:    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.File.Open(String path, FileMode mode)
   at BaseLibrary.ThrowClass.TestMethod() in D:\temp2\PdbSample\BaseLibrary\ThrowClass.cs:line 14
   at WebApplication1._Default.Page_Load(Object sender, EventArgs e) in D:\temp2\PdbSample\AspNet\WebApplicationModel\WebApplication1\Default.aspx.cs:line 19
   at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
   at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

WinForm Application의 예를 보신 분들이라면 결과를 예측하실 수 있으셨을 텐데요. 그때와 마찬가지로, 해당 오류가 발생한 모듈과 관련해서 PDB 파일이 존재하면 구체적인 소스 파일과 라인 번호를 얻어낼 수 있습니다. 또한 릴리스 빌드에서도 "pdb-only" 유형의 PDB 파일을 생성하는 것도 동일합니다. 일단, 기본적인 사항들은 WinForm에서의 PDB 역할을 살펴보았던 것과 동일합니다.

그런데, ^^ 한 가지 더 고려할 것이 있지요. 바로, web.config에 있는 compilation[@debug] ="true" 또는 "false"는 어떤 영향을 미칠지에 대해서입니다.

아시는 것처럼, Web Application은 첫 번째로 프로젝트 빌드를 하면 Code Behind 파일의 코드 파일들이 컴파일 되어 /bin 폴더에 위치하게 됩니다. 이후에 사용자들이 실제로 aspx 페이지를 방문하게 되면서 웹 사이트의 /bin 파일들은 shadow-copy가 이뤄지게 됩니다. 이번 예제에서처럼 웹 응용 프로그램의 이름이 "WebApplication1"인 경우에는 다음과 같은 폴더에 shadow copy가 이루어집니다.

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\webapplication1

aspx는 /bin 폴더에 있는 DLL에 포함된 code behind 클래스들로부터 실행 시에 상속을 받아서 동적으로 컴파일 되어집니다. 바로 이때의 컴파일을 "debug" 모드로 할 것인지, "release" 모드로 할 것인지를 결정하는 것이 web.config의 compilation[@debug] 값입니다. 예제 WebApplication1 프로젝트를 빌드해서 네비게이션을 하게 되면, 다음과 같은 파일들이 ASP.NET 임시 폴더에 생성된 것을 확인할 수 있습니다.

App_Web_dquidpq_0.cs
App_Web_dquidpq_1.cs
App_Web_dquidpq_.dll ( release 빌드 시에는 dll만 생성됨 )
App_Web_dquidpq_.pdb

보시는 것처럼, compilation[@debug] ="true"인 경우에는, PDB 파일과 cs 소스 파일까지 생성된 것을 볼 수 있습니다. 하지만, 그 값을 "false"로 지정하게 되면, pdb 및 소스 파일은 생성되지 않고 DLL 파일만 생성되게 됩니다. debug 빌드 시에 cs 소스 파일을 유지하는 이유는 PDB 파일 내부에 소스 파일의 위치 정보까지 포함하고 있기 때문에 가용한 경우 cs 파일까지 있다면 더욱 확실한 디버그를 할 수 있습니다.

그럼, 이제 compilation[@debug] = "false" 값으로 놓고 default.aspx를 방문해 볼까요? 그럼, 이제 다음과 같은 이벤트 로그 오류 정보를 얻을 수 있습니다.

Stack trace:    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, 
      FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.File.Open(String path, FileMode mode)
   at BaseLibrary.ThrowClass.TestMethod() in D:\temp2\PdbSample\BaseLibrary\ThrowClass.cs:line 14
   at WebApplication1._Default.Page_Load(Object sender, EventArgs e) in D:\temp2\PdbSample\AspNet\WebApplicationModel\WebApplication1\Default.aspx.cs:line 19
   at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
   at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

보시는 것처럼, 달라진 것은 없습니다. 그렇습니다. default.aspx/cs 파일과 같은 응용 프로그램 구성이라면 굳이 compilation[@debug] 값을 "true"로 설정해 놓으실 필요는 없습니다. 그럼, 과연 이 옵션은 언제 필요할까요? ^^

asp.net의 코드는 code behind 파일에만 있는 것은 아니죠. 바로 aspx 파일 자체에 코드가 포함되어 있는 경우에는 compilation[@debug] 값을 "true"로 해놓는 것이 의미가 있어집니다.
차이를 확인하기 위해서, default.aspx의 html에 다음과 같이 코드를 추가해 보겠습니다.

----- default.aspx.cs -------
    public partial class _Default : System.Web.UI.Page
    {
        public BaseLibrary.ThrowClass throwClass = new BaseLibrary.ThrowClass();
    }

----- default.aspx -------
<head runat="server">
    <title>Untitled Page : <% throwClass.TestMethod(); %></title>
</head>

아래의 이벤트 로그는 compilation[@debug] = "true"인 경우입니다.

Stack trace:    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, 
        FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.File.Open(String path, FileMode mode)
   at BaseLibrary.ThrowClass.TestMethod() in D:\temp2\PdbSample\BaseLibrary\ThrowClass.cs:line 14
   at ASP.default_aspx.__Render__control3(HtmlTextWriter __w, Control parameterContainer) in d:\temp2\PdbSample\AspNet\WebApplicationModel\WebApplication1\Default.aspx:line 7
   at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
   at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
   at System.Web.UI.HtmlControls.HtmlTitle.Render(HtmlTextWriter writer)
   [이하 생략....]

아래의 이벤트 로그는 compilation[@debug] = "false"인 경우입니다.

Stack trace:    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, 
         FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.File.Open(String path, FileMode mode)
   at BaseLibrary.ThrowClass.TestMethod() in D:\temp2\PdbSample\BaseLibrary\ThrowClass.cs:line 14
   at ASP.default_aspx.__Render__control3(HtmlTextWriter __w, Control parameterContainer)
   at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
   at System.Web.UI.Control.RenderChildren(HtmlTextWriter writer)
   at System.Web.UI.HtmlControls.HtmlTitle.Render(HtmlTextWriter writer)
   [이하 생략....]

차이가 분명하지요. ^^ "true"인 경우에는 default.aspx 페이지의 어느 라인인지까지도 표시가 되어지는 반면, "false"인 경우에는 알 수 없습니다. (그런데, 어째서 여기서의 파일이 shadow-copy 임시 폴더에 있는 cs 파일이 아닌, 원래의 web site 폴더에 있는 aspx를 가리키고 있을까요? 이는 #line 지시자를 임시 폴더의 cs 파일에서 사용하고 있기 때문입니다. 이에 대해서는 나중에 기회되면 설명 드리겠습니다.)

그럼, 이것을 보고 어떻게 결론을 내리는 것이 좋을까요?

웹 애플리케이션인 경우에는 가능한 aspx 페이지에는 직접 코드를 사용하지 않는 것이 좋습니다. 만약, 사용해야 한다면 오류가 거의 발생하지 않을 코드에 대해서 해야 하거나, 부득이한 경우 처리 속도 저하를 감수하고 compilation[@debug] = "true"로 설정해서 배포를 해야 합니다. compilation[@debug] = "false"로 하는 경우라면, 위의 오류 스택에서 보는 것처럼, "ASP.className"과 같이 "ASP"로 시작한다면 aspx 페이지에서 오류가 났음을 이젠 알 수 있을 것입니다.

이러한 문제를 해결하기 위해 MS에 건의하고 싶은 것이 있다면 compilation 옵션에 "build" 속성과 "pdb" 속성을 분리해서 넣어 달라는 정도입니다. 즉, aspx에 코드를 사용하더라도 dll은 release로 빌드하지만 (C++의 경우와 비교해 보면, /Zi 옵션만으로 빌드) pdb 파일이 생성될 수 있도록 하는 조정을 할 수 있게 하면 좋겠지요. ^^ ([2006-08-10] 다시 읽어보니 ^^ 이 부분은 수정이 되어야 할 것 같습니다. "3.3 PDB 파일에 따른 Debug 정보 - .NET 2.0 Web Site Model Project"에 보면 제가 system.codedom에서 이것을 해결하는 방법을 제시했지요.)
[연관 글]






[최초 등록일: ]
[최종 수정일: 7/5/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




1  2  3  4  5  6  7  8  9  10  [11]  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13667정성태7/7/20246625닷넷: 2273. C# - 리눅스 환경에서의 Hyper-V Socket 연동 (AF_VSOCK)파일 다운로드1
13666정성태7/7/20247718Linux: 74. C++ - Vsock 예제 (Hyper-V Socket 연동)파일 다운로드1
13665정성태7/6/20247908Linux: 73. Linux 측의 socat을 이용한 Hyper-V 호스트와의 vsock 테스트파일 다운로드1
13663정성태7/5/20247505닷넷: 2272. C# - Hyper-V Socket 통신(AF_HYPERV, AF_VSOCK)의 VMID Wildcards 유형파일 다운로드1
13662정성태7/4/20247500닷넷: 2271. C# - WSL 2 VM의 VM ID를 알아내는 방법 - Host Compute System API파일 다운로드1
13661정성태7/3/20247429Linux: 72. g++ - 다른 버전의 GLIBC로 소스코드 빌드
13660정성태7/3/20247538오류 유형: 912. Visual C++ - Linux 프로젝트 빌드 오류
13659정성태7/1/20247876개발 환경 구성: 715. Windows - WSL 2 환경의 Docker Desktop 네트워크
13658정성태6/28/20248268개발 환경 구성: 714. WSL 2 인스턴스와 호스트 측의 Hyper-V에 운영 중인 VM과 네트워크 연결을 하는 방법 - 두 번째 이야기
13657정성태6/27/20247925닷넷: 2270. C# - Hyper-V Socket 통신(AF_HYPERV, AF_VSOCK)을 위한 EndPoint 사용자 정의
13656정성태6/27/20248117Windows: 264. WSL 2 VM의 swap 파일 위치
13655정성태6/24/20247875닷넷: 2269. C# - Win32 Resource 포맷 해석파일 다운로드1
13654정성태6/24/20247802오류 유형: 911. shutdown - The entered computer name is not valid or remote shutdown is not supported on the target computer.
13653정성태6/22/20247940닷넷: 2268. C# 코드에서 MAKEINTREOURCE 매크로 처리
13652정성태6/21/20249259닷넷: 2267. C# - Linux 환경에서 (Reflection 없이) DLL AssemblyFileVersion 구하는 방법파일 다운로드2
13651정성태6/19/20248501닷넷: 2266. C# - (Reflection 없이) DLL AssemblyFileVersion 구하는 방법파일 다운로드1
13650정성태6/18/20248429개발 환경 구성: 713. "WSL --debug-shell"로 살펴보는 WSL 2 VM의 리눅스 환경
13649정성태6/18/20247980오류 유형: 910. windbg - !py 확장 명령어 실행 시 "failed to find python interpreter" (2)
13648정성태6/17/20248308오류 유형: 909. C# - DynamicMethod 사용 시 System.TypeAccessException
13647정성태6/16/20249365개발 환경 구성: 712. Windows - WSL 2의 네트워크 통신 방법 - 세 번째 이야기 (같은 IP를 공유하는 WSL 2 인스턴스) [1]
13646정성태6/14/20247783오류 유형: 908. Process Explorer - "Error configuring dump resources: The system cannot find the file specified."
13645정성태6/13/20248210개발 환경 구성: 711. Visual Studio로 개발 시 기본 등록하는 dev tag 이미지로 Docker Desktop k8s에서 실행하는 방법
13644정성태6/12/20248882닷넷: 2265. C# - System.Text.Json의 기본적인 (한글 등에서의) escape 처리 [1]
13643정성태6/12/20248337오류 유형: 907. MySqlConnector 사용 시 System.IO.FileLoadException 오류
13642정성태6/11/20248221스크립트: 65. 파이썬 - asgi 버전(2, 3)에 따라 달라지는 uvicorn 호스팅
13641정성태6/11/20248688Linux: 71. Ubuntu 20.04를 22.04로 업데이트
1  2  3  4  5  6  7  8  9  10  [11]  12  13  14  15  ...