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