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

... 136  137  138  139  140  141  142  143  [144]  145  146  147  148  149  150  ...
NoWriterDateCnt.TitleFile(s)
1454정성태5/31/201326282Java: 15. Java 7 Control Panel 실행시키는 방법
1453정성태5/22/201325329기타: 32. Microsoft FTP 사이트에 접속하는 방법
1452정성태5/21/201333037Windows: 73. TabProcGrowth 값 삭제 후 IE를 실행시키면 다시 복원되는 경우 [3]
1451정성태5/17/201331960Windows: 72. 윈도우 서버 2012 기초 사용법
1450정성태5/16/201322733오류 유형: 176. SQL10007N Message "0" could not be retrieved. Reason code: "3"
1449정성태5/15/201329842오류 유형: 175. SpeechRecognitionEngine 사용 시 오류 유형 2가지
1448정성태5/14/201324835VC++: 68. #pragma warning(disable: ...)로 오류 제어가 안된다면?
1447정성태5/3/201326519개발 환경 구성: 191. Debugging Tools for Windows 독립 설치 버전 [1]
1446정성태4/30/201327318.NET Framework: 368. Encoding 타입의 대체(fallback) 메카니즘 [1]
1445정성태4/26/201325536디버깅 기술: 54. NT 서비스의 Main 메서드 안에서 Process.GetProcessesByName 호출 시 멈춤 현상 [1]
1444정성태4/26/201329545기타: 31. Internet Explorer: 자바스크립트로 숨겨진 파일 다운로드 경로를 알아내는 방법 [1]
1443정성태4/24/201325226개발 환경 구성: 190. Azure PaaS 웹 응용 프로그램 배포 후 SMTP 서버 구성 [2]
1442정성태4/21/201328795기타: 30. 마이크로소프트 워드의 CPU 점유 현상으로 글자 입력이 느려졌다면? [1]
1441정성태4/21/201335401.NET Framework: 367. LargeAddressAware 옵션이 적용된 닷넷 32비트 프로세스의 가용 메모리 [14]
1440정성태4/19/201324129오류 유형: 174. dumpbin.exe 실행시 mspdb110.dll 로드 오류
1439정성태4/18/201327983VS.NET IDE: 76. Visual Studio 2012와 Itanium 빌드 옵션 [2]
1438정성태4/17/201327398.NET Framework: 366. 다른 프로세스에 환경 변수 설정하는 방법 - 두 번째 이야기 [1]파일 다운로드1
1437정성태4/17/201327620VC++: 67. CRT(C Runtime DLL: msvcr...dll)에 대한 의존성 제거
1436정성태4/17/201333003.NET Framework: 365. Local SYSTEM 권한으로 코드를 실행하는 방법파일 다운로드1
1435정성태4/15/201341889Windows: 71. ad-hoc 보다 더 편리한 "가상 Wifi" 를 이용한 인터넷 공유 [2]
1434정성태4/9/201323178오류 유형: 173. TFS 서버의 이벤트 로그 오류 - WebHost failed to process a request. Parameter name: certificate
1433정성태4/9/201323473개발 환경 구성: 189. TFS에 설치된 SharePoint 의 PowerShell 콘솔 띄우는 방법
1432정성태4/5/201324485오류 유형: 172. System.Web.PipelineModuleStepContainer.GetEventCount 에서 NullReferenceException 이 발생한다면?
1431정성태4/5/201325118기타: 29. 부팅 가능한 (외장) HDD를 기존 부팅 메뉴에 추가하는 방법
1430정성태4/4/201326991제니퍼 .NET: 23. 모바일용 웹 사이트에서 발생하는 응답 시간 지연 현상 [5]파일 다운로드1
1429정성태3/29/201323355개발 환경 구성: 188. SCOM 2012 - ASP.NET 모니터링 방법
... 136  137  138  139  140  141  142  143  [144]  145  146  147  148  149  150  ...