Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)
(시리즈 글이 9개 있습니다.)
.NET Framework: 90. XmlSerializer 생성자의 실행 속도를 올리는 방법
; https://www.sysnet.pe.kr/2/0/511

.NET Framework: 92. XmlSerializer 생성자의 실행 속도를 올리는 방법 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/521

.NET Framework: 100. XML Serializer를 이용한 값 복사
; https://www.sysnet.pe.kr/2/0/577

.NET Framework: 122. XML Serializer를 이용한 값 복사: 성능은 어떨까!
; https://www.sysnet.pe.kr/2/0/653

.NET Framework: 648. Dictionary<TKey, TValue>를 deep copy하는 방법
; https://www.sysnet.pe.kr/2/0/11157

.NET Framework: 660. Shallow Copy와 Deep Copy
; https://www.sysnet.pe.kr/2/0/11220

.NET Framework: 1141. XmlSerializer와 Dictionary 타입
; https://www.sysnet.pe.kr/2/0/12942

.NET Framework: 2078. .NET Core/5+를 위한 SGen(Microsoft.XmlSerializer.Generator) 사용법
; https://www.sysnet.pe.kr/2/0/13196

.NET Framework: 2080. C# - Microsoft.XmlSerializer.Generator 처리 없이 XmlSerializer 생성자를 예외 없이 사용하고 싶다면?
; https://www.sysnet.pe.kr/2/0/13198





XmlSerializer 생성자의 실행 속도를 올리는 방법 - 두 번째 이야기


우선, 이 글을 읽으시기 전에 문맥의 이해를 돕기 위해 다음의 토픽을 먼저 읽어주십시오.

XmlSerializer 생성자의 실행 속도를 올리는 방법 
; https://www.sysnet.pe.kr/2/0/511

참고로, 오늘 이야기는 "MSBuild"와 함께 진행됩니다. 이 부분에서... 벌써 "아하... 어떤 내용인지 알겠다" 하실 분이 있을 것 같군요. ^^ 어쨌든, MSBuild에 대한 이해가 부족하신 분들은 다음의 토픽을 미리 읽어두시는 것도 좋겠습니다.

Inside MSBuild 
; https://learn.microsoft.com/en-us/archive/msdn-magazine/2006/june/msdn-magazine-june-2006




지난 토픽을 보신 분들은, sgen.exe로 생성된 "[파일명].XmlSerializers.dll"과 같은 형식을 어디선가 본 적이 있으실 것입니다. 어디였을까???

명확한 재현 예를 들어볼까요? ^^

우선, "Class Library" 형식의 프로젝트를 하나 만든 후 다음과 같은 정의를 포함하는 "Class1.cs" 파일을 추가합니다.

using System;
using System.Collections.Generic;
using System.Text;

namespace ClassLibrary1
{
  public class MyClass
  {
    public string Prop;
  }
}

다음, 위의 MyClass 타입을 반환하는 아래의 코드와 같은 웹 메서드를 구현한 웹 애플리케이션을 만듭니다.

[WebMethod]
public MyClass GetData()
{
  return new MyClass();
}

이제 간단한 독립실행형 응용 프로그램 프로젝트(Console 또는 WinForm)를 만들어서 위의 웹 서비스를 참조한 다음, "Debug" 모드가 아닌, "Release" 모드로 빌드를 합니다.

아래는 제가 테스트 한 "XmlSerializerTest" 프로젝트의 빌드 결과물이 있는 bin\release 폴더의 내용입니다.

XmlSerializerTest.exe
XmlSerializerTest.exe.config
XmlSerializerTest.pdb
XmlSerializerTest.vshost.exe
XmlSerializerTest.vshost.exe.config
XmlSerializerTest.XmlSerializers.dll

보시는 것처럼, "[파일명].XmlSerializers.dll"이 자동으로 생성된 것을 확인할 수 있습니다. 이 때문에, 웹 서비스를 참조한 프로젝트를 Release 모드로 빌드해서 배포하는 경우에는 "XmlSerializer" 내부에서 "System.IO.FileNotFoundException" 예외가 발생하지 않게 됩니다.

Visual Studio IDE에서는, 위의 Sgen.exe 결과물이 생성되지 않도록 하는 옵션도 제공해 줍니다. 아래와 같이 "Generate serialization assembly" 옵션을 "Off"로 주면 됩니다.

sgen_msbuild_task_use_1.png




특이한 점이 있다면, "[파일명].XmlSerializers.dll"의 자동 생성은 "웹 서비스 참조"에 한해서 발생할 뿐, 위의 예제에서 응용 프로그램이 "MyClass"가 정의된 DLL을 직접 참조해서 XmlSerializer를 이용하는 경우에는 자동 생성되지 않습니다. (이 이유에 대해서는 잠시 후에 답이 나옵니다.)

어쨌든, 이쯤 되면 답은 거의 나온 것이나 다름없습니다.
왜냐하면, VS.NET 2005 역시 MSBuild로 빌드를 하는 것이기 때문에 틀림없이 그 안에 sgen.exe가 동작되도록 하는 그 무엇인가 있을 것이기 때문입니다.

