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)
13368정성태6/13/20233543개발 환경 구성: 678. openssl로 생성한 인증서를 SQL Server의 암호화 인증서로 설정하는 방법
13367정성태6/10/20233697오류 유형: 864. openssl로 만든 pfx 인증서를 Windows Server 2016 이하에서 등록 시 "The password you entered is incorrect" 오류 발생
13366정성태6/10/20233457.NET Framework: 2128. C# - 윈도우 시스템에서 지원하는 암호화 목록(Cipher Suites) 나열파일 다운로드1
13365정성태6/8/20233168오류 유형: 863. MODIFY FILE encountered operating system error 112(failed to retrieve text for this error. Reason: 15105)
13364정성태6/8/20233999.NET Framework: 2127. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 [1]
13363정성태6/7/20233581스크립트: 49. 파이썬 - "Transformers (신경망 언어모델 라이브러리) 강좌" - 1장 2절 코드 실행 결과
13362정성태6/1/20233550.NET Framework: 2126. C# - 서버 측의 요청 제어 (Microsoft.AspNetCore.RateLimiting)파일 다운로드1
13361정성태5/31/20233903오류 유형: 862. Facebook - ASP.NET/WebClient 사용 시 graph.facebook.com/me 호출에 대해 403 Forbidden 오류
13360정성태5/31/20233264오류 유형: 861. WSL/docker - failed to start shim: start failed: io.containerd.runc.v2: create new shim socket
13359정성태5/19/20233570오류 유형: 860. Docker Desktop - k8s 초기화 무한 반복한다면?
13358정성태5/17/20233992.NET Framework: 2125. C# - Semantic Kernel의 Semantic Memory 사용 예제 [1]파일 다운로드1
13357정성태5/16/20233827.NET Framework: 2124. C# - Semantic Kernel의 Planner 사용 예제파일 다운로드1
13356정성태5/15/20234154DDK: 10. Device Driver 테스트 설치 관련 오류 (Code 37, Code 31) 및 인증서 관련 정리
13355정성태5/12/20234090.NET Framework: 2123. C# - Semantic Kernel의 ChatGPT 대화 구현 [1]파일 다운로드1
13354정성태5/12/20234250.NET Framework: 2122. C# - "Use Unicode UTF-8 for worldwide language support" 설정을 한 경우, 한글 입력이 '\0' 문자로 처리
13352정성태5/12/20233902.NET Framework: 2121. C# - Semantic Kernel의 대화 문맥 유지파일 다운로드1
13351정성태5/11/20234399VS.NET IDE: 185. Visual Studio - 원격 Docker container 내에 실행 중인 응용 프로그램에 대한 디버깅 [1]
13350정성태5/11/20233670오류 유형: 859. Windows Date and Time - Unable to continue. You do not have permission to perform this task
13349정성태5/11/20234004.NET Framework: 2120. C# - Semantic Kernel의 Skill과 Function 사용 예제파일 다운로드1
13348정성태5/10/20233904.NET Framework: 2119. C# - Semantic Kernel의 "Basic Loading of the Kernel" 예제
13347정성태5/10/20234316.NET Framework: 2118. C# - Semantic Kernel의 Prompt chaining 예제파일 다운로드1
13346정성태5/10/20234146오류 유형: 858. RDP 원격 환경과 로컬 PC 간의 Ctrl+C, Ctrl+V 복사가 안 되는 문제
13345정성태5/9/20235576.NET Framework: 2117. C# - (OpenAI 기반의) Microsoft Semantic Kernel을 이용한 자연어 처리 [1]파일 다운로드1
13344정성태5/9/20236681.NET Framework: 2116. C# - OpenAI API 사용 - 지원 모델 목록 [1]파일 다운로드1
13343정성태5/9/20234615디버깅 기술: 192. Windbg - Hyper-V VM으로 이더넷 원격 디버깅 연결하는 방법
13342정성태5/8/20234456.NET Framework: 2115. System.Text.Json의 역직렬화 시 필드/속성 주의
1  2  3  4  5  6  7  8  9  10  [11]  12  13  14  15  ...