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)
13609정성태4/27/202470닷넷: 2250. PInvoke 호출 시 참조 타입(class)을 마샬링하는 [IN], [OUT] 특성파일 다운로드1
13608정성태4/26/2024424닷넷: 2249. C# - 부모의 필드/프로퍼티에 대해 서로 다른 자식 클래스 간에 Reflection 접근이 동작할까요?파일 다운로드1
13607정성태4/25/2024423닷넷: 2248. C# - 인터페이스 타입의 다중 포인터를 인자로 갖는 C/C++ 함수 연동
13606정성태4/24/2024478닷넷: 2247. C# - tensorflow 연동 (MNIST 예제)파일 다운로드1
13605정성태4/23/2024714닷넷: 2246. C# - Python.NET을 이용한 파이썬 소스코드 연동파일 다운로드1
13604정성태4/22/2024756오류 유형: 901. Visual Studio - Unable to set the next statement. Set next statement cannot be used in '[Exception]' call stack frames.
13603정성태4/21/2024905닷넷: 2245. C# - IronPython을 이용한 파이썬 소스코드 연동파일 다운로드1
13602정성태4/20/2024945닷넷: 2244. C# - PCM 오디오 데이터를 연속(Streaming) 재생 (Windows Multimedia)파일 다운로드1
13601정성태4/19/2024972닷넷: 2243. C# - PCM 사운드 재생(NAudio)파일 다운로드1
13600정성태4/18/2024989닷넷: 2242. C# - 관리 스레드와 비관리 스레드
13599정성태4/17/2024938닷넷: 2241. C# - WAV 파일의 PCM 사운드 재생(Windows Multimedia)파일 다운로드1
13598정성태4/16/2024981닷넷: 2240. C# - WAV 파일 포맷 + LIST 헤더파일 다운로드2
13597정성태4/15/2024977닷넷: 2239. C# - WAV 파일의 PCM 데이터 생성 및 출력파일 다운로드1
13596정성태4/14/20241083닷넷: 2238. C# - WAV 기본 파일 포맷파일 다운로드1
13595정성태4/13/20241070닷넷: 2237. C# - Audio 장치 열기 (Windows Multimedia, NAudio)파일 다운로드1
13594정성태4/12/20241088닷넷: 2236. C# - Audio 장치 열람 (Windows Multimedia, NAudio)파일 다운로드1
13593정성태4/8/20241091닷넷: 2235. MSBuild - AccelerateBuildsInVisualStudio 옵션
13592정성태4/2/20241228C/C++: 165. CLion으로 만든 Rust Win32 DLL을 C#과 연동
13591정성태4/2/20241203닷넷: 2234. C# - WPF 응용 프로그램에 Blazor App 통합파일 다운로드1
13590정성태3/31/20241084Linux: 70. Python - uwsgi 응용 프로그램이 k8s 환경에서 OOM 발생하는 문제
13589정성태3/29/20241162닷넷: 2233. C# - 프로세스 CPU 사용량을 나타내는 성능 카운터와 Win32 API파일 다운로드1
13588정성태3/28/20241436닷넷: 2232. C# - Unity + 닷넷 App(WinForms/WPF) 간의 Named Pipe 통신 [2]파일 다운로드1
13587정성태3/27/20241362오류 유형: 900. Windows Update 오류 - 8024402C, 80070643
13586정성태3/27/20241542Windows: 263. Windows - 복구 파티션(Recovery Partition) 용량을 늘리는 방법
13585정성태3/26/20241500Windows: 262. PerformanceCounter의 InstanceName에 pid를 추가한 "Process V2"
[1]  2  3  4  5  6  7  8  9  10  11  12  13  14  15  ...