이를 위해, 자신의 빌드 옵션에서 불려지는 아래와 같은 "Microsoft.Common.targets" 파일들 중의 하나를 열어서 살펴보면 해답을 발견할 수 있습니다. (물론, 변경까지 하게 되면 모든 프로젝트의 빌드에 영향을 줄 수 있습니다.)

"C:\Windows\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets"
"C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets"
"C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Microsoft.Common.targets"
"C:\Windows\Microsoft.NET\Framework64\v3.5\Microsoft.Common.targets"

찾아낸 내용은 다음과 같습니다.

<SGen
    BuildAssemblyName="$(TargetFileName)"
    BuildAssemblyPath="$(IntermediateOutputPath)"
    References="@(ReferencePath)"
    ShouldGenerateSerializer="true"
    UseProxyTypes="true"
    KeyContainer="$(KeyContainerName)"
    KeyFile="$(KeyOriginatorFile)"
    DelaySign="$(DelaySign)"
    ToolPath="$(SGenToolPath)">

    <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly"/>
</SGen>

보시면, "UseProxyTypes" 옵션이 "true"로 되어 있는 것을 확인할 수 있는데요. 바로 이 옵션 떄문에 "웹 서비스 참조"에 대해서만 "[파일명].XmlSerializers.dll" 파일들이 생성되는 것입니다. 간단하게는, 이 옵션을 "false"로 바꿔주면 모든 참조 DLL 들에 대해서 "SerializationAssembly"를 얻을 수 있습니다.




하지만 개인적으로는, 위와 같은 방법을 선호하지는 않습니다. 왜냐하면, 팀 개발에서 모든 구성원에게 "Microsoft.Common.targets" 파일을 변경하라고 하는 것은 그다지 바람직하지 않기 때문입니다. 하긴, 이런 부분은 "빌드 서버"에만 적용하면 된다는 현실적인 이유로 인해 묵인될 수는 있습니다.

하지만, 또 다른 이유로, 쓸데없는 타입들에 대해서도 sgen 작업이 이뤄진다는 점을 들 수 있습니다. 사실, 설계가 잘된 솔루션 구조라면 특정 라이브러리 프로젝트에 모든 데이터 엔티티 클래스들이 구현되어져 있을 것이므로 해당 프로젝트에만 적용하는 것이 더 바람직하다고 봅니다.

그렇다면, 프로젝트 파일을 수정해야 할 텐데요. 이에 대해서는 다음의 토픽을 간단하게 살펴 보십시오.

Do you know: editing VS project files made easy
; https://learn.microsoft.com/en-us/archive/blogs/nagarajp/do-you-know-editing-vs-project-files-made-easy

그럼, 우리가 원하는 데로 해볼까요? ^^
저라면, 다음과 같이 추가를 하겠습니다. ^^

<Target Name="AfterBuild">
  <SGen
   BuildAssemblyName="$(TargetFileName)"
   BuildAssemblyPath="$(OutputPath)"
   References="@(ReferencePath)"
   ShouldGenerateSerializer="true"
   KeyContainer="$(KeyContainerName)" KeyFile="$(KeyOriginatorFile)"
   DelaySign="$(DelaySign)"
   UseProxyTypes="false"
   ToolPath="$(SGenToolPath)">
    <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly"/>
  </SGen>
</Target> 

이제 빌드를 해보면, 해당 DLL 에 대해서 "[파일명].XmlSerializers.dll"이 생성되는 것을 확인할 수 있습니다. 이 부분에서... "에이, 그 정도는 '빌드 후 이벤트' 기능으로도 얼마든지 구현이 가능한데!"라고 하시는 분이 계실지도 모르겠는데요. MSBuild의 장점은, 해당 DLL 프로젝트를 다른 프로젝트가 참조할 때 발생합니다. ^^

다른 프로젝트에 의해서 참조되는 경우, 해당 DLL만 복사되는 것이 아니라 자동적으로 "[파일명].XmlSerializers.dll"까지 복사되어 넘어갑니다. 우와~~~ ^^; (게다가 빌드 이벤트는 "TFS 팀 빌드" 시에는 효과가 없다는 점도 있지요.)

이제 배우셨으니, 여러분들의 클래스 라이브러리에 적용해 보십시오. 이전보다 "쪼끔 더" 빠른 초기 실행 속도를 경험하실 수 있습니다. (디버그 모드에서 실행시, System.IO.FileNotFoundException 예외가 발생하면서 동적 DLL들이 생성되는 경우가 있는지 확인해 보시면 됩니다. 하나도 발생하지 않도록 만드는 순간,,, 가벼운 희열을 느끼실 수 있습니다. ^^;)

마지막으로 아래는, 위의 내용과 비슷한 내용을 담고 있는 해외 블로거의 글입니다.

VS2005 - When SGEN Doesn't Work... 
; http://www.kiwidude.com/blog/2007/02/vs2005-when-sgen-doesnt-work.html





[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 12/15/2022]

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

비밀번호

댓글 작성자
 



