<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Performance | The .NET Blog</title><link>https://thedotnetblog.com/ko/tags/performance/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>ko</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Tue, 26 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/ko/tags/performance/index.xml" rel="self" type="application/rss+xml"/><item><title>.NET 11이 드디어 프로세스 API를 수정합니다</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/dotnet-11-process-api-improvements-runandcapturetext/</link><pubDate>Tue, 26 May 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/dotnet-11-process-api-improvements-runandcapturetext/</guid><description>System.Diagnostics.Process가 수년 만에 가장 큰 업데이트를 받습니다. RunAndCaptureTextAsync, KillOnParentExit, SafeProcessHandle API, 표준 핸들 리다이렉션에 대한 완전한 제어 — 더 이상 데드락 보일러플레이트 코드는 없습니다.</description><content:encoded>&lt;p&gt;프로세스를 시작하고 출력을 캡처해야 했던 모든 .NET 개발자는 동일한 위험한 보일러플레이트 코드의 변형을 작성해 왔습니다: stdout의 비동기 읽기, stderr의 비동기 읽기, &lt;code&gt;WaitForExitAsync&lt;/code&gt;, 두 스트림을 모두 비우는 것을 잊으면 데드락이 발생합니다. 이것은 수년간 존재해 온 잘 알려진 함정입니다.&lt;/p&gt;
&lt;p&gt;.NET 11이 마침내 이것을 제대로 수정합니다.&lt;/p&gt;
&lt;h2 id="runandcapturetextasync"&gt;RunAndCaptureTextAsync&lt;/h2&gt;
&lt;p&gt;핵심 추가 사항: 프로세스를 시작하고, stdout과 stderr를 캡처하고, 데드락 없이 종료를 기다리는 단일 정적 메서드.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAndCaptureTextAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dotnet&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;--version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StandardOutput&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;한 번의 호출. 수동 스트림 드레인 없음. 신중하게 배치된 &lt;code&gt;WaitForExit&lt;/code&gt; 없음. 단순히 무언가를 실행하고 출력을 얻어야 한다면, 이것이 원하는 API입니다.&lt;/p&gt;
&lt;p&gt;출력을 캡처하지 않고 종료를 기다리는 경우를 위한 &lt;code&gt;Process.RunAsync&lt;/code&gt;도 있습니다.&lt;/p&gt;
&lt;h2 id="killonparentexit"&gt;KillOnParentExit&lt;/h2&gt;
&lt;p&gt;시작된 프로세스의 일반적인 문제: 부모 프로세스가 충돌하거나 종료되면, 자식 프로세스는 고아로 계속 실행됩니다. &lt;code&gt;KillOnParentExit&lt;/code&gt;를 사용하면 프로세스 시작 시 부모 프로세스가 종료될 때 자식 프로세스도 종료되어야 한다고 선언할 수 있습니다.&lt;/p&gt;
&lt;p&gt;이것은 플랫폼별 방식(Windows의 job objects, Linux의 prctl)으로 존재했던 기능이지만 .NET에서 사용하려면 p/invoke나 서드파티 라이브러리가 필요했습니다. 이제 &lt;code&gt;ProcessStartInfo&lt;/code&gt;의 일급 프로퍼티가 되었습니다.&lt;/p&gt;
&lt;h2 id="safeprocesshandle-기반-api"&gt;SafeProcessHandle 기반 API&lt;/h2&gt;
&lt;p&gt;새로운 경량 API 표면은 전체 &lt;code&gt;Process&lt;/code&gt; 클래스가 아닌 &lt;code&gt;SafeProcessHandle&lt;/code&gt;을 중심으로 구축되었습니다. 전체 &lt;code&gt;Process&lt;/code&gt; 클래스는 많은 상태를 가지고 있어 트리밍하기 어렵습니다 — &lt;code&gt;SafeProcessHandle&lt;/code&gt; 경로는 출력 크기를 최소화해야 하는 애플리케이션(WASM, 네이티브 AOT)에 더 트리머 친화적입니다.&lt;/p&gt;
&lt;h2 id="핸들-상속에-대한-완전한-제어"&gt;핸들 상속에 대한 완전한 제어&lt;/h2&gt;
&lt;p&gt;업데이트는 또한 자식 프로세스가 상속하는 핸들과 표준 핸들이 리다이렉트되는 방식에 대한 세밀한 제어를 추가합니다. 이전에는 stdin/stdout/stderr를 리다이렉트할 수 있었지만 OS 수준에서 정확히 어떤 핸들을 상속할지 지정할 수 없었습니다. 새로운 API는 그 제어를 노출합니다.&lt;/p&gt;
&lt;h2 id="왜-중요한가"&gt;왜 중요한가&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Process&lt;/code&gt; 클래스는 툴링, 빌드 시스템, 테스트 러너, 그리고 다른 실행 파일을 호출하는 모든 애플리케이션에서 사용됩니다. 이전 API 표면은 .NET Framework 시절의 것으로 노후화되어 있었습니다. 이것은 호환성을 깨는 변경이 아닙니다 — 이전 API는 계속 작동합니다 — 하지만 새 코드는 새 표면을 선호해야 합니다.&lt;/p&gt;
&lt;p&gt;트리밍된 애플리케이션이나 AOT 컴파일 시나리오에서는 &lt;code&gt;SafeProcessHandle&lt;/code&gt; 경로가 특히 환영받습니다. 이전 &lt;code&gt;Process&lt;/code&gt; 클래스는 트리밍을 복잡하게 만드는 리플렉션 heavy 코드를 많이 가져왔습니다.&lt;/p&gt;
&lt;p&gt;원본 게시물: &lt;a href="https://devblogs.microsoft.com/dotnet/process-api-improvements-in-dotnet-11/"&gt;Process API Improvements in .NET 11&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>Copilot Studio가 .NET 10 WebAssembly로 마이그레이션하여 20% 빨라진 방법</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/copilot-studio-net10-webassembly-migration-performance/</link><pubDate>Sat, 23 May 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/copilot-studio-net10-webassembly-migration-performance/</guid><description>.NET 10 WASM 개선 사항은 새 프로젝트만을 위한 것이 아닙니다. .NET 8에서 업그레이드한 후 Copilot Studio가 측정한 것: 자동 지문 인식, 기본값 WasmStripILAfterAOT, 실제 실행 성능 수치.</description><content:encoded>&lt;p&gt;Copilot Studio 팀은 모든 Blazor WASM 개발자들이 궁금해했던 것을 실행했습니다: 프로덕션 애플리케이션을 .NET 8에서 .NET 10으로 실제로 업그레이드하고 결과를 측정했습니다. 게시물은 구체적인 수치를 공유하는데, 이는 드물고 진정으로 유용합니다.&lt;/p&gt;
&lt;h2 id="업그레이드는-지루했습니다-이것은-좋은-일입니다"&gt;업그레이드는 지루했습니다 (이것은 좋은 일입니다)&lt;/h2&gt;
&lt;p&gt;타겟 프레임워크 업데이트, 패키지 참조 새로 고침, 주요 변경 사항 수정. 그게 전부입니다. .NET 10 빌드가 이제 프로덕션에서 실행되고 있습니다. 마이그레이션 자체는 흥미로운 부분이 아니었습니다—.NET 10의 변경 사항이 그렇습니다.&lt;/p&gt;
&lt;h2 id="자동-에셋-지문-인식"&gt;자동 에셋 지문 인식&lt;/h2&gt;
&lt;p&gt;이전에는 WASM 앱을 배포하려면 캐시 무효화를 위해 SHA256 해시로 게시된 에셋의 이름을 바꾸는 사용자 정의 스크립트를 작성해야 했습니다. Copilot Studio에는 정확히 이를 수행하는 PowerShell 스크립트가 있었습니다—파일 이름 바꾸기, JavaScript 로더에 &lt;code&gt;integrity&lt;/code&gt; 속성 주입, 모든 것을 수동으로 관리.&lt;/p&gt;
&lt;p&gt;.NET 10에서는 이 모든 것이 내장되어 있습니다. 게시된 에셋은 자동으로 지문 인식되고, &lt;code&gt;dotnet.js&lt;/code&gt;에서 직접 가져오며, 수동 개입 없이 무결성 검증됩니다. 팀은 이름 바꾸기 스크립트를 삭제했습니다.&lt;/p&gt;
&lt;p&gt;범위의 작은 변경, 복잡성의 상당한 감소.&lt;/p&gt;
&lt;h2 id="wasmstripilafteraot가-이제-기본적으로-활성화"&gt;WasmStripILAfterAOT가 이제 기본적으로 활성화&lt;/h2&gt;
&lt;p&gt;.NET 8에서는 AOT 컴파일된 어셈블리에서 IL을 제거하는 것이 옵트인이었습니다. .NET 10에서는 기본값입니다. AOT 컴파일 후 원본 IL 바이트코드가 출력에서 제거됩니다—런타임에 필요하지 않으며, 이를 유지하면 이유 없이 패키지 크기가 커졌습니다.&lt;/p&gt;
&lt;p&gt;Copilot Studio는 특정 최적화를 사용합니다: JIT 엔진(빠른 시작)과 AOT 엔진(최대 안정 상태 성능) 둘 다 배포하고, 둘 다 병렬로 로드하여 준비되면 JIT에서 AOT로 핸드오프합니다. 두 엔진 간에 동일한 파일도 중복 제거합니다.&lt;/p&gt;
&lt;p&gt;새로운 IL 제거 동작은 AOT 어셈블리가 더 이상 JIT 대응물과 비트 단위로 일치하지 않음을 의미하므로 더 적은 파일이 중복 제거됩니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.NET 8: 59개의 공유 파일&lt;/li&gt;
&lt;li&gt;.NET 10: 22개의 공유 파일&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;결과: AOT 엔진의 패키지 크기가 약 15% 더 커집니다. AOT 다운로드는 빠른 LAN에서 ~6% 느리고, 4G에서 ~17% 느립니다. 하지만 이 모든 것은 앱이 이미 인터랙티브해진 후 백그라운드에서 발생합니다.&lt;/p&gt;
&lt;h2 id="성능-수치"&gt;성능 수치&lt;/h2&gt;
&lt;p&gt;이것이 중요한 부분입니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;첫 번째 호출 시 &lt;strong&gt;~20% 더 빠름&lt;/strong&gt; (콜드 패스)&lt;/li&gt;
&lt;li&gt;후속 호출 시 &lt;strong&gt;~5% 더 빠름&lt;/strong&gt; (웜 패스)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;개선 사항은 &amp;ldquo;큰 봇&amp;quot;에서 가장 눈에 띕니다—AOT 컴파일된 코드가 지배하는 크고 복잡한 에이전트. 더 단순한 워크플로우에서는 이득이 더 작습니다.&lt;/p&gt;
&lt;h2 id="아직-net-8을-사용-중이라면"&gt;아직 .NET 8을 사용 중이라면&lt;/h2&gt;
&lt;p&gt;마이그레이션 이야기는 진정으로 간단합니다: &lt;code&gt;&amp;lt;TargetFramework&amp;gt;&lt;/code&gt;를 업데이트하고, 패키지 참조를 업데이트하고, 사용자 정의 지문 인식 스크립트를 제거하면, 자동으로 &lt;code&gt;WasmStripILAfterAOT&lt;/code&gt;의 혜택을 받게 됩니다. AOT를 컴파일하는 경우 유사한 성능 향상을 기대하세요.&lt;/p&gt;
&lt;p&gt;게시물의 참고 사항: &lt;code&gt;WebWorker&lt;/code&gt; 내에서 .NET WASM 런타임을 로드하는 경우 초기화 시 &lt;code&gt;dotnetSidecar = true&lt;/code&gt;를 설정하세요.&lt;/p&gt;
&lt;p&gt;원본 게시물: &lt;a href="https://devblogs.microsoft.com/dotnet/copilot-studio-dotnet-10-migration/"&gt;Copilot Studio gets faster with .NET 10 on WebAssembly&lt;/a&gt;&lt;/p&gt;</content:encoded></item></channel></rss>