2008-02-23 05시34분
Use of SGEN.exe to avoid common XmlSerializer performance pitfalls
; https://learn.microsoft.com/en-us/archive/blogs/billwert/use-of-sgen-exe-to-avoid-common-xmlserializer-performance-pitfalls

위의 기사를 읽어보고 한 가지 재미있는 사실을 알았습니다.
원래 XmlSerializer는 해당 타입에 대해서 런타임 시에 직렬화 코드를 만들어 낼 때, In-memory 상에서 코드를 생성해 내는데요. 이것을 %Temp% 파일에 생성하도록 바꿔주는 방법을 알려주고 있습니다. (직접 보세요. ^^)
kevin25
2008-06-18 09시47분
직렬화 코드를 담은 어셈블리를 특정 폴더로 지정하기 위한 방법을 아래의 토픽에서 설명하고 있습니다.

Serialization Temporary Assemblies
; https://learn.microsoft.com/en-us/archive/blogs/drnick/serialization-temporary-assemblies

system.xml.serialization/xmlserializer[@tempFilesLocation] 속성을 바꾸면 된다는.
kevin25
2009-11-04 10시54분
kevin25

1  2  3  4  5  6  7  8  9  10  [11]  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13372정성태6/15/20233361개발 환경 구성: 682. SQL Server TLS 통신을 위해 사용되는 키 길이 확인 방법
13371정성태6/15/20233472개발 환경 구성: 681. openssl - 인증서 버전(V1 / V3)
13370정성태6/14/20233615개발 환경 구성: 680. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 - TLS 1.2 지원
13369정성태6/13/20233425개발 환경 구성: 679. PyCharm(을 비롯해 JetBrains에 속한 여타) IDE에서 내부 Window들의 탭이 없어진 경우
13368정성태6/13/20233575개발 환경 구성: 678. openssl로 생성한 인증서를 SQL Server의 암호화 인증서로 설정하는 방법
13367정성태6/10/20233747오류 유형: 864. openssl로 만든 pfx 인증서를 Windows Server 2016 이하에서 등록 시 "The password you entered is incorrect" 오류 발생
13366정성태6/10/20233506.NET Framework: 2128. C# - 윈도우 시스템에서 지원하는 암호화 목록(Cipher Suites) 나열파일 다운로드1
13365정성태6/8/20233175오류 유형: 863. MODIFY FILE encountered operating system error 112(failed to retrieve text for this error. Reason: 15105)
13364정성태6/8/20234049.NET Framework: 2127. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 [1]
13363정성태6/7/20233611스크립트: 49. 파이썬 - "Transformers (신경망 언어모델 라이브러리) 강좌" - 1장 2절 코드 실행 결과
13362정성태6/1/20233578.NET Framework: 2126. C# - 서버 측의 요청 제어 (Microsoft.AspNetCore.RateLimiting)파일 다운로드1
13361정성태5/31/20233925오류 유형: 862. Facebook - ASP.NET/WebClient 사용 시 graph.facebook.com/me 호출에 대해 403 Forbidden 오류
13360정성태5/31/20233267오류 유형: 861. WSL/docker - failed to start shim: start failed: io.containerd.runc.v2: create new shim socket
13359정성태5/19/20233589오류 유형: 860. Docker Desktop - k8s 초기화 무한 반복한다면?
13358정성태5/17/20234056.NET Framework: 2125. C# - Semantic Kernel의 Semantic Memory 사용 예제 [1]파일 다운로드1
13357정성태5/16/20233883.NET Framework: 2124. C# - Semantic Kernel의 Planner 사용 예제파일 다운로드1
13356정성태5/15/20234208DDK: 10. Device Driver 테스트 설치 관련 오류 (Code 37, Code 31) 및 인증서 관련 정리
13355정성태5/12/20234127.NET Framework: 2123. C# - Semantic Kernel의 ChatGPT 대화 구현 [1]파일 다운로드1
13354정성태5/12/20234268.NET Framework: 2122. C# - "Use Unicode UTF-8 for worldwide language support" 설정을 한 경우, 한글 입력이 '\0' 문자로 처리
13352정성태5/12/20233961.NET Framework: 2121. C# - Semantic Kernel의 대화 문맥 유지파일 다운로드1
13351정성태5/11/20234428VS.NET IDE: 185. Visual Studio - 원격 Docker container 내에 실행 중인 응용 프로그램에 대한 디버깅 [1]
13350정성태5/11/20233725오류 유형: 859. Windows Date and Time - Unable to continue. You do not have permission to perform this task
13349정성태5/11/20234069.NET Framework: 2120. C# - Semantic Kernel의 Skill과 Function 사용 예제파일 다운로드1
13348정성태5/10/20233963.NET Framework: 2119. C# - Semantic Kernel의 "Basic Loading of the Kernel" 예제
13347정성태5/10/20234346.NET Framework: 2118. C# - Semantic Kernel의 Prompt chaining 예제파일 다운로드1
13346정성태5/10/20234192오류 유형: 858. RDP 원격 환경과 로컬 PC 간의 Ctrl+C, Ctrl+V 복사가 안 되는 문제
1  2  3  4  5  6  7  8  9  10  [11]  12  13  14  15  ...