<?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>Dotnet | The .NET Blog</title><link>https://thedotnetblog.com/ko/tags/dotnet/</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>Mon, 11 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/ko/tags/dotnet/index.xml" rel="self" type="application/rss+xml"/><item><title>SDD Conference 2026</title><link>https://thedotnetblog.com/ko/events/sdd-conference-2026/</link><pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate><guid>https://thedotnetblog.com/ko/events/sdd-conference-2026/</guid><description>런던 Barbican Centre에서 열리는 5일간의 소프트웨어 개발 컨퍼런스 — 78개 세션과 14개 워크숍으로 아키텍처, .NET, AI, Azure, DevOps 등을 다룹니다.</description><content:encoded>&lt;p&gt;&lt;strong&gt;SDD 2026&lt;/strong&gt;은 &lt;strong&gt;2026년 5월 11일~15일&lt;/strong&gt; &lt;strong&gt;런던의 Barbican Centre&lt;/strong&gt;에서 개최됩니다. 3일간의 핵심 컨퍼런스는 화요일부터 목요일까지이며, 월요일과 금요일에는 선택적 전일 워크숍이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;78개 세션&lt;/strong&gt;과 &lt;strong&gt;14개 워크숍&lt;/strong&gt;을 갖춘 유럽에서 가장 알찬 개발자 컨퍼런스 중 하나입니다.&lt;/p&gt;
&lt;h2 id="주제"&gt;주제&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;아키텍처적 사고&lt;/li&gt;
&lt;li&gt;C# 13에서의 함수형 코드&lt;/li&gt;
&lt;li&gt;서버리스 디자인&lt;/li&gt;
&lt;li&gt;시맨틱 AI&lt;/li&gt;
&lt;li&gt;Azure Kubernetes Services&lt;/li&gt;
&lt;li&gt;린 DevOps 전략&lt;/li&gt;
&lt;li&gt;모델 컨텍스트 프로토콜 (MCP)&lt;/li&gt;
&lt;li&gt;.NET에서의 에이전틱 AI&lt;/li&gt;
&lt;li&gt;모놀리스 리팩토링&lt;/li&gt;
&lt;li&gt;LLM으로 더 빠르게 코딩&lt;/li&gt;
&lt;li&gt;포스트 양자 세계의 암호학&lt;/li&gt;
&lt;li&gt;로컬 퍼스트 개발&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="발표자"&gt;발표자&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Kevlin Henney&lt;/strong&gt;, &lt;strong&gt;Neal Ford&lt;/strong&gt;, &lt;strong&gt;Sander Hoogendoorn&lt;/strong&gt;, &lt;strong&gt;Andrew Clymer&lt;/strong&gt;, &lt;strong&gt;Jacqui Read&lt;/strong&gt;, &lt;strong&gt;Christian Weyer&lt;/strong&gt;, &lt;strong&gt;Jeff Prosise&lt;/strong&gt;, &lt;strong&gt;Jules May&lt;/strong&gt;, &lt;strong&gt;Oliver Sturm&lt;/strong&gt;, &lt;strong&gt;Raju Gandhi&lt;/strong&gt;를 포함한 세계적 수준의 라인업.&lt;/p&gt;
&lt;h2 id="티켓-및-정보"&gt;티켓 및 정보&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sddconf.com/"&gt;이벤트 웹사이트&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sddvault.s3.amazonaws.com/assets/SDD_2026_schedule.pdf"&gt;전체 어젠다 PDF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sddconf.com/register"&gt;등록 옵션&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SDD 2025 참가자의 98%가 전체 경험을 좋음, 매우 좋음 또는 우수로 평가했습니다.&lt;/p&gt;</content:encoded></item><item><title>Python, TypeScript, .NET으로 azd 훅 작성하기: 셸 스크립트와의 작별</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azd-hooks-python-javascript-typescript-dotnet/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azd-hooks-python-javascript-typescript-dotnet/</guid><description>Azure Developer CLI가 이제 Python, JavaScript, TypeScript, .NET으로 훅 작성을 지원합니다. 마이그레이션 스크립트 하나 때문에 Bash로 전환할 필요가 없어집니다.</description><content:encoded>&lt;p&gt;&lt;em&gt;이 게시물은 자동으로 번역되었습니다. 원본 버전을 보려면 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azd-hooks-python-javascript-typescript-dotnet/"&gt;여기를 클릭하세요&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;완전히 .NET으로 구성된 프로젝트에서 azd 훅을 위해 Bash 스크립트를 작성해야 했던 경험이 있다면, 그 불편함을 잘 알 것이다. 프로젝트의 모든 것이 C#인데, 왜 pre-provisioning 단계 하나 때문에 셸 문법으로 전환해야 하는가.&lt;/p&gt;
&lt;p&gt;그 불만이 이제 공식적으로 해결됐다. Azure Developer CLI가 &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-multi-language-hooks/"&gt;훅의 멀티 언어 지원을 출시&lt;/a&gt;했으며, 기대했던 것만큼 훌륭하다.&lt;/p&gt;
&lt;h2 id="훅이란"&gt;훅이란&lt;/h2&gt;
&lt;p&gt;훅은 &lt;code&gt;azd&lt;/code&gt; 라이프사이클의 핵심 지점에서 실행되는 스크립트다 — 프로비저닝 전, 배포 후 등. &lt;code&gt;azure.yaml&lt;/code&gt;에 정의되며 CLI를 수정하지 않고 커스텀 로직을 주입할 수 있게 해준다.&lt;/p&gt;
&lt;p&gt;기존에는 Bash와 PowerShell만 지원됐다. 이제 &lt;strong&gt;Python, JavaScript, TypeScript 또는 .NET&lt;/strong&gt;을 사용할 수 있으며, &lt;code&gt;azd&lt;/code&gt;가 나머지를 자동으로 처리한다.&lt;/p&gt;
&lt;h2 id="감지-방식"&gt;감지 방식&lt;/h2&gt;
&lt;p&gt;훅을 파일로 가리키기만 하면 &lt;code&gt;azd&lt;/code&gt;가 파일 확장자에서 언어를 추론한다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;preprovision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/setup.py&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;postdeploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/seed.ts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;postprovision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/migrate.cs&lt;/span&gt;&lt;span class="w"&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;kind: python&lt;/code&gt; (또는 해당 언어)을 명시적으로 지정할 수 있다.&lt;/p&gt;
&lt;h2 id="언어별-주요-세부-사항"&gt;언어별 주요 세부 사항&lt;/h2&gt;
&lt;h3 id="python"&gt;Python&lt;/h3&gt;
&lt;p&gt;스크립트 옆 (또는 상위 디렉토리)에 &lt;code&gt;requirements.txt&lt;/code&gt;나 &lt;code&gt;pyproject.toml&lt;/code&gt;을 놓으면 &lt;code&gt;azd&lt;/code&gt;가 자동으로 가상 환경을 생성하고 의존성을 설치한 후 스크립트를 실행한다.&lt;/p&gt;
&lt;h3 id="javascript와-typescript"&gt;JavaScript와 TypeScript&lt;/h3&gt;
&lt;p&gt;같은 패턴 — 스크립트 근처에 &lt;code&gt;package.json&lt;/code&gt;을 두면 &lt;code&gt;azd&lt;/code&gt;가 먼저 &lt;code&gt;npm install&lt;/code&gt;을 실행한다. TypeScript의 경우 컴파일 단계나 &lt;code&gt;tsconfig.json&lt;/code&gt; 없이 &lt;code&gt;npx tsx&lt;/code&gt;를 사용한다.&lt;/p&gt;
&lt;h3 id="net"&gt;.NET&lt;/h3&gt;
&lt;p&gt;두 가지 모드 지원:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;프로젝트 모드&lt;/strong&gt;: 스크립트 옆에 &lt;code&gt;.csproj&lt;/code&gt;가 있으면 &lt;code&gt;azd&lt;/code&gt;가 자동으로 &lt;code&gt;dotnet restore&lt;/code&gt;와 &lt;code&gt;dotnet build&lt;/code&gt;를 실행한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;단일 파일 모드&lt;/strong&gt;: .NET 10+에서 독립 &lt;code&gt;.cs&lt;/code&gt; 파일을 &lt;code&gt;dotnet run script.cs&lt;/code&gt;로 직접 실행 가능하다. 프로젝트 파일 불필요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="실행기별-설정"&gt;실행기별 설정&lt;/h2&gt;
&lt;p&gt;각 언어는 선택적 &lt;code&gt;config&lt;/code&gt; 블록을 지원한다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;preprovision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/setup.ts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;packageManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pnpm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;postprovision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./hooks/migrate.cs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Release&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;framework&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;net10.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="net-개발자에게-중요한-이유"&gt;.NET 개발자에게 중요한 이유&lt;/h2&gt;
&lt;p&gt;훅은 azd 기반 프로젝트에서 언어 전환을 강제하는 마지막 장소였다. 이제 앱 코드, 인프라 스크립트, 라이프사이클 훅을 포함한 전체 배포 파이프라인이 하나의 언어로 살 수 있다. 기존 .NET 유틸리티를 훅에서 재사용하고, 공유 라이브러리를 참조하고, 셸 스크립트 유지보수에서 해방될 수 있다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;작은 변화처럼 보이지만 azd 일상 워크플로우에서 많은 마찰을 제거하는 변화 중 하나다. 훅의 멀티 언어 지원은 지금 바로 사용 가능하다 — &lt;a href="https://devblogs.microsoft.com/azure-sdk/azd-multi-language-hooks/"&gt;공식 게시물&lt;/a&gt;에서 전체 문서를 확인해 보자.&lt;/p&gt;</content:encoded></item><item><title>Windows App Dev CLI v0.3: 터미널에서 F5 디버그와 에이전트를 위한 UI 자동화</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/windows-app-dev-cli-v03-run-ui-automation/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/windows-app-dev-cli-v03-run-ui-automation/</guid><description>Windows App Development CLI v0.3는 터미널에서 디버그 실행을 위한 winapp run, UI 자동화를 위한 winapp ui, 그리고 패키지 앱에서 dotnet run을 동작하게 하는 NuGet 패키지를 제공합니다.</description><content:encoded>&lt;p&gt;&lt;em&gt;이 게시물은 자동으로 번역되었습니다. 원본을 보려면 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/windows-app-dev-cli-v03-run-ui-automation/"&gt;여기를 클릭하세요&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Visual Studio의 F5 경험은 훌륭합니다. 하지만 CI 파이프라인, 자동화 워크플로우, 또는 AI 에이전트가 테스트를 수행할 때 패키지된 Windows 앱을 시작하고 디버그하기 위해 VS를 열어야 한다면 너무 번거롭습니다.&lt;/p&gt;
&lt;p&gt;Windows App Development CLI v0.3이 &lt;a href="https://devblogs.microsoft.com/ifdef-windows/windows-app-development-cli-v0-3-new-run-and-ui-commands-plus-dotnet-run-support-for-packaged-apps/"&gt;출시&lt;/a&gt;되었으며, 두 가지 핵심 기능으로 이를 직접 해결합니다: &lt;code&gt;winapp run&lt;/code&gt;과 &lt;code&gt;winapp ui&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="winapp-run-어디서나-f5"&gt;winapp run: 어디서나 F5&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;winapp run&lt;/code&gt;은 언패키지된 앱 폴더와 매니페스트를 받아, VS가 디버그 시작 시 수행하는 모든 작업을 실행합니다: 루스 패키지 등록, 앱 시작, 재배포 간 &lt;code&gt;LocalState&lt;/code&gt; 보존.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 앱을 빌드한 다음 패키지 앱으로 실행&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;winapp run ./bin/Debug
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;WinUI, WPF, WinForms, Console, Avalonia 등에서 동작합니다. 모드는 개발자와 자동화 워크플로우 모두를 위해 설계되었습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--detach&lt;/code&gt;&lt;/strong&gt;: 시작 후 즉시 터미널에 제어권을 반환합니다. CI/자동화에 적합합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--unregister-on-exit&lt;/code&gt;&lt;/strong&gt;: 앱 종료 시 등록된 패키지를 정리합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;--debug-output&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;OutputDebugString&lt;/code&gt; 메시지와 예외를 실시간으로 캡처합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="새로운-nuget-패키지-패키지-앱을-위한-dotnet-run"&gt;새로운 NuGet 패키지: 패키지 앱을 위한 dotnet run&lt;/h2&gt;
&lt;p&gt;.NET 개발자를 위한 새로운 NuGet 패키지가 있습니다: &lt;code&gt;Microsoft.Windows.SDK.BuildTools.WinApp&lt;/code&gt;. 설치 후 &lt;code&gt;dotnet run&lt;/code&gt;이 전체 이너 루프를 처리합니다: 빌드, 루스 레이아웃 패키지 준비, Windows 등록 및 시작 — 모두 한 단계로.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;winapp init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 또는&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet add package Microsoft.Windows.SDK.BuildTools.WinApp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="winapp-ui-커맨드-라인에서-ui-자동화"&gt;winapp ui: 커맨드 라인에서 UI 자동화&lt;/h2&gt;
&lt;p&gt;이것이 에이전트 시나리오를 여는 기능입니다. &lt;code&gt;winapp ui&lt;/code&gt;는 터미널에서 실행 중인 모든 Windows 앱(WPF, WinForms, Win32, Electron, WinUI3)에 대한 완전한 UI 자동화 액세스를 제공합니다.&lt;/p&gt;
&lt;p&gt;가능한 작업:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모든 최상위 창 나열&lt;/li&gt;
&lt;li&gt;창의 전체 UI 자동화 트리 탐색&lt;/li&gt;
&lt;li&gt;이름, 유형 또는 자동화 ID로 요소 검색&lt;/li&gt;
&lt;li&gt;클릭, 호출 및 값 설정&lt;/li&gt;
&lt;li&gt;스크린샷 캡처&lt;/li&gt;
&lt;li&gt;요소 나타날 때까지 대기 — 테스트 동기화에 이상적&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;winapp ui&lt;/code&gt;와 &lt;code&gt;winapp run&lt;/code&gt;을 결합하면 터미널에서 완전한 빌드 → 시작 → 검증 워크플로우가 가능합니다. 에이전트가 앱을 실행하고, UI 상태를 검사하고, 프로그래밍 방식으로 상호작용하여 결과를 검증할 수 있습니다.&lt;/p&gt;
&lt;h2 id="기타-새로운-기능"&gt;기타 새로운 기능&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;winapp unregister&lt;/code&gt;&lt;/strong&gt;: 완료 후 사이드로드된 패키지를 제거합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;winapp manifest add-alias&lt;/code&gt;&lt;/strong&gt;: 터미널에서 이름으로 앱을 시작하는 별칭을 추가합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;탭 자동완성&lt;/strong&gt;: 단일 명령으로 PowerShell 완성을 구성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="설치-방법"&gt;설치 방법&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;winget install Microsoft.WinAppCli
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 또는&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;npm install -g @microsoft/winappcli
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;CLI는 공개 미리 보기 중입니다. 전체 문서는 &lt;a href="https://github.com/microsoft/WinAppCli"&gt;GitHub 저장소&lt;/a&gt;를, 모든 세부 정보는 &lt;a href="https://devblogs.microsoft.com/ifdef-windows/windows-app-development-cli-v0-3-new-run-and-ui-commands-plus-dotnet-run-support-for-packaged-apps/"&gt;원본 발표&lt;/a&gt;를 참조하세요.&lt;/p&gt;</content:encoded></item><item><title>터미널 감시는 그만: Aspire의 분리 모드가 워크플로를 바꾼다</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-detached-mode-free-your-terminal/</link><pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-detached-mode-free-your-terminal/</guid><description>Aspire 13.2에서는 AppHost를 백그라운드에서 실행하고 터미널을 되찾을 수 있습니다. 새로운 CLI 명령과 에이전트 지원과 결합하면, 생각보다 훨씬 큰 변화입니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-detached-mode-free-your-terminal/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Aspire AppHost를 실행할 때마다 터미널이 사라집니다. 잠겨버립니다. Ctrl+C를 누를 때까지 점유된 상태입니다. 빠르게 명령어를 실행해야 하나요? 다른 탭을 엽니다. 로그를 확인하고 싶나요? 또 다른 탭. 작은 불편함이지만 빠르게 쌓입니다.&lt;/p&gt;
&lt;p&gt;Aspire 13.2가 이 문제를 해결합니다. James Newton-King이 &lt;a href="https://devblogs.microsoft.com/aspire/aspire-detached-mode-and-process-management/"&gt;자세한 내용을 작성했는데&lt;/a&gt;, 솔직히 이건 사용하는 순간 바로 작업 방식이 바뀌는 기능 중 하나입니다.&lt;/p&gt;
&lt;h2 id="분리-모드-명령어-하나로-터미널-되찾기"&gt;분리 모드: 명령어 하나로 터미널 되찾기&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이것은 &lt;code&gt;aspire run --detach&lt;/code&gt;의 단축 명령입니다. AppHost가 백그라운드에서 시작되고 터미널이 즉시 돌아옵니다. 추가 탭 없이. 터미널 멀티플렉서 없이. 프롬프트만 준비된 상태로요.&lt;/p&gt;
&lt;h2 id="실행-중인-프로세스-관리하기"&gt;실행 중인 프로세스 관리하기&lt;/h2&gt;
&lt;p&gt;핵심은 이겁니다 — 백그라운드 실행은 실행 중인 것을 관리할 수 있어야만 의미가 있습니다. Aspire 13.2는 바로 이를 위한 완전한 CLI 명령 세트를 제공합니다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# List all running AppHosts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire ps
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Inspect the state of a specific AppHost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire describe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stream logs from a running AppHost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire logs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Stop a specific AppHost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire stop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이로써 Aspire CLI가 본격적인 프로세스 관리자가 됩니다. 여러 AppHost를 시작하고, 상태를 확인하고, 로그를 추적하고, 종료할 수 있습니다 — 모두 하나의 터미널 세션에서.&lt;/p&gt;
&lt;h2 id="격리-모드와-결합하기"&gt;격리 모드와 결합하기&lt;/h2&gt;
&lt;p&gt;분리 모드는 격리 모드와 자연스럽게 어울립니다. 포트 충돌 없이 같은 프로젝트의 인스턴스 두 개를 백그라운드에서 실행하고 싶다면?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire start --isolated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire start --isolated
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;각각 랜덤 포트, 별도의 시크릿, 자체 라이프사이클을 갖습니다. &lt;code&gt;aspire ps&lt;/code&gt;로 둘 다 확인하고, &lt;code&gt;aspire stop&lt;/code&gt;으로 필요 없는 것을 중지하세요.&lt;/p&gt;
&lt;h2 id="코딩-에이전트에게-이것이-중요한-이유"&gt;코딩 에이전트에게 이것이 중요한 이유&lt;/h2&gt;
&lt;p&gt;여기서부터 정말 흥미로워집니다. 터미널에서 작업하는 코딩 에이전트가 이제 다음을 할 수 있습니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;aspire start&lt;/code&gt;로 앱 시작&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aspire describe&lt;/code&gt;로 상태 조회&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aspire logs&lt;/code&gt;로 로그를 확인하여 문제 진단&lt;/li&gt;
&lt;li&gt;완료 후 &lt;code&gt;aspire stop&lt;/code&gt;으로 중지&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;모두 터미널 세션을 잃지 않고 수행할 수 있습니다. 분리 모드 이전에는 AppHost를 실행한 에이전트가 자신의 터미널에 갇혀버렸습니다. 이제는 시작, 관찰, 반복, 정리가 가능합니다 — 자율 에이전트에게 기대하는 바로 그 동작입니다.&lt;/p&gt;
&lt;p&gt;Aspire 팀은 이 부분에 공을 들였습니다. &lt;code&gt;aspire agent init&lt;/code&gt;을 실행하면 에이전트에게 이러한 명령을 가르치는 Aspire 스킬 파일이 설정됩니다. 이를 통해 Copilot의 코딩 에이전트 같은 도구가 바로 Aspire 워크로드를 관리할 수 있습니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;분리 모드는 단순한 플래그로 위장한 워크플로 업그레이드입니다. 터미널 간 컨텍스트 전환이 사라지고, 에이전트가 스스로를 차단하지 않으며, 새로운 CLI 명령으로 실행 중인 것을 실시간으로 파악할 수 있습니다. 실용적이고, 깔끔하며, 일상 개발 사이클이 눈에 띄게 매끄러워집니다.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/aspire/aspire-detached-mode-and-process-management/"&gt;전체 글&lt;/a&gt;에서 모든 세부 사항을 확인하고, &lt;code&gt;aspire update --self&lt;/code&gt;로 Aspire 13.2를 설치하세요.&lt;/p&gt;</content:encoded></item><item><title>핀 클러스터링이 드디어 .NET MAUI Maps에 도착 — 프로퍼티 하나, 고통 제로</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/maui-maps-pin-clustering-finally/</link><pubDate>Thu, 16 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/maui-maps-pin-clustering-finally/</guid><description>.NET MAUI 11 Preview 3에서 Map 컨트롤에 네이티브 핀 클러스터링이 추가되었습니다. 프로퍼티 하나, 독립적인 클러스터링 그룹, 탭 처리 — 모두 내장.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/maui-maps-pin-clustering-finally/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;지도에 핀 100개를 로드했더니 전체가 읽을 수 없는 덩어리가 되는 그 순간, 아시죠? 네, 지금까지 .NET MAUI Maps 경험이 딱 그랬습니다. 이제 끝입니다.&lt;/p&gt;
&lt;p&gt;David Ortinau가 &lt;a href="https://devblogs.microsoft.com/dotnet/pin-clustering-in-dotnet-maui-maps/"&gt;방금 발표했습니다&lt;/a&gt;. .NET MAUI 11 Preview 3에서 Android와 iOS/Mac Catalyst에 핀 클러스터링이 기본 탑재됩니다. 그리고 가장 좋은 점 — 활성화하는 게 말도 안 되게 간단합니다.&lt;/p&gt;
&lt;h2 id="모든-것을-지배하는-하나의-프로퍼티"&gt;모든 것을 지배하는 하나의 프로퍼티&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;maps:Map&lt;/span&gt; &lt;span class="na"&gt;IsClusteringEnabled=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이게 전부입니다. 가까운 핀들이 카운트 배지가 달린 클러스터로 그룹화됩니다. 확대하면 펼쳐지고, 축소하면 접힙니다. 모던한 지도라면 당연히 기대하는 동작 — 이제 프로퍼티 하나로 얻을 수 있습니다.&lt;/p&gt;
&lt;h2 id="독립적인-클러스터링-그룹"&gt;독립적인 클러스터링 그룹&lt;/h2&gt;
&lt;p&gt;여기서부터 흥미로워집니다. 모든 핀이 함께 클러스터링되어야 하는 건 아닙니다. 커피숍과 공원은 다른 것이고, 지도도 그걸 알아야 합니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ClusteringIdentifier&lt;/code&gt; 프로퍼티를 사용하면 핀을 독립적인 그룹으로 분리할 수 있습니다:&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="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;Label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Pike Place Coffee&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;Location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;47.6097&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;122.3331&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;ClusteringIdentifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;coffee&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;Label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Occidental Square&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;Location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;47.6064&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;122.3325&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;ClusteringIdentifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;parks&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;/p&gt;
&lt;h2 id="클러스터-탭-처리"&gt;클러스터 탭 처리&lt;/h2&gt;
&lt;p&gt;사용자가 클러스터를 탭하면 필요한 모든 것이 담긴 &lt;code&gt;ClusterClicked&lt;/code&gt; 이벤트를 받습니다:&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="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClusterClicked&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Label&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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;DisplayAlert&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="s"&gt;$&amp;#34;Cluster ({e.Pins.Count} pins)&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;names&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="s"&gt;&amp;#34;OK&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Suppress default zoom-to-cluster behavior:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// e.Handled = true;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;Pins&lt;/code&gt;(클러스터 내 핀), &lt;code&gt;Location&lt;/code&gt;(지리적 중심), &lt;code&gt;Handled&lt;/code&gt;(기본 줌 동작을 재정의하려면 &lt;code&gt;true&lt;/code&gt;로 설정)를 받습니다. 간단하고, 실용적이고, 정확히 기대한 대로입니다.&lt;/p&gt;
&lt;h2 id="알아두면-좋은-플랫폼-세부사항"&gt;알아두면 좋은 플랫폼 세부사항&lt;/h2&gt;
&lt;p&gt;Android에서는 클러스터링이 줌 변경 시 재계산하는 커스텀 그리드 기반 알고리즘을 사용합니다 — 외부 의존성 없음. iOS와 Mac Catalyst에서는 MapKit의 네이티브 &lt;code&gt;MKClusterAnnotation&lt;/code&gt; 지원을 활용하여 부드럽고 플랫폼 네이티브한 애니메이션을 제공합니다.&lt;/p&gt;
&lt;p&gt;MAUI 팀이 올바른 결정을 내린 사례입니다 — 의미 있는 곳에서 플랫폼에 의존하기.&lt;/p&gt;
&lt;h2 id="왜-이것이-중요한가"&gt;왜 이것이 중요한가&lt;/h2&gt;
&lt;p&gt;핀 클러스터링은 .NET MAUI에서 가장 많이 요청된 기능 중 하나였습니다(&lt;a href="https://github.com/dotnet/maui/issues/11811"&gt;issue #11811&lt;/a&gt;). 당연한 이유가 있습니다. 지도에 위치를 표시하는 모든 앱 — 배송 추적, 매장 찾기, 부동산 — 에 필요합니다. 이전에는 직접 구현하거나 서드파티 라이브러리를 사용해야 했습니다. 이제는 내장되어 있습니다.&lt;/p&gt;
&lt;p&gt;크로스플랫폼 모바일 앱을 만드는 .NET 개발자들에게, 이것은 MAUI를 지도 중심 시나리오에서 진정으로 실용적인 선택으로 만드는 삶의 질 개선입니다.&lt;/p&gt;
&lt;h2 id="시작하기"&gt;시작하기&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://dotnet.microsoft.com/download/dotnet/11.0"&gt;.NET 11 Preview 3&lt;/a&gt;를 설치하고 .NET MAUI 워크로드를 업데이트하세요. &lt;a href="https://github.com/dotnet/maui-samples/tree/main/10.0/UserInterface/Views/Map/MapDemo/WorkingWithMaps"&gt;Maps 샘플&lt;/a&gt;에 바로 사용해볼 수 있는 새로운 클러스터링 페이지가 포함되어 있습니다.&lt;/p&gt;
&lt;p&gt;뭔가 만들어 보세요 — 그리고 지도가 드디어 숨 쉴 수 있게 해주세요.&lt;/p&gt;</content:encoded></item><item><title>.NET 2026년 4월 서비싱 — 오늘 바로 적용해야 할 보안 패치</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/dotnet-april-2026-servicing-security-patches/</link><pubDate>Wed, 15 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/dotnet-april-2026-servicing-security-patches/</guid><description>2026년 4월 서비싱 릴리스는 .NET 10, .NET 9, .NET 8, .NET Framework에 걸쳐 6개의 CVE를 패치합니다 — 원격 코드 실행 취약점 2건을 포함합니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/dotnet-april-2026-servicing-security-patches/"&gt;여기&lt;/a&gt;를 참조하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;.NET과 .NET Framework의 &lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-and-dotnet-framework-april-2026-servicing-updates/"&gt;2026년 4월 서비싱 업데이트&lt;/a&gt;가 출시되었습니다. 이번에는 빨리 적용하고 싶은 보안 수정 사항이 포함되어 있습니다. 6개의 CVE가 패치되었으며, 그 중 2개는 원격 코드 실행(RCE) 취약점입니다.&lt;/p&gt;
&lt;h2 id="패치된-내용"&gt;패치된 내용&lt;/h2&gt;
&lt;p&gt;빠른 요약은 다음과 같습니다:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CVE&lt;/th&gt;
&lt;th&gt;유형&lt;/th&gt;
&lt;th&gt;영향 범위&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-26171&lt;/td&gt;
&lt;td&gt;보안 기능 우회&lt;/td&gt;
&lt;td&gt;.NET 10, 9, 8 + .NET Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-32178&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;원격 코드 실행&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;.NET 10, 9, 8 + .NET Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-33116&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;원격 코드 실행&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;.NET 10, 9, 8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-32203&lt;/td&gt;
&lt;td&gt;서비스 거부&lt;/td&gt;
&lt;td&gt;.NET 10, 9, 8 + .NET Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-23666&lt;/td&gt;
&lt;td&gt;서비스 거부&lt;/td&gt;
&lt;td&gt;.NET Framework 3.0–4.8.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2026-32226&lt;/td&gt;
&lt;td&gt;서비스 거부&lt;/td&gt;
&lt;td&gt;.NET Framework 2.0–4.8.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;2개의 RCE CVE(CVE-2026-32178 및 CVE-2026-33116)는 가장 넓은 범위의 .NET 버전에 영향을 미치며 우선적으로 대응해야 합니다.&lt;/p&gt;
&lt;h2 id="업데이트된-버전"&gt;업데이트된 버전&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;.NET 10&lt;/strong&gt;: 10.0.6&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.NET 9&lt;/strong&gt;: 9.0.15&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;.NET 8&lt;/strong&gt;: 8.0.26&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;모두 일반적인 채널을 통해 사용할 수 있습니다 — &lt;a href="https://dotnet.microsoft.com/download/dotnet/10.0"&gt;dotnet.microsoft.com&lt;/a&gt;, MCR의 컨테이너 이미지, Linux 패키지 관리자.&lt;/p&gt;
&lt;h2 id="해야-할-일"&gt;해야 할 일&lt;/h2&gt;
&lt;p&gt;프로젝트와 CI/CD 파이프라인을 최신 패치 버전으로 업데이트하세요. 컨테이너를 실행 중이라면 최신 이미지를 풀하세요. .NET Framework를 사용 중이라면 해당 패치에 대해 &lt;a href="https://learn.microsoft.com/dotnet/framework/release-notes/release-notes"&gt;.NET Framework 릴리스 노트&lt;/a&gt;를 확인하세요.&lt;/p&gt;
&lt;p&gt;.NET 10을 프로덕션에서 실행하고 있다면(현재 릴리스입니다), 10.0.6은 필수 업데이트입니다. LTS 트랙의 .NET 9.0.15와 .NET 8.0.26도 마찬가지입니다. 2개의 RCE 취약점은 미룰 수 있는 것이 아닙니다.&lt;/p&gt;</content:encoded></item><item><title>Azure MCP Server 2.0 출시 — 자체 호스팅 에이전트형 클라우드 자동화가 이제 시작됩니다</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azure-mcp-server-2-self-hosted-agentic-cloud/</link><pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azure-mcp-server-2-self-hosted-agentic-cloud/</guid><description>Azure MCP Server 2.0이 자체 호스팅 원격 배포, 57개 Azure 서비스에 걸친 276개 도구, 엔터프라이즈급 보안과 함께 안정화되었습니다. .NET 개발자들이 에이전트형 워크플로우를 구축할 때 알아야 할 내용을 정리했습니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원본은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azure-mcp-server-2-self-hosted-agentic-cloud/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;최근에 MCP와 Azure로 뭔가를 구축해본 분이라면 로컬 환경에서는 잘 작동한다는 걸 아실 겁니다. MCP 서버를 연결하고, AI 에이전트가 Azure 리소스와 대화하도록 하고, 끝. 하지만 그 설정을 팀 전체에서 공유해야 하는 순간? 그곳이 바로 복잡해지던 지점이었습니다.&lt;/p&gt;
&lt;p&gt;이제 더 이상 그럴 필요 없습니다. Azure MCP Server &lt;a href="https://devblogs.microsoft.com/azure-sdk/announcing-azure-mcp-server-2-0-stable-release/"&gt;방금 2.0 안정 버전에 도달했고&lt;/a&gt;, 이번 주요 기능은 정확히 엔터프라이즈 팀들이 요청해온 것입니다: &lt;strong&gt;자체 호스팅 원격 MCP 서버 지원&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="azure-mcp-server란"&gt;Azure MCP Server란?&lt;/h2&gt;
&lt;p&gt;간단히 정리하겠습니다. Azure MCP Server는 &lt;a href="https://modelcontextprotocol.io/docs/getting-started/intro"&gt;Model Context Protocol&lt;/a&gt; 명세를 구현하고 Azure의 기능을 구조화되고 발견 가능한 도구로 노출하여 AI 에이전트가 호출할 수 있도록 합니다. 에이전트와 Azure 사이의 표준화된 브릿지라고 생각하면 됩니다. 프로비저닝, 배포, 모니터링, 진단, 모든 것이 하나의 일관된 인터페이스를 통해 이루어집니다.&lt;/p&gt;
&lt;p&gt;숫자만 봐도 충분합니다: &lt;strong&gt;57개 Azure 서비스에 걸친 276개의 MCP 도구&lt;/strong&gt;. 정말 강력한 커버리지입니다.&lt;/p&gt;
&lt;h2 id="핵심-자체-호스팅-원격-배포"&gt;핵심: 자체 호스팅 원격 배포&lt;/h2&gt;
&lt;p&gt;이게 중요한 이유는 뭘까요. 로컬 머신에서 MCP를 실행하는 건 개발과 실험에는 충분합니다. 하지만 실제 팀 환경에서는 다음이 필요합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;개발자와 내부 에이전트 시스템을 위한 공유 액세스&lt;/li&gt;
&lt;li&gt;중앙 집중식 구성(테넌트 컨텍스트, 구독 기본값, 텔레메트리)&lt;/li&gt;
&lt;li&gt;엔터프라이즈 네트워크 및 정책 경계&lt;/li&gt;
&lt;li&gt;CI/CD 파이프라인 통합&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Azure MCP Server 2.0은 이 모든 것을 다룹니다. HTTP 기반 전송, 적절한 인증, 일관된 거버넌스와 함께 중앙에서 관리되는 내부 서비스로 배포할 수 있습니다.&lt;/p&gt;
&lt;p&gt;인증에 대해서는 두 가지 견고한 옵션이 있습니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Managed Identity&lt;/strong&gt; — &lt;a href="https://aka.ms/azmcp/self-host/foundry"&gt;Microsoft Foundry&lt;/a&gt;와 함께 실행할 때&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;On-Behalf-Of (OBO) flow&lt;/strong&gt; — 로그인한 사용자의 컨텍스트를 사용하여 Azure API를 호출하는 OpenID Connect 위임&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이 OBO 흐름은 우리 .NET 개발자들에게 특히 흥미롭습니다. 이는 에이전트형 워크플로우가 과도한 권한을 가진 서비스 계정이 아닌 실제 사용자의 권한으로 작동할 수 있다는 의미입니다. 최소 권한 원칙이 처음부터 내장되어 있는 것입니다.&lt;/p&gt;
&lt;h2 id="보안-강화"&gt;보안 강화&lt;/h2&gt;
&lt;p&gt;단순한 기능 릴리스가 아닙니다. 보안 측면의 업그레이드이기도 합니다. 2.0 릴리스는 다음을 추가합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;더 강화된 엔드포인트 검증&lt;/li&gt;
&lt;li&gt;쿼리 지향 도구의 주입 패턴에 대한 보호&lt;/li&gt;
&lt;li&gt;개발 환경을 위한 더 엄격한 격리 제어&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MCP를 공유 서비스로 노출할 거라면, 이러한 보안 조치들은 정말 중요합니다.&lt;/p&gt;
&lt;h2 id="어디서-사용할-수-있나요"&gt;어디서 사용할 수 있나요?&lt;/h2&gt;
&lt;p&gt;클라이언트 호환성 범위는 매우 넓습니다. Azure MCP Server 2.0은 다음과 함께 작동합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IDE&lt;/strong&gt;: VS Code, Visual Studio, IntelliJ, Eclipse, Cursor&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CLI 에이전트&lt;/strong&gt;: GitHub Copilot CLI, Claude Code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;독립 실행형&lt;/strong&gt;: 간단한 설정을 위한 로컬 서버&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;자체 호스팅 원격&lt;/strong&gt;: 2.0의 새로운 주인공&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;또한 Azure US Government와 21Vianet에 의해 운영되는 Azure를 위한 소버린 클라우드 지원이 있으며, 이는 규제 대상 배포에 필수적입니다.&lt;/p&gt;
&lt;h2 id="net-개발자에게-왜-중요한가요"&gt;.NET 개발자에게 왜 중요한가요?&lt;/h2&gt;
&lt;p&gt;Semantic Kernel, Microsoft Agent Framework, 또는 자체 오케스트레이션이든 .NET으로 에이전트형 애플리케이션을 구축하고 있다면, Azure MCP Server 2.0은 에이전트가 Azure 인프라와 상호작용할 수 있는 프로덕션 준비 방식을 제공합니다. 커스텀 REST 래퍼 없음. 서비스별 통합 패턴 없음. 오직 MCP뿐입니다.&lt;/p&gt;
&lt;p&gt;며칠 전에 출시된 &lt;a href="https://devblogs.microsoft.com/azure-sdk/mcp-as-easy-as-1-2-3-introducing-the-fluent-api-for-mcp-apps/"&gt;MCP Apps용 유창한 API&lt;/a&gt;와 함께라면, .NET MCP 생태계는 빠르게 성숙해지고 있습니다.&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;&lt;a href="https://aka.ms/azmcp"&gt;GitHub Repo&lt;/a&gt;&lt;/strong&gt; — 소스 코드, 문서, 모든 것&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://aka.ms/azmcp/download/docker"&gt;Docker Image&lt;/a&gt;&lt;/strong&gt; — 컨테이너화된 배포&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://aka.ms/azmcp/download/vscode"&gt;VS Code Extension&lt;/a&gt;&lt;/strong&gt; — IDE 통합&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://aka.ms/azmcp/self-host"&gt;Self-hosting guide&lt;/a&gt;&lt;/strong&gt; — 2.0의 주요 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="마치며"&gt;마치며&lt;/h2&gt;
&lt;p&gt;Azure MCP Server 2.0은 데모에서는 화려해 보이지 않지만 실제로는 모든 것을 바꾸는 인프라 업그레이드입니다. 적절한 인증, 보안 강화, 소버린 클라우드 지원과 함께하는 자체 호스팅 원격 MCP는 MCP가 Azure에서 실제 에이전트형 워크플로우를 구축하는 실제 팀을 위해 준비되었다는 의미입니다. &amp;ldquo;엔터프라이즈 준비 완료&amp;quot;라는 신호를 기다리고 있었다면, 이것이 바로 그 신호입니다.&lt;/p&gt;</content:encoded></item><item><title>.NET Aspire 13.2는 AI 에이전트의 가장 친한 친구가 되고 싶어한다</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-agentic-development-build-run-observe/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-agentic-development-build-run-observe/</guid><description>Aspire 13.2가 에이전틱 개발에 올인합니다 — 구조화된 CLI 출력, 격리된 실행, 자동 복구 환경, 그리고 완전한 OpenTelemetry 데이터로 AI 에이전트가 실제로 앱을 빌드, 실행, 관찰할 수 있게 합니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-agentic-development-build-run-observe/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;AI 코딩 에이전트가 꽤 괜찮은 코드를 작성해서 기대했는데, 그것을 실제로 &lt;em&gt;실행&lt;/em&gt;하려고 하면 전부 무너지는 그 순간 아시죠? 포트 충돌, 고스트 프로세스, 잘못된 환경 변수 — 갑자기 에이전트가 기능을 만드는 대신 시작 문제를 디버깅하느라 토큰을 소모합니다.&lt;/p&gt;
&lt;p&gt;Aspire 팀이 바로 이 문제에 대한 &lt;a href="https://devblogs.microsoft.com/aspire/agentic-dev-aspirations/"&gt;정말 사려 깊은 글&lt;/a&gt;을 발표했고, 그들의 답은 설득력이 있습니다: Aspire 13.2는 인간만을 위한 것이 아니라 AI 에이전트를 위해서도 설계되었습니다.&lt;/p&gt;
&lt;h2 id="문제는-현실입니다"&gt;문제는 현실입니다&lt;/h2&gt;
&lt;p&gt;AI 에이전트는 코드 작성에 놀라운 능력을 보여줍니다. 하지만 작동하는 풀스택 앱을 배포하려면 파일 생성 이상의 것이 필요합니다. 서비스를 올바른 순서로 시작하고, 포트를 관리하고, 환경 변수를 설정하고, 데이터베이스를 연결하고, 문제가 생겼을 때 피드백을 받아야 합니다. 현재 대부분의 에이전트는 이 모든 것을 시행착오로 처리합니다 — 명령 실행, 에러 출력 읽기, 재시도.&lt;/p&gt;
&lt;p&gt;Markdown 지침, 커스텀 스킬, 프롬프트를 쌓아올려 가이드하려 하지만, 이것들은 예측 불가능하고 컴파일할 수 없으며 파싱하는 것만으로도 토큰이 듭니다. Aspire 팀은 핵심 인사이트를 정확히 짚었습니다: 에이전트에게 필요한 것은 &lt;strong&gt;컴파일러와 구조화된 API&lt;/strong&gt;이지, 더 많은 Markdown이 아닙니다.&lt;/p&gt;
&lt;h2 id="에이전트-인프라로서의-aspire"&gt;에이전트 인프라로서의 Aspire&lt;/h2&gt;
&lt;p&gt;Aspire 13.2가 에이전틱 개발 테이블에 가져오는 것들:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;전체 스택을 타입이 있는 코드로.&lt;/strong&gt; AppHost가 앱의 전체 토폴로지 — API, 프론트엔드, 데이터베이스, 캐시 — 를 컴파일 가능한 TypeScript 또는 C#로 정의합니다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createBuilder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;./.modules/aspire.js&amp;#39;&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;createBuilder&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postgres&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addPostgres&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;pg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;catalog&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="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addRedis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cache&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addNodeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;src/index.ts&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="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withHttpEndpoint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PORT&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="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;postgres&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="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addViteApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;frontend&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./frontend&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="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&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="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;run&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;em&gt;검증을 위해 빌드&lt;/em&gt;할 수 있습니다. 컴파일러가 뭔가 잘못되면 즉시 알려줍니다. 추측 불필요, 설정 파일에 대한 시행착오 불필요.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;하나의 명령으로 모두 지배.&lt;/strong&gt; 에이전트가 &lt;code&gt;docker compose up&lt;/code&gt;, &lt;code&gt;npm run dev&lt;/code&gt;, 데이터베이스 시작 스크립트를 저글링하는 대신, 모든 것이 &lt;code&gt;aspire start&lt;/code&gt; 하나입니다. 모든 리소스가 올바른 순서로, 올바른 포트에, 올바른 설정으로 시작됩니다. 장시간 실행 프로세스도 에이전트를 멈추지 않습니다 — Aspire가 관리합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;병렬 에이전트를 위한 격리 모드.&lt;/strong&gt; &lt;code&gt;--isolated&lt;/code&gt;를 사용하면 각 Aspire 실행이 자체 랜덤 포트와 별도의 사용자 시크릿을 갖습니다. 여러 에이전트가 git worktree에서 작업 중인가요? 충돌하지 않습니다. 이것은 VS Code의 백그라운드 에이전트처럼 병렬 환경을 생성하는 도구에 매우 중요합니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;텔레메트리를 통한 에이전트의 눈.&lt;/strong&gt; 여기서 정말 강력해집니다. Aspire CLI는 개발 중 완전한 OpenTelemetry 데이터를 노출합니다 — 트레이스, 메트릭, 구조화된 로그. 에이전트가 콘솔 출력을 읽고 최선을 바라는 것이 아닙니다. 서비스 간 실패한 요청을 추적하고, 느린 엔드포인트를 프로파일링하고, 정확히 어디서 문제가 발생하는지 파악할 수 있습니다. 개발 루프에 프로덕션급 관찰 가능성이 있는 것입니다.&lt;/p&gt;
&lt;h2 id="볼링-범퍼-비유"&gt;볼링 범퍼 비유&lt;/h2&gt;
&lt;p&gt;Aspire 팀은 훌륭한 비유를 사용합니다: Aspire를 AI 에이전트를 위한 볼링 레인 범퍼라고 생각하세요. 에이전트가 완벽하지 않다면 (그리고 완벽하지 않을 것입니다), 범퍼가 거터볼을 치지 않도록 막아줍니다. 스택 정의가 잘못된 구성을 방지하고, 컴파일러가 오류를 잡고, CLI가 프로세스 관리를 담당하고, 텔레메트리가 피드백 루프를 제공합니다.&lt;/p&gt;
&lt;p&gt;이것을 Playwright CLI 같은 것과 결합하면, 에이전트가 실제로 앱을 &lt;em&gt;사용&lt;/em&gt;할 수 있습니다 — 플로우를 클릭하고, DOM을 확인하고, 텔레메트리에서 깨진 것을 보고, 코드를 수정하고, 재시작하고, 다시 테스트합니다. 빌드, 실행, 관찰, 수정. 이것이 우리가 추구해온 자율 개발 루프입니다.&lt;/p&gt;
&lt;h2 id="시작하기"&gt;시작하기&lt;/h2&gt;
&lt;p&gt;Aspire가 처음이세요? &lt;a href="https://get.aspire.dev"&gt;get.aspire.dev&lt;/a&gt;에서 CLI를 설치하고 &lt;a href="https://aspire.dev/get-started/first-app"&gt;시작 가이드&lt;/a&gt;를 따르세요.&lt;/p&gt;
&lt;p&gt;이미 Aspire를 사용 중이세요? &lt;code&gt;aspire update --self&lt;/code&gt;를 실행하여 13.2를 받고, 좋아하는 코딩 에이전트를 레포에 연결하세요. Aspire의 가드레일이 있으면 에이전트가 얼마나 더 멀리까지 갈 수 있는지 놀라실 수 있습니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;Aspire 13.2는 더 이상 단순한 분산 앱 프레임워크가 아닙니다 — 필수적인 에이전트 인프라가 되고 있습니다. 구조화된 스택 정의, 원커맨드 시작, 격리된 병렬 실행, 실시간 텔레메트리가 AI 에이전트에게 코드 작성에서 앱 배포로 넘어가는 데 필요한 모든 것을 제공합니다.&lt;/p&gt;
&lt;p&gt;Aspire 팀의 &lt;a href="https://devblogs.microsoft.com/aspire/agentic-dev-aspirations/"&gt;전체 포스트&lt;/a&gt;에서 모든 세부사항과 데모 비디오를 확인하세요.&lt;/p&gt;</content:encoded></item><item><title>Aspire의 격리 모드가 병렬 개발의 포트 충돌 악몽을 해결한다</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-isolated-mode-parallel-instances/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-isolated-mode-parallel-instances/</guid><description>Aspire 13.2가 --isolated 모드를 도입합니다: 랜덤 포트, 분리된 시크릿, 동일한 AppHost의 여러 인스턴스를 실행할 때 충돌 제로. AI 에이전트, worktree, 병렬 워크플로우에 완벽합니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-isolated-mode-parallel-instances/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;같은 프로젝트의 두 인스턴스를 동시에 실행하려고 해본 적이 있다면, 그 고통을 알 것입니다. 포트 8080이 이미 사용 중입니다. 포트 17370이 점유되어 있습니다. 뭔가를 kill하고, 재시작하고, 환경 변수를 저글링하는 — 생산성 킬러입니다.&lt;/p&gt;
&lt;p&gt;이 문제는 나아지는 게 아니라 악화되고 있습니다. AI 에이전트가 독립적으로 작업하기 위해 git worktree를 만듭니다. 백그라운드 에이전트가 별도의 환경을 생성합니다. 개발자가 피처 브랜치를 위해 같은 레포를 두 번 체크아웃합니다. 이 모든 시나리오가 같은 벽에 부딪힙니다: 같은 앱의 두 인스턴스가 같은 포트를 놓고 싸우는 것입니다.&lt;/p&gt;
&lt;p&gt;Aspire 13.2가 단 하나의 플래그로 이것을 해결합니다. Aspire 팀의 James Newton-King이 &lt;a href="https://devblogs.microsoft.com/aspire/aspire-isolated-mode-parallel-development/"&gt;전체 상세 내용을 작성했는데&lt;/a&gt;, &amp;ldquo;왜 진작 이게 없었지?&amp;ldquo;라는 기능 중 하나입니다.&lt;/p&gt;
&lt;h2 id="해결책---isolated"&gt;해결책: &lt;code&gt;--isolated&lt;/code&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire run --isolated
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;끝입니다. 각 실행이 다음을 얻습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;랜덤 포트&lt;/strong&gt; — 인스턴스 간 충돌 없음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;격리된 사용자 시크릿&lt;/strong&gt; — 연결 문자열과 API 키가 인스턴스별로 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;수동 포트 재할당이 필요 없습니다. 환경 변수 저글링도 필요 없습니다. 각 실행이 자동으로 깨끗하고 충돌 없는 환경을 얻습니다.&lt;/p&gt;
&lt;h2 id="이-기능이-빛나는-실제-시나리오"&gt;이 기능이 빛나는 실제 시나리오&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;다중 체크아웃.&lt;/strong&gt; 한 디렉토리에 피처 브랜치가 있고 다른 디렉토리에 버그픽스가 있는 경우:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Terminal 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projects/my-app-feature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire run --isolated
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Terminal 2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projects/my-app-bugfix
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire run --isolated
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;둘 다 충돌 없이 실행됩니다. 대시보드에서 무엇이 어디서 실행 중인지 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VS Code의 백그라운드 에이전트.&lt;/strong&gt; Copilot Chat의 백그라운드 에이전트가 코드에 독립적으로 작업하기 위해 git worktree를 만들면, Aspire AppHost를 실행해야 할 수 있습니다. &lt;code&gt;--isolated&lt;/code&gt; 없이는 기본 worktree와 포트 충돌이 발생합니다. 이것이 있으면 두 인스턴스 모두 문제없이 동작합니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;aspire agent init&lt;/code&gt;에 포함된 Aspire 스킬은 worktree에서 작업할 때 &lt;code&gt;--isolated&lt;/code&gt;를 사용하도록 에이전트에게 자동으로 지시합니다. 따라서 Copilot의 백그라운드 에이전트는 이것을 기본적으로 처리할 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;개발과 병행하는 통합 테스트.&lt;/strong&gt; 기능을 계속 만들면서 라이브 AppHost에 대해 테스트를 실행해야 하나요? 격리 모드는 각 컨텍스트에 자체 포트와 설정을 제공합니다.&lt;/p&gt;
&lt;h2 id="내부-작동-원리"&gt;내부 작동 원리&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;--isolated&lt;/code&gt;를 전달하면, CLI가 해당 실행을 위한 고유 인스턴스 ID를 생성합니다. 이것이 두 가지 동작을 구동합니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;포트 랜덤화&lt;/strong&gt; — AppHost 설정에 정의된 예측 가능한 포트에 바인딩하는 대신, 격리 모드는 모든 것에 대해 사용 가능한 랜덤 포트를 선택합니다 — 대시보드, 서비스 엔드포인트, 전부. 서비스 디스커버리가 자동으로 조정되어 어떤 포트에 할당되든 서비스들이 서로를 찾습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;시크릿 격리&lt;/strong&gt; — 각 격리된 실행은 인스턴스 ID로 키가 지정된 자체 사용자 시크릿 저장소를 갖습니다. 한 실행의 연결 문자열과 API 키가 다른 실행으로 누출되지 않습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;코드 변경은 필요 없습니다. Aspire의 서비스 디스커버리가 런타임에 엔드포인트를 해석하므로, 포트 할당에 관계없이 모든 것이 올바르게 연결됩니다.&lt;/p&gt;
&lt;h2 id="언제-사용할-것인가"&gt;언제 사용할 것인가&lt;/h2&gt;
&lt;p&gt;같은 AppHost의 여러 인스턴스를 동시에 실행할 때 &lt;code&gt;--isolated&lt;/code&gt;를 사용하세요 — 병렬 개발, 자동화된 테스트, AI 에이전트, 또는 git worktree 어떤 경우든. 예측 가능한 포트를 선호하는 단일 인스턴스 개발에는 일반 &lt;code&gt;aspire run&lt;/code&gt;이 여전히 잘 작동합니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;격리 모드는 실제적이고 점점 더 흔해지는 문제를 해결하는 작은 기능입니다. AI 지원 개발이 더 많은 병렬 워크플로우 — 다중 에이전트, 다중 worktree, 다중 컨텍스트 — 로 우리를 밀어붙이는 만큼, 포트 경쟁 없이 또 다른 인스턴스를 간단히 띄울 수 있는 능력은 필수적입니다.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/aspire/aspire-isolated-mode-parallel-development/"&gt;전체 포스트&lt;/a&gt;에서 모든 기술적 세부사항을 확인하고, &lt;code&gt;aspire update --self&lt;/code&gt;로 13.2를 받아 시도해 보세요.&lt;/p&gt;</content:encoded></item><item><title>Azure Functions의 MCP 서버를 Foundry 에이전트에 연결하는 방법</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/foundry-agents-mcp-servers-azure-functions/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/foundry-agents-mcp-servers-azure-functions/</guid><description>MCP 서버를 한 번 구축하고 Azure Functions에 배포한 다음, 적절한 인증으로 Microsoft Foundry 에이전트에 연결하세요. 도구는 어디서나 작동합니다 — VS Code, Cursor, 그리고 이제 엔터프라이즈 AI 에이전트에서도.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/foundry-agents-mcp-servers-azure-functions/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;MCP 생태계에서 제가 좋아하는 점이 있습니다: 서버를 한 번 구축하면 어디서나 작동한다는 것입니다. VS Code, Visual Studio, Cursor, ChatGPT — 모든 MCP 클라이언트가 여러분의 도구를 발견하고 사용할 수 있습니다. 이제 Microsoft가 그 목록에 또 다른 소비자를 추가하고 있습니다: Foundry 에이전트입니다.&lt;/p&gt;
&lt;p&gt;Azure SDK 팀의 Lily Ma가 Azure Functions에 배포된 MCP 서버를 Microsoft Foundry 에이전트에 연결하는 &lt;a href="https://devblogs.microsoft.com/azure-sdk/give-your-foundry-agent-custom-tools-with-mcp-servers-on-azure-functions/"&gt;실용 가이드를 발표&lt;/a&gt;했습니다. 이미 MCP 서버가 있다면 순수한 부가가치입니다 — 재구축이 필요 없습니다.&lt;/p&gt;
&lt;h2 id="이-조합이-합리적인-이유"&gt;이 조합이 합리적인 이유&lt;/h2&gt;
&lt;p&gt;Azure Functions는 MCP 서버 호스팅을 위한 확장 가능한 인프라, 기본 제공 인증, 서버리스 과금을 제공합니다. Microsoft Foundry는 추론하고, 계획하고, 행동할 수 있는 AI 에이전트를 제공합니다. 둘을 연결하면 커스텀 도구 — 데이터베이스 쿼리, 비즈니스 API 호출, 검증 로직 실행 — 가 엔터프라이즈 AI 에이전트가 자율적으로 발견하고 사용할 수 있는 기능이 됩니다.&lt;/p&gt;
&lt;p&gt;핵심 포인트: MCP 서버는 그대로 유지됩니다. Foundry를 또 다른 소비자로 추가하는 것뿐입니다. VS Code 설정에서 작동하는 동일한 도구가 이제 팀이나 고객이 상호작용하는 AI 에이전트를 구동합니다.&lt;/p&gt;
&lt;h2 id="인증-옵션"&gt;인증 옵션&lt;/h2&gt;
&lt;p&gt;여기서 이 글이 진정한 가치를 제공합니다. 시나리오에 따른 네 가지 인증 방법:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;방법&lt;/th&gt;
&lt;th&gt;사용 사례&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;키 기반&lt;/strong&gt; (기본)&lt;/td&gt;
&lt;td&gt;개발 또는 Entra 인증 없는 서버&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft Entra&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;관리 ID를 사용한 프로덕션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OAuth 아이덴티티 패스스루&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;각 사용자가 개별 인증하는 프로덕션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;인증 없음&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;개발/테스트 또는 공개 데이터만&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;프로덕션에서는 에이전트 ID를 사용한 Microsoft Entra가 권장 경로입니다. OAuth 아이덴티티 패스스루는 사용자 컨텍스트가 중요할 때 사용합니다 — 에이전트가 사용자에게 로그인을 요청하고, 각 요청이 사용자 자신의 토큰을 전달합니다.&lt;/p&gt;
&lt;h2 id="설정하기"&gt;설정하기&lt;/h2&gt;
&lt;p&gt;대략적인 흐름:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;MCP 서버를 Azure Functions에 배포&lt;/strong&gt; — &lt;a href="https://github.com/Azure-Samples/remote-mcp-functions-dotnet"&gt;.NET&lt;/a&gt;, Python, TypeScript, Java 샘플 제공&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;함수 앱에서 기본 제공 MCP 인증 활성화&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;엔드포인트 URL 가져오기&lt;/strong&gt; — &lt;code&gt;https://&amp;lt;FUNCTION_APP_NAME&amp;gt;.azurewebsites.net/runtime/webhooks/mcp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Foundry에 MCP 서버를 도구로 추가&lt;/strong&gt; — 포털에서 에이전트로 이동, 새 MCP 도구 추가, 엔드포인트와 자격 증명 제공&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;그런 다음 Agent Builder 플레이그라운드에서 도구 중 하나를 트리거할 프롬프트를 보내 테스트합니다.&lt;/p&gt;
&lt;h2 id="제-의견"&gt;제 의견&lt;/h2&gt;
&lt;p&gt;여기서의 조합성 이야기는 정말 강력해지고 있습니다. .NET(또는 Python, TypeScript, Java)으로 MCP 서버를 한 번 구축하고, Azure Functions에 배포하면, 모든 MCP 호환 클라이언트가 사용할 수 있습니다 — 코딩 도구, 채팅 앱, 그리고 이제 엔터프라이즈 AI 에이전트. 실제로 작동하는 &amp;ldquo;한 번 작성, 어디서나 사용&amp;rdquo; 패턴입니다.&lt;/p&gt;
&lt;p&gt;특히 .NET 개발자에게 &lt;a href="https://github.com/Azure-Samples/remote-mcp-functions-dotnet"&gt;Azure Functions MCP 확장&lt;/a&gt;이 이를 간단하게 만들어줍니다. 도구를 Azure Functions로 정의하고, 배포하면, Azure Functions가 제공하는 모든 보안과 확장성을 갖춘 프로덕션 등급의 MCP 서버를 갖게 됩니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;Azure Functions에서 MCP 도구를 실행하고 있다면, Foundry 에이전트에 연결하는 것은 빠른 성과입니다 — 커스텀 도구가 적절한 인증을 갖춘 엔터프라이즈 AI 기능이 되며, 서버 자체의 코드 변경은 없습니다.&lt;/p&gt;
&lt;p&gt;각 인증 방법에 대한 단계별 안내는 &lt;a href="https://devblogs.microsoft.com/azure-sdk/give-your-foundry-agent-custom-tools-with-mcp-servers-on-azure-functions/"&gt;전체 가이드&lt;/a&gt;를, 프로덕션 설정에 대해서는 &lt;a href="https://learn.microsoft.com/azure/azure-functions/functions-mcp-foundry-tools?tabs=entra%2Cmcp-extension%2Cfoundry"&gt;상세 문서&lt;/a&gt;를 확인하세요.&lt;/p&gt;</content:encoded></item><item><title>GitHub Copilot의 모더나이제이션 평가는 아직 사용하지 않고 있는 최고의 마이그레이션 도구</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/dotnet-modernization-assessment-github-copilot/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/dotnet-modernization-assessment-github-copilot/</guid><description>GitHub Copilot의 모더나이제이션 확장은 단순히 코드 변경을 제안하는 것이 아니라, 실행 가능한 이슈, Azure 대상 비교, 협업 워크플로가 포함된 완전한 마이그레이션 평가를 생성합니다. 평가 문서가 모든 것의 핵심인 이유를 설명합니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/dotnet-modernization-assessment-github-copilot/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;레거시 .NET Framework 앱을 최신 .NET으로 마이그레이션하는 것은 모두가 해야 한다는 것을 알지만 아무도 시작하고 싶어하지 않는 작업 중 하나입니다. 단순히 &amp;ldquo;대상 프레임워크 변경&amp;quot;으로 끝나지 않습니다. 사라진 API, 더 이상 존재하지 않는 패키지, 완전히 다르게 작동하는 호스팅 모델, 그리고 무엇을 컨테이너화하고, 무엇을 다시 작성하고, 무엇을 그대로 둘지에 대한 수백만 가지 작은 결정이 있습니다.&lt;/p&gt;
&lt;p&gt;Jeffrey Fritz가 &lt;a href="https://devblogs.microsoft.com/dotnet/your-migrations-source-of-truth-the-modernization-assessment/"&gt;GitHub Copilot의 모더나이제이션 평가에 대한 심층 분석&lt;/a&gt;을 발표했는데, 솔직히? .NET에서 본 최고의 마이그레이션 도구입니다. 코드 생성 때문이 아닙니다 — 그건 이제 기본입니다. 생성하는 평가 문서 때문입니다.&lt;/p&gt;
&lt;h2 id="단순한-코드-제안-엔진이-아닙니다"&gt;단순한 코드 제안 엔진이 아닙니다&lt;/h2&gt;
&lt;p&gt;VS Code 확장은 &lt;strong&gt;평가 → 계획 → 실행&lt;/strong&gt; 모델을 따릅니다. 평가 단계는 전체 코드베이스를 분석하고 모든 것을 캡처하는 구조화된 문서를 생성합니다: 무엇을 변경해야 하는지, 어떤 Azure 리소스를 프로비저닝해야 하는지, 어떤 배포 모델을 사용해야 하는지. 이후의 모든 것 — Infrastructure as Code, 컨테이너화, 배포 매니페스트 — 은 평가 결과에서 흘러나옵니다.&lt;/p&gt;
&lt;p&gt;평가는 프로젝트의 &lt;code&gt;.github/modernize/assessment/&lt;/code&gt;에 저장됩니다. 각 실행은 독립적인 보고서를 생성하므로 이력을 쌓아가며 이슈를 수정함에 따라 마이그레이션 태세가 어떻게 발전하는지 추적할 수 있습니다.&lt;/p&gt;
&lt;h2 id="두-가지-시작-방법"&gt;두 가지 시작 방법&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;권장 평가&lt;/strong&gt; — 빠른 경로. 큐레이션된 도메인(Java/.NET 업그레이드, 클라우드 준비, 보안)에서 선택하고 구성을 건드리지 않고도 의미 있는 결과를 얻습니다. 앱의 현재 상태를 처음 확인하기에 좋습니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;사용자 정의 평가&lt;/strong&gt; — 표적화된 경로. 분석할 내용을 정확히 구성: 대상 컴퓨팅(App Service, AKS, Container Apps), 대상 OS, 컨테이너화 분석. 여러 Azure 대상을 선택하여 마이그레이션 접근 방식을 나란히 비교합니다.&lt;/p&gt;
&lt;p&gt;그 비교 뷰는 정말 유용합니다. App Service에서 필수 이슈가 3개인 앱이 AKS에서는 7개일 수 있습니다. 둘 다 보는 것은 마이그레이션 경로를 결정하기 전에 호스팅 결정을 내리는 데 도움이 됩니다.&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;필수&lt;/strong&gt; — 수정해야 하며, 그렇지 않으면 마이그레이션 실패&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;잠재적&lt;/strong&gt; — 마이그레이션에 영향을 줄 수 있으며, 인간의 판단이 필요&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;선택적&lt;/strong&gt; — 권장 개선 사항, 마이그레이션을 차단하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;그리고 각 이슈는 영향받는 파일과 줄 번호에 링크되고, 무엇이 잘못되었고 왜 대상 플랫폼에 중요한지에 대한 상세한 설명을 제공하며, 구체적인 수정 단계를 제시하고(&amp;ldquo;이걸 고쳐&amp;quot;가 아닌), 공식 문서 링크를 포함합니다.&lt;/p&gt;
&lt;p&gt;개별 이슈를 개발자에게 전달할 수 있으며, 그들은 조치에 필요한 모든 것을 갖추고 있습니다. 이것이 &amp;ldquo;문제가 있다&amp;quot;고 알려주는 도구와 &amp;ldquo;해결 방법&amp;quot;을 알려주는 도구의 차이입니다.&lt;/p&gt;
&lt;h2 id="다루는-업그레이드-경로"&gt;다루는 업그레이드 경로&lt;/h2&gt;
&lt;p&gt;.NET 구체적으로:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.NET Framework → .NET 10&lt;/li&gt;
&lt;li&gt;ASP.NET → ASP.NET Core&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;각 업그레이드 경로에는 어떤 API가 제거되었는지, 어떤 패턴에 직접적인 등가물이 없는지, 어떤 보안 이슈에 주의가 필요한지 아는 탐지 규칙이 있습니다.&lt;/p&gt;
&lt;p&gt;여러 앱을 관리하는 팀을 위해 다중 레포 배치 평가를 지원하는 CLI도 있습니다 — 모든 레포를 클론하고, 전부 평가하고, 앱별 보고서와 통합된 포트폴리오 뷰를 얻을 수 있습니다.&lt;/p&gt;
&lt;h2 id="제-의견"&gt;제 의견&lt;/h2&gt;
&lt;p&gt;레거시 .NET Framework 앱을 보유하고 있다면(솔직히, 대부분의 엔터프라이즈 팀이 그렇습니다), 이것이 시작해야 할 &lt;em&gt;바로 그&lt;/em&gt; 도구입니다. 평가 문서만으로도 시간 투자의 가치가 있습니다 — 모호한 &amp;ldquo;현대화해야 한다&amp;quot;를 명확한 전진 경로가 있는 구체적이고 우선순위가 매겨진 작업 항목 목록으로 변환합니다.&lt;/p&gt;
&lt;p&gt;협업 워크플로도 영리합니다: 평가를 내보내고, 팀과 공유하고, 재실행 없이 가져옵니다. 의사결정자가 도구를 실행하는 사람이 아닌 아키텍처 리뷰? 커버됩니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;GitHub Copilot의 모더나이제이션 평가는 .NET 마이그레이션을 무섭고 정의되지 않은 프로젝트에서 구조화되고 추적 가능한 프로세스로 변환합니다. 권장 평가로 시작하여 현재 위치를 확인한 다음, 사용자 정의 평가로 Azure 대상을 비교하고 마이그레이션 계획을 수립하세요.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/your-migrations-source-of-truth-the-modernization-assessment/"&gt;전체 워크스루&lt;/a&gt;를 읽고 &lt;a href="https://aka.ms/ghcp-appmod/vscode-ext"&gt;VS Code 확장&lt;/a&gt;을 받아 자신의 코드베이스에서 사용해 보세요.&lt;/p&gt;</content:encoded></item><item><title>MCP Apps에 Fluent API 도입 — .NET에서 3단계로 풍부한 AI 도구 UI 구축</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/mcp-fluent-api-azure-functions-dotnet/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/mcp-fluent-api-azure-functions-dotnet/</guid><description>Azure Functions의 MCP Apps용 새로운 Fluent 구성 API를 사용하면 몇 줄의 코드만으로 모든 .NET MCP 도구를 뷰, 권한, CSP 정책이 포함된 완전한 앱으로 변환할 수 있습니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/mcp-fluent-api-azure-functions-dotnet/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;MCP 도구는 AI 에이전트에게 기능을 부여하는 데 훌륭합니다. 하지만 도구가 사용자에게 무언가를 보여줘야 한다면요? 대시보드, 폼, 인터랙티브 시각화 같은 것들이요. 바로 여기서 MCP Apps가 등장하며, 이제 훨씬 더 쉽게 만들 수 있게 되었습니다.&lt;/p&gt;
&lt;p&gt;Azure SDK 팀의 Lilian Kasem이 .NET Azure Functions의 MCP Apps를 위한 &lt;a href="https://devblogs.microsoft.com/azure-sdk/mcp-as-easy-as-1-2-3-introducing-the-fluent-api-for-mcp-apps/"&gt;새로운 Fluent 구성 API를 발표&lt;/a&gt;했습니다. 왜 처음부터 이렇게 간단하지 않았을까 싶은 그런 개발자 경험 개선입니다.&lt;/p&gt;
&lt;h2 id="mcp-apps란"&gt;MCP Apps란?&lt;/h2&gt;
&lt;p&gt;MCP Apps는 Model Context Protocol을 확장하여 도구가 자체 UI 뷰, 정적 에셋, 보안 제어를 가질 수 있게 합니다. 단순히 텍스트를 반환하는 대신 MCP 도구가 완전한 HTML 경험을 렌더링할 수 있습니다 — 인터랙티브 대시보드, 데이터 시각화, 구성 폼 — 모두 AI 에이전트가 호출 가능하고 MCP 클라이언트를 통해 사용자에게 표시됩니다.&lt;/p&gt;
&lt;p&gt;문제는 이 모든 것을 수동으로 연결하려면 MCP 스펙을 깊이 이해해야 했다는 것입니다: &lt;code&gt;ui://&lt;/code&gt; URI, 특수 MIME 타입, 도구와 리소스 간의 메타데이터 조정. 어렵지는 않지만 번거로웠습니다.&lt;/p&gt;
&lt;h2 id="fluent-api-3단계"&gt;Fluent API 3단계&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1단계: 함수를 정의합니다.&lt;/strong&gt; 표준 Azure Functions MCP 도구:&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="na"&gt;[Function(nameof(HelloApp))]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;HelloApp&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="na"&gt; [McpToolTrigger(&amp;#34;HelloApp&amp;#34;, &amp;#34;A simple MCP App that says hello.&amp;#34;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ToolInvocationContext&lt;/span&gt; &lt;span class="n"&gt;context&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="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Hello from app&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="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;2단계: MCP App으로 승격시킵니다.&lt;/strong&gt; 프로그램 시작 시:&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="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigureMcpTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;HelloApp&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsMcpApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;assets/hello-app.html&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello App&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithPermissions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpAppPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClipboardWrite&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;McpAppPermissions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClipboardRead&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCsp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;csp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowBaseUri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://www.microsoft.com&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://www.microsoft.com&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="p"&gt;}));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;3단계: HTML 뷰를 추가합니다.&lt;/strong&gt; 필요한 UI로 &lt;code&gt;assets/hello-app.html&lt;/code&gt;을 생성합니다.&lt;/p&gt;
&lt;p&gt;끝입니다. Fluent API가 MCP 프로토콜의 모든 배관 작업을 처리합니다 — 합성 리소스 함수 생성, 올바른 MIME 타입 설정, 도구와 뷰를 연결하는 메타데이터 주입.&lt;/p&gt;
&lt;h2 id="api-설계가-훌륭합니다"&gt;API 설계가 훌륭합니다&lt;/h2&gt;
&lt;p&gt;특히 마음에 드는 점 몇 가지:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;뷰 소스가 유연합니다.&lt;/strong&gt; 디스크의 파일에서 HTML을 제공하거나, 독립 배포를 위해 리소스를 어셈블리에 직접 포함할 수 있습니다:&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="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpViewSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;assets/my-view.html&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpViewSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromEmbeddedResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;MyApp.Resources.view.html&amp;#34;&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;strong&gt;CSP가 조합 가능합니다.&lt;/strong&gt; 최소 권한 원칙에 따라 앱에 필요한 출처를 명시적으로 허용합니다. &lt;code&gt;WithCsp&lt;/code&gt;를 여러 번 호출하면 출처가 누적됩니다:&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithCsp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;csp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://api.example.com&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadResourcesFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://cdn.example.com&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://youtube.com&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="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;가시성 제어.&lt;/strong&gt; 도구를 LLM에만 표시, 호스트 UI에만 표시, 또는 둘 다에 표시할 수 있습니다. UI만 렌더링하고 모델에서 호출되지 않아야 하는 도구를 원하시나요? 간단합니다:&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithVisibility&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;McpVisibility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// UI-only, hidden from the model&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="시작하기"&gt;시작하기&lt;/h2&gt;
&lt;p&gt;프리뷰 패키지를 추가합니다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Mcp --version 1.5.0-preview.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;이미 Azure Functions로 MCP 도구를 만들고 있다면 패키지 업데이트만 하면 됩니다. 개념이 처음이라면 &lt;a href="https://learn.microsoft.com/azure/azure-functions/scenario-mcp-apps?tabs=bash%2Clinux&amp;amp;pivots=programming-language-csharp"&gt;MCP Apps 빠른 시작&lt;/a&gt;이 가장 좋은 출발점입니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;MCP Apps는 AI 도구 분야에서 가장 흥미로운 발전 중 하나입니다 — 단순히 &lt;em&gt;무언가를 하는&lt;/em&gt; 것이 아니라 사용자에게 &lt;em&gt;무언가를 보여줄 수 있는&lt;/em&gt; 도구. Fluent API는 프로토콜 복잡성을 제거하고 중요한 것에 집중하게 해줍니다: 도구의 로직과 UI.&lt;/p&gt;
&lt;p&gt;완전한 API 리퍼런스와 예제는 &lt;a href="https://devblogs.microsoft.com/azure-sdk/mcp-as-easy-as-1-2-3-introducing-the-fluent-api-for-mcp-apps/"&gt;전체 게시물&lt;/a&gt;을 읽어보세요.&lt;/p&gt;</content:encoded></item><item><title>C# 15에 유니온 타입 도입 — 우리가 원하던 바로 그것</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/</link><pubDate>Sun, 05 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/</guid><description>C# 15가 union 키워드를 도입합니다 — 컴파일러가 강제하는 판별 공용체와 완전한 패턴 매칭. 어떤 모습인지, 왜 중요한지, 그리고 오늘 바로 시도하는 방법을 알아봅니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문을 보시려면 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/"&gt;여기를 클릭하세요&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;바로 이것을 기다려왔습니다. C# 15가 &lt;code&gt;union&lt;/code&gt; 키워드를 도입했습니다 — 컴파일러가 강제하는 완전한 패턴 매칭을 갖춘 진정한 판별 공용체입니다. F#의 판별 공용체나 Rust의 enum을 부러워한 적이 있다면, 이것이 왜 중요한지 정확히 알 것입니다.&lt;/p&gt;
&lt;p&gt;Bill Wagner가 .NET 블로그에 &lt;a href="https://devblogs.microsoft.com/dotnet/csharp-15-union-types/"&gt;심층 분석을 게시했는데&lt;/a&gt;, 솔직히? 디자인이 깔끔하고, 실용적이며, 매우 C#답습니다. 실제로 무엇이 있는지, 그리고 왜 첫눈에 보이는 것보다 더 큰 의미가 있는지 보여드리겠습니다.&lt;/p&gt;
&lt;h2 id="유니온이-해결하는-문제"&gt;유니온이 해결하는 문제&lt;/h2&gt;
&lt;p&gt;C# 15 이전에는 메서드에서 &amp;ldquo;여러 가능한 타입 중 하나&amp;quot;를 반환하는 것이 항상 타협이었습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;object&lt;/code&gt;&lt;/strong&gt; — 제약 없음, 컴파일러 도움 없음, 어디서나 방어적 캐스팅&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;마커 인터페이스&lt;/strong&gt; — 더 낫지만, 누구나 구현 가능. 컴파일러는 집합이 완전하다고 판단할 수 없음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;추상 기본 클래스&lt;/strong&gt; — 같은 문제, 게다가 타입들이 공통 조상이 필요함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 중 어느 것도 실제로 원하는 것을 제공하지 못합니다: 컴파일러가 모든 케이스를 처리했음을 보장하는 닫힌 타입 집합. 유니온 타입이 바로 그것을 합니다.&lt;/p&gt;
&lt;h2 id="구문은-아름다울-정도로-간결합니다"&gt;구문은 아름다울 정도로 간결합니다&lt;/h2&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="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&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="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&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="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Bird&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bird&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;Pet&lt;/code&gt;은 &lt;code&gt;Cat&lt;/code&gt;, &lt;code&gt;Dog&lt;/code&gt;, 또는 &lt;code&gt;Bird&lt;/code&gt;를 담을 수 있습니다. 암시적 변환이 자동으로 생성됩니다:&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="n"&gt;Pet&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rex&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;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Dog { Name = Rex }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;그리고 여기가 마법입니다 — 컴파일러가 완전한 매칭을 강제합니다:&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;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;Dog&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&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;Cat&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&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;Bird&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&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="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;_&lt;/code&gt;가 필요 없습니다. 컴파일러는 이 switch가 모든 가능한 케이스를 커버한다는 것을 알고 있습니다. 나중에 유니온에 네 번째 타입을 추가하면, 그것을 처리하지 않는 모든 switch 식이 경고를 생성합니다. 누락된 케이스가 런타임이 아니라 빌드 시점에 잡힙니다.&lt;/p&gt;
&lt;h2 id="실용적으로-빛나는-곳"&gt;실용적으로 빛나는 곳&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Pet&lt;/code&gt; 예제는 귀엽지만, 여기서부터가 유니온이 실제 코드에서 진짜로 빛나는 부분입니다.&lt;/p&gt;
&lt;h3 id="다양한-형태를-반환하는-api-응답"&gt;다양한 형태를 반환하는 API 응답&lt;/h3&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;ApiResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ValidationFailure&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;이제 모든 소비자가 성공, 오류, 유효성 검증 실패를 처리하도록 강제됩니다. &amp;ldquo;에러 케이스 체크를 깜빡했다&amp;rdquo; 버그는 더 이상 없습니다.&lt;/p&gt;
&lt;h3 id="단일-값-또는-컬렉션"&gt;단일 값 또는 컬렉션&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;OneOrMore&amp;lt;T&amp;gt;&lt;/code&gt; 패턴은 유니온이 헬퍼 메서드를 가진 본문을 가질 수 있음을 보여줍니다:&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AsEnumerable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;T&lt;/span&gt; &lt;span class="n"&gt;single&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;single&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;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple&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="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&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="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;/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="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tags&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;moreTags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;csharp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;unions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;preview&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsEnumerable&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;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$&amp;#34;[{tag}] &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="c1"&gt;// [dotnet]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="관련-없는-타입들의-합성"&gt;관련 없는 타입들의 합성&lt;/h3&gt;
&lt;p&gt;이것이 전통적 계층 구조에 대한 킬러 기능입니다. 공통점이 전혀 없는 타입들을 유니온할 수 있습니다 — &lt;code&gt;string&lt;/code&gt;과 &lt;code&gt;Exception&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;와 &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;. 공통 조상이 필요 없습니다.&lt;/p&gt;
&lt;h2 id="기존-라이브러리를-위한-커스텀-유니온"&gt;기존 라이브러리를 위한 커스텀 유니온&lt;/h2&gt;
&lt;p&gt;똑똑한 디자인 선택이 있습니다: 기본 패턴(케이스 타입에 대한 public 생성자와 &lt;code&gt;Value&lt;/code&gt; 프로퍼티)을 따르기만 하면, &lt;code&gt;[Union]&lt;/code&gt; 어트리뷰트가 있는 모든 클래스나 구조체가 유니온 타입으로 인식됩니다. 이미 유니온과 유사한 타입을 제공하는 OneOf 같은 라이브러리들이 내부를 재작성하지 않고도 컴파일러 지원에 옵트인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;값 타입을 사용하는 성능에 민감한 시나리오에서는 라이브러리가 &lt;code&gt;HasValue&lt;/code&gt;와 &lt;code&gt;TryGetValue&lt;/code&gt; 메서드로 박싱 없는 접근 패턴을 구현할 수 있습니다.&lt;/p&gt;
&lt;h2 id="더-큰-그림"&gt;더 큰 그림&lt;/h2&gt;
&lt;p&gt;유니온 타입은 C#에 오고 있는 더 넓은 완전성 이야기의 일부입니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;유니온 타입&lt;/strong&gt; — 닫힌 타입 집합에 대한 완전한 매칭 (지금 프리뷰에서 사용 가능)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;닫힌 계층 구조&lt;/strong&gt; — &lt;code&gt;closed&lt;/code&gt; 수정자가 정의 어셈블리 외부의 파생 클래스를 방지 (제안됨)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;닫힌 enum&lt;/strong&gt; — 선언된 멤버 이외의 값 생성을 방지 (제안됨)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이 세 가지 기능이 합쳐지면, C#은 모든 주류 언어 중 가장 포괄적인 타입 안전 패턴 매칭 시스템 중 하나를 갖게 될 것입니다.&lt;/p&gt;
&lt;h2 id="오늘-바로-시도해보세요"&gt;오늘 바로 시도해보세요&lt;/h2&gt;
&lt;p&gt;유니온 타입은 .NET 11 Preview 2에서 사용 가능합니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://dotnet.microsoft.com/download/dotnet"&gt;.NET 11 Preview SDK&lt;/a&gt;를 설치&lt;/li&gt;
&lt;li&gt;프로젝트에서 &lt;code&gt;net11.0&lt;/code&gt;을 타깃으로 설정&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;LangVersion&amp;gt;preview&amp;lt;/LangVersion&amp;gt;&lt;/code&gt;을 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;한 가지 주의사항: Preview 2에서는 런타임에 아직 포함되어 있지 않으므로 프로젝트에서 &lt;code&gt;UnionAttribute&lt;/code&gt;와 &lt;code&gt;IUnion&lt;/code&gt;을 선언해야 합니다. docs 레포에서 &lt;a href="https://github.com/dotnet/docs/blob/e68b5dd1e557b53c45ca43e61b013bc919619fb9/docs/csharp/language-reference/builtin-types/snippets/unions/RuntimePolyfill.cs"&gt;RuntimePolyfill.cs&lt;/a&gt;를 가져오거나, 다음을 추가하세요:&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="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;System.Runtime.CompilerServices&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="na"&gt; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; AllowMultiple = false)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnionAttribute&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Attribute&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IUnion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="kt"&gt;object?&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&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="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;유니온 타입은 그것 없이 어떻게 지냈는지 의아하게 만드는 기능 중 하나입니다. 컴파일러가 강제하는 완전한 매칭, 깔끔한 구문, 제네릭 지원, 기존 패턴 매칭과의 통합 — 우리가 요청해온 모든 것이 C#의 방식으로 구현되었습니다.&lt;/p&gt;
&lt;p&gt;.NET 11 Preview 2에서 시도하고, 이것저것 부숴보고, &lt;a href="https://github.com/dotnet/csharplang/discussions/9663"&gt;GitHub에서 피드백을 공유하세요&lt;/a&gt;. 이것은 프리뷰이며, C# 팀은 적극적으로 듣고 있습니다. 여러분의 엣지 케이스와 디자인 피드백이 최종 릴리스를 형성할 것입니다.&lt;/p&gt;
&lt;p&gt;전체 언어 참조는 &lt;a href="https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/union"&gt;유니온 타입 문서&lt;/a&gt;와 &lt;a href="https://learn.microsoft.com/dotnet/csharp/language-reference/proposals/unions"&gt;기능 사양&lt;/a&gt;을 확인하세요.&lt;/p&gt;</content:encoded></item><item><title>Aspire 13.2에 문서 CLI가 탑재 — AI 에이전트도 사용할 수 있습니다</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-docs-cli-ai-skills/</link><pubDate>Sat, 04 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-docs-cli-ai-skills/</guid><description>.NET Aspire 13.2에 aspire docs가 추가되었습니다. 터미널을 떠나지 않고 공식 문서를 검색, 탐색, 읽을 수 있는 CLI입니다. AI 에이전트의 도구로도 작동합니다. 이것이 왜 중요한지 알려드립니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-docs-cli-ai-skills/"&gt;여기를 클릭&lt;/a&gt;하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Aspire AppHost 깊숙이 들어가서 통합을 연결하는 중에, Redis 통합이 정확히 어떤 파라미터를 기대하는지 확인해야 하는 그 순간을 아시죠? Alt-Tab으로 브라우저로 전환하고, aspire.dev를 뒤지고, API 문서를 눈을 가늘게 뜨고 보다가, 다시 에디터로 돌아옵니다. 컨텍스트를 잃었고, 플로우가 끊겼습니다.&lt;/p&gt;
&lt;p&gt;Aspire 13.2가 바로 &lt;a href="https://devblogs.microsoft.com/aspire/aspire-docs-in-your-terminal/"&gt;그 해결책을 출시했습니다&lt;/a&gt;. &lt;code&gt;aspire docs&lt;/code&gt; CLI를 사용하면 터미널에서 직접 Aspire 공식 문서를 검색하고, 탐색하고, 읽을 수 있습니다. 그리고 재사용 가능한 서비스에 기반하고 있어서, AI 에이전트와 스킬이 같은 명령어를 사용해 문서를 조회할 수 있습니다. 존재하지 않는 API를 환각하는 대신에요.&lt;/p&gt;
&lt;h2 id="이것이-실제로-해결하는-문제"&gt;이것이 실제로 해결하는 문제&lt;/h2&gt;
&lt;p&gt;David Pine이 원문에서 정확히 짚었습니다: AI 에이전트는 개발자가 Aspire 앱을 구축하는 것을 돕는 데 &lt;em&gt;끔찍했습니다&lt;/em&gt;. &lt;code&gt;aspire run&lt;/code&gt; 대신 &lt;code&gt;dotnet run&lt;/code&gt;을 추천하고, aspire.dev에 있는 문서에 대해 learn.microsoft.com을 참조하고, 오래된 NuGet 패키지를 제안하고, 그리고 — 개인적으로 가장 좋아하는 — 존재하지 않는 API를 환각했습니다.&lt;/p&gt;
&lt;p&gt;왜 그럴까요? Aspire가 폴리글랏이 된 것보다 .NET 전용이었던 기간이 훨씬 길었고, LLM은 최신 기능보다 앞선 학습 데이터로 작동하기 때문입니다. AI 에이전트에게 현재 문서를 실제로 조회할 수 있는 능력을 주면, 추측을 멈추고 유용해지기 시작합니다.&lt;/p&gt;
&lt;h2 id="세-가지-명령어-브라우저-탭은-제로"&gt;세 가지 명령어, 브라우저 탭은 제로&lt;/h2&gt;
&lt;p&gt;CLI는 상쾌할 정도로 간단합니다:&lt;/p&gt;
&lt;h3 id="모든-문서-나열"&gt;모든 문서 나열&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs list
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;aspire.dev에서 사용 가능한 모든 문서 페이지를 반환합니다. 기계가 읽을 수 있는 출력이 필요하세요? &lt;code&gt;--format Json&lt;/code&gt;을 추가하세요.&lt;/p&gt;
&lt;h3 id="주제-검색"&gt;주제 검색&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs search &lt;span class="s2"&gt;&amp;#34;redis&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;가중 관련성 점수로 제목과 콘텐츠 모두를 검색합니다. 내부적으로 문서 도구를 구동하는 것과 같은 검색 엔진입니다. 제목, 슬러그, 관련성 점수가 포함된 순위별 결과를 얻을 수 있습니다.&lt;/p&gt;
&lt;h3 id="전체-페이지-읽기-또는-한-섹션만"&gt;전체 페이지 읽기 (또는 한 섹션만)&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs get redis-integration
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;전체 페이지를 마크다운으로 터미널에 스트리밍합니다. 한 섹션만 필요하세요?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs get redis-integration --section &lt;span class="s2"&gt;&amp;#34;Add Redis resource&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;외과적 정밀도. 500줄을 스크롤할 필요 없습니다. 필요한 부분만.&lt;/p&gt;
&lt;h2 id="ai-에이전트-관점"&gt;AI 에이전트 관점&lt;/h2&gt;
&lt;p&gt;AI 도구로 개발하는 우리 개발자들에게 흥미로워지는 부분입니다. 같은 &lt;code&gt;aspire docs&lt;/code&gt; 명령어가 스킬, MCP 서버, 또는 간단한 CLI 래퍼를 통해 AI 에이전트의 도구로 작동합니다.&lt;/p&gt;
&lt;p&gt;AI 어시스턴트가 오래된 학습 데이터를 기반으로 Aspire API를 지어내는 대신, &lt;code&gt;aspire docs search &amp;quot;postgres&amp;quot;&lt;/code&gt;를 호출하고, 공식 통합 문서를 찾고, 올바른 페이지를 읽고, 문서화된 접근 방식을 제공할 수 있습니다. 실시간이고 최신인 문서 — 모델이 6개월 전에 기억한 것이 아닙니다.&lt;/p&gt;
&lt;p&gt;이 뒤의 아키텍처는 의도적입니다. Aspire 팀은 일회성 통합 대신 재사용 가능한 서비스(&lt;code&gt;IDocsIndexService&lt;/code&gt;, &lt;code&gt;IDocsSearchService&lt;/code&gt;, &lt;code&gt;IDocsFetcher&lt;/code&gt;, &lt;code&gt;IDocsCache&lt;/code&gt;)를 구축했습니다. 이는 같은 검색 엔진이 터미널의 사람, 에디터의 AI 에이전트, CI 파이프라인의 자동화를 위해 작동한다는 의미입니다.&lt;/p&gt;
&lt;h2 id="실제-시나리오"&gt;실제 시나리오&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;터미널에서 빠른 조회:&lt;/strong&gt; 파일 세 개 깊이에 있고 Redis 설정 파라미터가 필요합니다. 두 개의 명령어, 90초, 다시 작업으로:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs search &lt;span class="s2"&gt;&amp;#34;redis&amp;#34;&lt;/span&gt; --limit &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs get redis-integration --section &lt;span class="s2"&gt;&amp;#34;Configuration&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;AI 지원 개발:&lt;/strong&gt; VS Code 스킬이 CLI 명령어를 래핑합니다. &amp;ldquo;내 AppHost에 PostgreSQL 데이터베이스를 추가해&amp;quot;라고 물으면 에이전트가 답변하기 전에 실제 문서를 조회합니다. 환각 없음.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CI/CD 검증:&lt;/strong&gt; 파이프라인이 공식 문서에 대해 AppHost 설정을 프로그래밍 방식으로 검증합니다. &lt;code&gt;--format Json&lt;/code&gt; 출력은 &lt;code&gt;jq&lt;/code&gt; 및 다른 도구와 깔끔하게 연결됩니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;커스텀 지식 베이스:&lt;/strong&gt; 자체 AI 도구를 구축하고 있나요? 구조화된 JSON 출력을 지식 베이스에 직접 파이프:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aspire docs search &lt;span class="s2"&gt;&amp;#34;monitoring&amp;#34;&lt;/span&gt; --format Json &lt;span class="p"&gt;|&lt;/span&gt; jq &lt;span class="s1"&gt;&amp;#39;[.[] | {slug, title, summary}]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;웹 스크래핑 없음. API 키 없음. 문서 도구가 내부적으로 사용하는 것과 같은 구조화된 데이터.&lt;/p&gt;
&lt;h2 id="문서는-항상-최신-상태"&gt;문서는 항상 최신 상태&lt;/h2&gt;
&lt;p&gt;이것이 제가 가장 높이 평가하는 부분입니다. CLI는 스냅샷을 다운로드하지 않습니다 — ETag 기반 캐싱으로 aspire.dev를 조회합니다. 문서가 업데이트되는 순간, CLI와 그 위에 구축된 모든 스킬이 이를 반영합니다. 오래된 복사본도 없고, &amp;ldquo;하지만 위키에는&amp;hellip;&amp;ldquo;하는 순간도 없습니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;aspire docs&lt;/code&gt;는 실제 문제를 깔끔하게 해결하는 작은 기능 중 하나입니다. 사람은 터미널 네이티브 문서 접근을 얻습니다. AI 에이전트는 추측을 멈추고 실제 문서를 참조할 수 있는 방법을 얻습니다. 그리고 모든 것이 같은 진실의 원천에 의해 뒷받침됩니다.&lt;/p&gt;
&lt;p&gt;.NET Aspire로 개발하고 있고 아직 CLI를 시도해보지 않았다면, &lt;code&gt;aspire docs search &amp;quot;여러분의-주제&amp;quot;&lt;/code&gt; 를 실행하고 어떤 느낌인지 확인해 보세요. 그런 다음 사용 중인 AI 스킬이나 자동화 설정에 이 명령어들을 래핑하는 것을 고려해 보세요 — 여러분의 에이전트가 감사할 것입니다.&lt;/p&gt;
&lt;p&gt;문서 도구가 어떻게 만들어졌는지에 대한 &lt;a href="https://davidpine.dev/posts/aspire-docs-mcp-tools/"&gt;David Pine의 심층 분석&lt;/a&gt;과 모든 세부 사항이 담긴 &lt;a href="https://aspire.dev/reference/cli/commands/aspire-docs/"&gt;공식 CLI 레퍼런스&lt;/a&gt;를 확인해 보세요.&lt;/p&gt;</content:encoded></item><item><title>Microsoft Agent Framework 1.0 출시 — .NET 개발자에게 정말 중요한 것들</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/agent-framework-1-0-production-ready/</link><pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/agent-framework-1-0-production-ready/</guid><description>Microsoft Agent Framework 1.0이 안정적인 API, 멀티 에이전트 오케스트레이션, 모든 주요 AI 제공업체용 커넥터를 갖추고 프로덕션 준비가 완료되었습니다. .NET 개발자로서 알아야 할 내용을 정리했습니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원문은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/agent-framework-1-0-production-ready/"&gt;여기를 클릭&lt;/a&gt;하여 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Semantic Kernel과 AutoGen 초기부터 Agent Framework의 여정을 지켜봐 왔다면, 이번 소식은 의미가 큽니다. Microsoft Agent Framework가 &lt;a href="https://devblogs.microsoft.com/agent-framework/microsoft-agent-framework-version-1-0/"&gt;버전 1.0에 도달&lt;/a&gt;했습니다 — 프로덕션 준비 완료, 안정적인 API, 장기 지원 약속. .NET과 Python 모두에서 사용할 수 있으며, 실제 워크로드를 처리할 준비가 되어 있습니다.&lt;/p&gt;
&lt;p&gt;발표의 소음을 걷어내고 .NET으로 AI 기반 앱을 구축하는 분들에게 중요한 내용에 집중하겠습니다.&lt;/p&gt;
&lt;h2 id="짧은-요약"&gt;짧은 요약&lt;/h2&gt;
&lt;p&gt;Agent Framework 1.0은 기존의 Semantic Kernel과 AutoGen을 하나의 오픈소스 SDK로 통합합니다. 하나의 에이전트 추상화. 하나의 오케스트레이션 엔진. 다수의 AI 제공업체. 엔터프라이즈 패턴을 위한 Semantic Kernel과 연구용 멀티 에이전트 워크플로를 위한 AutoGen 사이를 오갔다면, 이제 그만해도 됩니다. 이것이 유일한 SDK입니다.&lt;/p&gt;
&lt;h2 id="시작하기가-거의-불공평할-정도로-쉽습니다"&gt;시작하기가 거의 불공평할 정도로 쉽습니다&lt;/h2&gt;
&lt;p&gt;.NET에서 작동하는 에이전트 코드입니다:&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="c1"&gt;// dotnet add package Microsoft.Agents.AI.OpenAI --prerelease&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI&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="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Agents.AI.Foundry&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="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Azure.Identity&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&gt;&lt;/span&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;agent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;https://your-project.services.ai.azure.com&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetResponsesClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;gpt-5.3&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;HaikuBot&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;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;You are an upbeat assistant that writes beautifully.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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&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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Write a haiku about shipping 1.0.&amp;#34;&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;이게 전부입니다. 몇 줄의 코드로 Azure Foundry에서 실행되는 AI 에이전트가 완성됩니다. Python 버전도 마찬가지로 간결합니다. 함수 도구, 멀티턴 대화, 스트리밍은 필요할 때 추가하면 됩니다 — API 표면이 이상해지지 않으면서 확장됩니다.&lt;/p&gt;
&lt;h2 id="멀티-에이전트-오케스트레이션--이것이-진짜입니다"&gt;멀티 에이전트 오케스트레이션 — 이것이 진짜입니다&lt;/h2&gt;
&lt;p&gt;단일 에이전트는 데모에는 괜찮지만, 프로덕션 시나리오는 보통 조율이 필요합니다. Agent Framework 1.0은 Microsoft Research와 AutoGen에서 직접 가져온 실전 검증된 오케스트레이션 패턴을 탑재하고 있습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;순차적&lt;/strong&gt; — 에이전트가 순서대로 처리 (작성자 → 검토자 → 편집자)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;동시적&lt;/strong&gt; — 여러 에이전트에게 병렬로 분배하고, 결과를 수렴&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;핸드오프&lt;/strong&gt; — 하나의 에이전트가 의도에 따라 다른 에이전트에게 위임&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;그룹 채팅&lt;/strong&gt; — 여러 에이전트가 논의하고 해결책으로 수렴&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Magentic-One&lt;/strong&gt; — MSR의 연구용 멀티 에이전트 패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;모두 스트리밍, 체크포인팅, 인간 참여 승인, 일시 중지/재개를 지원합니다. 체크포인팅 부분이 중요합니다 — 장시간 실행되는 워크플로가 프로세스 재시작을 견뎌냅니다. Azure Functions로 지속성 있는 워크플로를 구축해 본 .NET 개발자에게는 익숙한 느낌일 겁니다.&lt;/p&gt;
&lt;h2 id="가장-중요한-기능들"&gt;가장 중요한 기능들&lt;/h2&gt;
&lt;p&gt;알아둘 가치가 있는 항목 목록입니다:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;미들웨어 훅.&lt;/strong&gt; ASP.NET Core에 미들웨어 파이프라인이 있는 거 아시죠? 같은 개념인데, 에이전트 실행용입니다. 모든 단계를 가로채서 — 콘텐츠 안전, 로깅, 컴플라이언스 정책을 추가 — 에이전트 프롬프트를 건드리지 않고 할 수 있습니다. 이것이 에이전트를 엔터프라이즈 수준으로 만드는 방법입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;플러거블 메모리.&lt;/strong&gt; 대화 이력, 영속적 키-값 상태, 벡터 기반 검색. 백엔드를 선택하세요: Foundry Agent Service, Mem0, Redis, Neo4j, 또는 직접 구현. 메모리는 상태 없는 LLM 호출을 실제로 컨텍스트를 기억하는 에이전트로 바꿔주는 핵심입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;선언적 YAML 에이전트.&lt;/strong&gt; 에이전트의 지시사항, 도구, 메모리, 오케스트레이션 토폴로지를 버전 관리되는 YAML 파일에 정의합니다. 단일 API 호출로 로드하고 실행합니다. 이것은 코드를 재배포하지 않고 에이전트 동작을 반복하고 싶은 팀에게 게임 체인저입니다.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A2A 및 MCP 지원.&lt;/strong&gt; MCP(Model Context Protocol)는 에이전트가 외부 도구를 동적으로 발견하고 호출할 수 있게 합니다. A2A(Agent-to-Agent 프로토콜)는 크로스 런타임 협업을 가능하게 합니다 — .NET 에이전트가 다른 프레임워크에서 실행되는 에이전트와 조율할 수 있습니다. A2A 1.0 지원은 곧 출시 예정입니다.&lt;/p&gt;
&lt;h2 id="주목할-만한-프리뷰-기능"&gt;주목할 만한 프리뷰 기능&lt;/h2&gt;
&lt;p&gt;1.0에서 프리뷰로 출시된 기능들이 있습니다 — 작동하지만 API가 변경될 수 있습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DevUI&lt;/strong&gt; — 에이전트 실행, 메시지 흐름, 도구 호출을 실시간으로 시각화하는 브라우저 기반 로컬 디버거. Application Insights의 에이전트 추론 버전이라고 생각하면 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub Copilot SDK 및 Claude Code SDK&lt;/strong&gt; — 오케스트레이션 코드에서 직접 Copilot이나 Claude를 에이전트 하네스로 사용합니다. 같은 워크플로에서 코딩 가능한 에이전트를 다른 에이전트와 함께 구성할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent Harness&lt;/strong&gt; — 에이전트에게 셸, 파일 시스템, 메시징 루프에 대한 접근을 제공하는 커스터마이즈 가능한 로컬 런타임. 코딩 에이전트와 자동화 패턴을 떠올려 보세요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skills&lt;/strong&gt; — 에이전트에게 즉시 사용 가능한 구조화된 기능을 제공하는 재사용 가능한 도메인 능력 패키지.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="semantic-kernel-또는-autogen에서-마이그레이션"&gt;Semantic Kernel 또는 AutoGen에서 마이그레이션&lt;/h2&gt;
&lt;p&gt;기존 Semantic Kernel 또는 AutoGen 코드가 있다면, 코드를 분석하고 단계별 마이그레이션 계획을 생성하는 전용 마이그레이션 어시스턴트가 있습니다. &lt;a href="https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-semantic-kernel"&gt;Semantic Kernel 마이그레이션 가이드&lt;/a&gt;와 &lt;a href="https://learn.microsoft.com/en-us/agent-framework/migration-guide/from-autogen"&gt;AutoGen 마이그레이션 가이드&lt;/a&gt;가 모든 과정을 안내해 줍니다.&lt;/p&gt;
&lt;p&gt;RC 패키지를 사용하고 계셨다면, 1.0으로의 업그레이드는 버전 번호만 바꾸면 됩니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;Agent Framework 1.0은 엔터프라이즈 팀이 기다려온 프로덕션 마일스톤입니다. 안정적인 API, 멀티 제공업체 지원, 실제로 대규모에서 작동하는 오케스트레이션 패턴, 그리고 Semantic Kernel과 AutoGen 모두에서의 마이그레이션 경로.&lt;/p&gt;
&lt;p&gt;프레임워크는 &lt;a href="https://github.com/microsoft/agent-framework"&gt;GitHub에서 완전한 오픈소스&lt;/a&gt;이며, &lt;code&gt;dotnet add package Microsoft.Agents.AI&lt;/code&gt;로 오늘 바로 시작할 수 있습니다. &lt;a href="https://learn.microsoft.com/en-us/agent-framework/get-started/"&gt;빠른 시작 가이드&lt;/a&gt;와 &lt;a href="https://github.com/microsoft/agent-framework"&gt;샘플&lt;/a&gt;을 확인해서 직접 경험해 보세요.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;프로덕션에서 안전하게 사용할 수 있다&amp;quot;는 신호를 기다리고 있었다면 — 바로 이것입니다.&lt;/p&gt;</content:encoded></item><item><title>Aspire 13.2 대시보드에 텔레메트리 API가 추가됐다 — 그리고 모든 것이 바뀐다</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-132-dashboard-export-telemetry/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-132-dashboard-export-telemetry/</guid><description>.NET Aspire 13.2가 스마트한 텔레메트리 내보내기, 트레이스와 로그를 위한 프로그래밍 가능한 API, GenAI 시각화 개선을 제공합니다. 디버깅 워크플로에 왜 중요한지 알아보세요.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원본은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/aspire-132-dashboard-export-telemetry/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;.NET Aspire로 분산 앱을 구축해왔다면, 대시보드가 전체 경험에서 가장 훌륭한 부분이라는 걸 이미 알고 있을 겁니다. 모든 트레이스, 로그, 메트릭이 한 곳에 — 외부 Jaeger도 필요 없고, Seq 설정도 필요 없고, &amp;ldquo;다른 터미널 확인해 볼게&amp;rdquo; 같은 순간도 없습니다.&lt;/p&gt;
&lt;p&gt;Aspire 13.2가 이를 크게 개선했습니다. James Newton-King이 &lt;a href="https://devblogs.microsoft.com/aspire/aspire-dashboard-improvements-export-and-telemetry/"&gt;업데이트를 발표&lt;/a&gt;했는데, 솔직히? 텔레메트리 내보내기와 API 기능만으로도 업그레이드할 가치가 있습니다.&lt;/p&gt;
&lt;h2 id="텔레메트리를-제대로-내보내기"&gt;텔레메트리를 제대로 내보내기&lt;/h2&gt;
&lt;p&gt;우리 모두 겪어본 시나리오입니다: 분산 문제를 디버깅하면서 20분간의 설정 끝에 마침내 재현했는데, 이제 팀에게 무슨 일이 있었는지 공유해야 합니다. 이전에는? 스크린샷. 트레이스 ID 복사 붙여넣기. 항상 그러는 것처럼.&lt;/p&gt;
&lt;p&gt;Aspire 13.2는 &lt;strong&gt;로그 및 텔레메트리 관리&lt;/strong&gt; 대화상자를 추가했습니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;모든 텔레메트리 삭제 (재현 시도 전에 유용)&lt;/li&gt;
&lt;li&gt;선택한 텔레메트리를 표준 OTLP/JSON 형식의 ZIP 파일로 내보내기&lt;/li&gt;
&lt;li&gt;나중에 해당 ZIP을 아무 Aspire 대시보드에 다시 가져오기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;마지막 부분이 핵심 기능입니다. 버그를 재현하고, 텔레메트리를 내보내고, 작업 항목에 첨부하면, 팀원이 자신의 대시보드에 가져와서 당신이 본 것과 정확히 같은 것을 볼 수 있습니다. &amp;ldquo;네 컴퓨터에서 재현해볼 수 있어?&amp;ldquo;는 이제 그만.&lt;/p&gt;
&lt;p&gt;개별 트레이스, 스팬, 로그에도 컨텍스트 메뉴에 &amp;ldquo;Export JSON&amp;rdquo; 옵션이 있습니다. 특정 트레이스를 공유해야 할 때? 우클릭, JSON 복사, PR 설명에 붙여넣기. 끝.&lt;/p&gt;
&lt;h2 id="텔레메트리-api가-진짜-게임-체인저"&gt;텔레메트리 API가 진짜 게임 체인저&lt;/h2&gt;
&lt;p&gt;가장 기대되는 부분입니다. 대시보드가 이제 &lt;code&gt;/api/telemetry&lt;/code&gt; 하위에 HTTP API를 제공하여 텔레메트리 데이터를 프로그래밍 방식으로 조회할 수 있습니다. 사용 가능한 엔드포인트:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/resources&lt;/code&gt; — 텔레메트리가 있는 리소스 목록&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/spans&lt;/code&gt; — 필터를 사용한 스팬 조회&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/logs&lt;/code&gt; — 필터를 사용한 로그 조회&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/traces&lt;/code&gt; — 트레이스 목록&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/telemetry/traces/{traceId}&lt;/code&gt; — 특정 트레이스의 모든 스팬 가져오기&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;모든 것이 OTLP JSON 형식으로 반환됩니다. 이것은 새로운 CLI 명령 &lt;code&gt;aspire agent mcp&lt;/code&gt;와 &lt;code&gt;aspire otel&lt;/code&gt;을 구동하지만, 진정한 의미는 더 큽니다: 이제 앱의 텔레메트리를 직접 조회하는 도구, 스크립트, AI 에이전트 통합을 구축할 수 있습니다.&lt;/p&gt;
&lt;p&gt;디버깅 중에 실제 분산 트레이스를 볼 수 있는 AI 코딩 에이전트를 상상해보세요. 더 이상 가설이 아닙니다 — 이 API가 가능하게 하는 것입니다.&lt;/p&gt;
&lt;h2 id="genai-텔레메트리가-실용적으로"&gt;GenAI 텔레메트리가 실용적으로&lt;/h2&gt;
&lt;p&gt;Semantic Kernel이나 Microsoft.Extensions.AI로 AI 기반 앱을 구축하고 있다면, 개선된 GenAI 텔레메트리 시각화 도구를 좋아할 겁니다. Aspire 13.2 추가 기능:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI 도구 설명을 Markdown으로 렌더링&lt;/li&gt;
&lt;li&gt;트레이스 페이지에 전용 GenAI 버튼으로 빠른 접근&lt;/li&gt;
&lt;li&gt;잘린 또는 비표준 GenAI JSON에 대한 더 나은 에러 처리&lt;/li&gt;
&lt;li&gt;도구 정의 간 클릭-하이라이트 내비게이션&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;블로그 포스트에서 VS Code Copilot chat, Copilot CLI, OpenCode 모두 &lt;code&gt;OTEL_EXPORTER_OTLP_ENDPOINT&lt;/code&gt; 설정을 지원한다고 언급합니다. Aspire 대시보드를 가리키면 텔레메트리를 통해 AI 에이전트가 실시간으로 생각하는 모습을 말 그대로 볼 수 있습니다. 다른 곳에서는 찾을 수 없는 디버깅 경험입니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;Aspire 13.2는 대시보드를 &amp;ldquo;괜찮은 디버깅 UI&amp;quot;에서 &amp;ldquo;프로그래밍 가능한 관찰성 플랫폼&amp;quot;으로 변화시킵니다. 내보내기/가져오기 워크플로만으로도 분산 디버깅에서 실질적인 시간을 절약하고, 텔레메트리 API는 AI 지원 진단의 문을 엽니다.&lt;/p&gt;
&lt;p&gt;이미 Aspire를 사용 중이라면 업그레이드하세요. 아직이라면 — &lt;a href="https://aspire.dev"&gt;aspire.dev&lt;/a&gt;를 확인해볼 좋은 이유입니다.&lt;/p&gt;</content:encoded></item><item><title>azd로 AI 에이전트를 로컬에서 실행하고 디버깅할 수 있게 됐다 — 2026년 3월 변경사항 정리</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azd-march-2026-local-ai-agent-debugging/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azd-march-2026-local-ai-agent-debugging/</guid><description>Azure Developer CLI가 2026년 3월에 7개 릴리스를 발행했습니다. 하이라이트: AI 에이전트의 로컬 실행 및 디버그 루프, GitHub Copilot 프로젝트 설정 통합, Container App Jobs 지원.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원본은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/azd-march-2026-local-ai-agent-debugging/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;한 달에 7개 릴리스. Azure Developer CLI (&lt;code&gt;azd&lt;/code&gt;) 팀이 2026년 3월에 발행한 것이며, 메인 기능은 제가 기다리던 것입니다: &lt;strong&gt;AI 에이전트를 위한 로컬 실행 및 디버그 루프&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;PC Chan이 &lt;a href="https://devblogs.microsoft.com/azure-sdk/azure-developer-cli-azd-march-2026/"&gt;전체 요약을 게시&lt;/a&gt;했는데, 내용이 많지만 AI 기반 앱을 구축하는 .NET 개발자에게 실제로 중요한 것만 걸러보겠습니다.&lt;/p&gt;
&lt;h2 id="배포-없이-ai-에이전트-실행-및-디버깅"&gt;배포 없이 AI 에이전트 실행 및 디버깅&lt;/h2&gt;
&lt;p&gt;이것이 핵심입니다. 새로운 &lt;code&gt;azure.ai.agents&lt;/code&gt; 확장이 AI 에이전트를 위한 적절한 이너 루프 경험을 제공하는 명령을 추가합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;azd ai agent run&lt;/code&gt; — 에이전트를 로컬에서 시작&lt;/li&gt;
&lt;li&gt;&lt;code&gt;azd ai agent invoke&lt;/code&gt; — 메시지 전송 (로컬 또는 배포된 에이전트)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;azd ai agent show&lt;/code&gt; — 컨테이너 상태 및 건강 표시&lt;/li&gt;
&lt;li&gt;&lt;code&gt;azd ai agent monitor&lt;/code&gt; — 컨테이너 로그를 실시간 스트리밍&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이전에는 AI 에이전트 테스트가 변경할 때마다 Microsoft Foundry로 배포하는 것을 의미했습니다. 이제 로컬에서 반복하고, 에이전트 동작을 테스트하고, 준비가 되면 배포할 수 있습니다.&lt;/p&gt;
&lt;h2 id="github-copilot이-azd-프로젝트를-설정"&gt;GitHub Copilot이 azd 프로젝트를 설정&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;azd init&lt;/code&gt;에 &amp;ldquo;Set up with GitHub Copilot (Preview)&amp;rdquo; 옵션이 추가됐습니다. 프로젝트 구조에 대한 프롬프트에 수동으로 답하는 대신, Copilot 에이전트가 구성을 생성합니다. 명령이 실패하면 &lt;code&gt;azd&lt;/code&gt;가 AI 지원 문제 해결을 제공합니다.&lt;/p&gt;
&lt;h2 id="container-app-jobs-및-배포-개선"&gt;Container App Jobs 및 배포 개선&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Container App Jobs&lt;/strong&gt;: &lt;code&gt;azd&lt;/code&gt;가 기존 &lt;code&gt;host: containerapp&lt;/code&gt; 설정으로 &lt;code&gt;Microsoft.App/jobs&lt;/code&gt; 배포&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;설정 가능한 배포 타임아웃&lt;/strong&gt;: &lt;code&gt;azd deploy&lt;/code&gt;의 새 &lt;code&gt;--timeout&lt;/code&gt; 플래그와 &lt;code&gt;azure.yaml&lt;/code&gt;의 &lt;code&gt;deployTimeout&lt;/code&gt; 필드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;원격 빌드 폴백&lt;/strong&gt;: ACR 빌드 실패 시 로컬 Docker/Podman 빌드로 자동 폴백&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;로컬 프리플라이트 검증&lt;/strong&gt;: 배포 전 Bicep 매개변수를 로컬에서 검증&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="dx-개선"&gt;DX 개선&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;자동 pnpm/yarn 감지&lt;/strong&gt; — JS/TS 프로젝트용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pyproject.toml 지원&lt;/strong&gt; — Python 패키징용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;로컬 템플릿 디렉토리&lt;/strong&gt; — &lt;code&gt;azd init --template&lt;/code&gt;이 파일시스템 경로 허용&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;개선된 오류 메시지&lt;/strong&gt; — &lt;code&gt;--no-prompt&lt;/code&gt; 모드&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;빌드 환경 변수&lt;/strong&gt; — 모든 프레임워크 빌드 서브프로세스에 주입 (.NET, Node.js, Java, Python)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;로컬 AI 에이전트 디버그 루프가 이번 릴리스의 스타이지만, 배포 개선과 DX 폴리시의 축적으로 &lt;code&gt;azd&lt;/code&gt;가 그 어느 때보다 성숙해졌습니다. Azure에 .NET 앱을 배포하고 있다면 — 특히 AI 에이전트라면 — 이번 업데이트는 가치가 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/azure-sdk/azure-developer-cli-azd-march-2026/"&gt;전체 릴리스 노트&lt;/a&gt;에서 모든 세부사항을 확인하세요.&lt;/p&gt;</content:encoded></item><item><title>Visual Studio 3월 업데이트로 커스텀 Copilot 에이전트 제작 가능 — find_symbol이 큰 변화</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/visual-studio-march-2026-custom-copilot-agents/</link><pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/visual-studio-march-2026-custom-copilot-agents/</guid><description>Visual Studio 2026년 3월 업데이트가 커스텀 Copilot 에이전트, 재사용 가능한 스킬, 언어 인식 find_symbol 도구, Test Explorer에서의 Copilot 프로파일링을 제공합니다.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;이 글은 자동 번역되었습니다. 원본은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/visual-studio-march-2026-custom-copilot-agents/"&gt;여기&lt;/a&gt;에서 확인하세요.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Visual Studio가 가장 중요한 Copilot 업데이트를 받았습니다. Mark Downie가 &lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studio-march-update-build-your-own-custom-agents/"&gt;3월 릴리스를 발표&lt;/a&gt;했는데, 헤드라인은 커스텀 에이전트이지만 솔직히 &lt;code&gt;find_symbol&lt;/code&gt; 도구가 워크플로를 가장 많이 바꿀 기능일 수 있습니다.&lt;/p&gt;
&lt;h2 id="리포에-커스텀-copilot-에이전트"&gt;리포에 커스텀 Copilot 에이전트&lt;/h2&gt;
&lt;p&gt;Copilot이 팀의 코딩 표준을 따르게 하고 싶으세요? 커스텀 에이전트는 리포의 &lt;code&gt;.github/agents/&lt;/code&gt;에 &lt;code&gt;.agent.md&lt;/code&gt; 파일로 정의됩니다. 각 에이전트는 워크스페이스 인식, 코드 이해, 도구, 선호 모델, MCP 연결에 대한 전체 접근 권한을 가집니다.&lt;/p&gt;
&lt;h2 id="에이전트-스킬-재사용-가능한-인스트럭션-팩"&gt;에이전트 스킬: 재사용 가능한 인스트럭션 팩&lt;/h2&gt;
&lt;p&gt;스킬은 리포의 &lt;code&gt;.github/skills/&lt;/code&gt;나 프로필의 &lt;code&gt;~/.copilot/skills/&lt;/code&gt;에서 자동 로드됩니다.&lt;/p&gt;
&lt;h2 id="find_symbol-언어-인식-내비게이션"&gt;find_symbol: 언어 인식 내비게이션&lt;/h2&gt;
&lt;p&gt;새로운 &lt;code&gt;find_symbol&lt;/code&gt; 도구는 Copilot의 에이전트 모드에 언어 서비스 기반 심볼 내비게이션을 제공합니다. 텍스트 검색 대신 심볼의 모든 참조를 찾고 타입 정보와 스코프에 접근할 수 있습니다.&lt;/p&gt;
&lt;p&gt;.NET 개발자에게 이것은 엄청난 개선입니다 — 깊은 타입 계층 구조를 가진 C# 코드베이스가 크게 혜택을 받습니다.&lt;/p&gt;
&lt;h2 id="copilot으로-테스트-프로파일링"&gt;Copilot으로 테스트 프로파일링&lt;/h2&gt;
&lt;p&gt;Test Explorer 컨텍스트 메뉴에 &lt;strong&gt;Profile with Copilot&lt;/strong&gt;이 추가됐습니다. Profiling Agent가 테스트를 실행하고 자동으로 성능을 분석합니다.&lt;/p&gt;
&lt;h2 id="라이브-디버깅-중-perf-tips"&gt;라이브 디버깅 중 Perf Tips&lt;/h2&gt;
&lt;p&gt;성능 최적화가 이제 디버깅 중에 이루어집니다. Visual Studio가 인라인으로 실행 시간을 표시합니다. 느린 라인을 발견하면 Perf Tip을 클릭하고 Copilot에게 최적화 제안을 요청하세요.&lt;/p&gt;
&lt;h2 id="solution-explorer에서-nuget-취약점-수정"&gt;Solution Explorer에서 NuGet 취약점 수정&lt;/h2&gt;
&lt;p&gt;NuGet 패키지 취약점이 감지되면 Solution Explorer에 직접 &lt;strong&gt;Fix with GitHub Copilot&lt;/strong&gt; 링크가 표시됩니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;커스텀 에이전트와 스킬이 헤드라인이지만, &lt;code&gt;find_symbol&lt;/code&gt;이 숨겨진 보석입니다 — .NET 코드 리팩토링 시 Copilot의 정확도를 근본적으로 바꿉니다. &lt;a href="https://visualstudio.microsoft.com/downloads/"&gt;Visual Studio 2026 Insiders&lt;/a&gt;를 다운로드해서 모든 기능을 체험해보세요.&lt;/p&gt;</content:encoded></item><item><title>KubeCon Europe 2026: .NET 개발자가 실제로 알아야 할 것</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/kubecon-2026-aks-updates-dotnet-developers/</link><pubDate>Sun, 29 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/kubecon-2026-aks-updates-dotnet-developers/</guid><description>Microsoft가 KubeCon Europe 2026에서 대량의 Kubernetes 발표를 쏟아냈습니다. .NET 앱을 배포하고 있다면 실제로 중요한 AKS와 클라우드 네이티브 업데이트만 필터링해서 정리했습니다.</description><content:encoded>&lt;p&gt;&lt;em&gt;이 게시물은 자동 번역되었습니다. 원본은 &lt;a href="https://thedotnetblog.com/ko/news/emiliano-montesdeoca/kubecon-2026-aks-updates-dotnet-developers/"&gt;여기를 클릭&lt;/a&gt;하세요.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;거대한 발표 글이 올라오고 스크롤하면서 &amp;ldquo;멋지긴 한데, 이게 실제로 나한테 뭘 바꿔주는 거지?&amp;ldquo;라고 생각하는 그 느낌 아시죠? 매 KubeCon 시즌마다 저한테 벌어지는 일입니다.&lt;/p&gt;
&lt;p&gt;Microsoft가 방금 &lt;a href="https://opensource.microsoft.com/blog/2026/03/24/whats-new-with-microsoft-in-open-source-and-kubernetes-at-kubecon-cloudnativecon-europe-2026/"&gt;KubeCon Europe 2026 전체 요약&lt;/a&gt;을 발표했는데요 — Brendan Burns 본인이 직접 작성했습니다 — 솔직히? 진짜 내용이 있습니다. 기능 체크리스트가 아니라, 프로덕션에서 운영하는 방식을 바꿔주는 운영 개선 사항들입니다.&lt;/p&gt;
&lt;p&gt;.NET 개발자로서 진짜 중요한 것만 정리해 보겠습니다.&lt;/p&gt;
&lt;h2 id="서비스-메시-세금-없는-mtls"&gt;서비스 메시 세금 없는 mTLS&lt;/h2&gt;
&lt;p&gt;서비스 메시의 문제점: 모두가 보안 보장을 원하지만, 운영 오버헤드는 아무도 원하지 않습니다. AKS가 드디어 이 격차를 메우고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://aka.ms/aks/application-network"&gt;Azure Kubernetes Application Network&lt;/a&gt;은 상호 TLS, 애플리케이션 인식 인가, 트래픽 텔레메트리를 제공합니다 — 사이드카가 무거운 풀 메시를 배포할 필요 없이요. &lt;a href="https://aka.ms/acns/cilium-mtls"&gt;Advanced Container Networking Services의 Cilium mTLS&lt;/a&gt;와 결합하면, X.509 인증서와 SPIRE 신원 관리를 사용한 암호화된 pod 간 통신을 얻을 수 있습니다.&lt;/p&gt;
&lt;p&gt;실제로 의미하는 것: ASP.NET Core API가 백그라운드 워커와 통신하고, gRPC 서비스가 서로 호출하는 것 — 모두 네트워크 수준에서 암호화되고 신원 검증되며, 애플리케이션 코드 변경은 제로. 이건 큽니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ingress-nginx&lt;/code&gt;에서 마이그레이션하는 팀을 위해, &lt;a href="https://aka.ms/aks/app-routing/gateway-api"&gt;Meshless Istio를 사용한 Application Routing&lt;/a&gt;도 있으며 Kubernetes Gateway API를 완전히 지원합니다. 사이드카 없음. 표준 기반. 점진적 마이그레이션을 위한 &lt;code&gt;ingress2gateway&lt;/code&gt; 도구도 함께 출시되었습니다.&lt;/p&gt;
&lt;h2 id="뒤늦은-생각이-아닌-gpu-관측성"&gt;뒤늦은 생각이 아닌 GPU 관측성&lt;/h2&gt;
&lt;p&gt;.NET 서비스와 함께 AI 추론을 실행하고 있다면(솔직히, 누가 시작하지 않고 있겠어요?), GPU 모니터링 사각지대를 경험했을 겁니다. CPU/메모리 대시보드는 훌륭했는데, GPU는&amp;hellip; 수동 익스포터 설정 없이는 아무것도 없었죠.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://aka.ms/aks/managed-gpu-metrics"&gt;AKS가 이제 GPU 메트릭을 네이티브로 노출&lt;/a&gt;합니다 — 관리형 Prometheus와 Grafana에서. 같은 스택, 같은 대시보드, 같은 알림 파이프라인. 커스텀 익스포터도 서드파티 에이전트도 불필요.&lt;/p&gt;
&lt;p&gt;네트워크 측에서는, HTTP, gRPC, Kafka 트래픽에 대한 플로우별 가시성이 &lt;a href="https://learn.microsoft.com/en-us/azure/aks/container-network-observability-logs"&gt;원클릭 Azure Monitor 경험&lt;/a&gt;과 함께 추가되었습니다. IP, 포트, 워크로드, 플로우 방향, 정책 결정 — 모두 내장 대시보드에서.&lt;/p&gt;
&lt;p&gt;그리고 두 번 쳐다보게 만든 것: &lt;a href="https://learn.microsoft.com/en-us/azure/aks/advanced-container-networking-services-overview"&gt;agentic container networking&lt;/a&gt;이 자연어로 클러스터의 네트워크 상태에 대해 질문할 수 있는 웹 UI를 추가합니다. &amp;ldquo;Pod X가 서비스 Y에 도달하지 못하는 이유는?&amp;rdquo; → 라이브 텔레메트리에서 읽기 전용 진단. 새벽 2시에 진짜 유용합니다.&lt;/p&gt;
&lt;h2 id="박사-학위-필요-없는-크로스-클러스터-네트워킹"&gt;박사 학위 필요 없는 크로스 클러스터 네트워킹&lt;/h2&gt;
&lt;p&gt;멀티 클러스터 Kubernetes는 역사적으로 &amp;ldquo;자체 네트워크 접착제를 가져오세요&amp;rdquo; 경험이었습니다. Azure Kubernetes Fleet Manager가 이제 관리형 Cilium 클러스터 메시를 통한 &lt;a href="https://aka.ms/kubernetes-fleet/networking/cross-cluster"&gt;크로스 클러스터 네트워킹&lt;/a&gt;을 제공합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AKS 클러스터 간 통합 연결&lt;/li&gt;
&lt;li&gt;크로스 클러스터 디스커버리를 위한 글로벌 서비스 레지스트리&lt;/li&gt;
&lt;li&gt;클러스터마다 반복하지 않고 중앙에서 관리되는 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;복원력이나 컴플라이언스를 위해 여러 리전에서 .NET 마이크로서비스를 실행하고 있다면, 많은 취약한 커스텀 접착제를 대체합니다. West Europe의 서비스 A가 메시를 통해 East US의 서비스 B를 발견하고 호출할 수 있으며, 일관된 라우팅과 보안 정책이 적용됩니다.&lt;/p&gt;
&lt;h2 id="용기가-필요-없는-업그레이드"&gt;용기가 필요 없는 업그레이드&lt;/h2&gt;
&lt;p&gt;솔직히 — 프로덕션에서의 Kubernetes 업그레이드는 스트레스입니다. &amp;ldquo;업그레이드하고 기도하기&amp;quot;가 너무 많은 팀의 사실상 전략이었고, 클러스터가 버전에서 뒤처지는 주된 이유입니다.&lt;/p&gt;
&lt;p&gt;두 가지 새로운 기능이 이것을 바꿉니다:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Blue-green 에이전트 풀 업그레이드&lt;/strong&gt;는 새 설정으로 병렬 노드 풀을 생성합니다. 동작을 검증하고, 트래픽을 점진적으로 이동하고, 깨끗한 롤백 경로를 유지하세요. 프로덕션 노드에서의 인플레이스 변경은 이제 끝.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;에이전트 풀 롤백&lt;/strong&gt;은 업그레이드가 잘못된 후 클러스터를 재구축하지 않고 노드 풀을 이전 Kubernetes 버전과 노드 이미지로 되돌릴 수 있게 합니다.&lt;/p&gt;
&lt;p&gt;함께 사용하면, 운영자에게 업그레이드 생명주기에 대한 진정한 통제력을 제공합니다. .NET 팀에게 중요한 이유는 플랫폼 속도가 새로운 런タ임, 보안 패치, 네트워크 기능을 얼마나 빨리 채택하는지를 직접 제어하기 때문입니다.&lt;/p&gt;
&lt;h2 id="ai-워크로드가-kubernetes의-일급-시민이-되다"&gt;AI 워크로드가 Kubernetes의 일급 시민이 되다&lt;/h2&gt;
&lt;p&gt;업스트림 오픈소스 작업도 마찬가지로 중요합니다. Dynamic Resource Allocation (DRA)이 Kubernetes 1.36에서 GA가 되어, GPU 스케줄링이 우회 방법이 아닌 진정한 일급 기능이 되었습니다.&lt;/p&gt;
&lt;p&gt;주목할 프로젝트들:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;프로젝트&lt;/th&gt;
&lt;th&gt;하는 일&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/kaito-project/kubeairunway"&gt;AI Runway&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;추론을 위한 공통 Kubernetes API — K8s를 몰라도 모델 배포 가능, HuggingFace 검색과 비용 추정 포함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://www.cncf.io/blog/2026/01/07/holmesgpt-agentic-troubleshooting-built-for-the-cloud-native-era/"&gt;HolmesGPT&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;클라우드 네이티브를 위한 에이전트 문제 해결 — CNCF Sandbox 프로젝트로 합류&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/project-dalec/dalec"&gt;Dalec&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;SBOM 생성을 포함한 선언적 컨테이너 이미지 빌드 — 빌드 단계에서 CVE 감소&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;방향은 명확합니다: 여러분의 .NET API, Semantic Kernel 오케스트레이션 레이어, 추론 워크로드 모두 하나의 일관된 플랫폼 모델에서 실행되어야 합니다. 거기에 도달하고 있습니다.&lt;/p&gt;
&lt;h2 id="이번-주부터-시작한다면"&gt;이번 주부터 시작한다면&lt;/h2&gt;
&lt;p&gt;팀에서 이러한 변경 사항을 평가하고 있다면, 제 솔직한 우선순위 목록:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;관측성 먼저&lt;/strong&gt; — 비프로덕션 클러스터에서 GPU 메트릭과 네트워크 플로우 로그를 활성화하세요. 놓치고 있던 것을 확인하세요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blue-green 업그레이드 테스트&lt;/strong&gt; — 다음 프로덕션 클러스터 업그레이드 전에 롤백 워크플로우를 테스트하세요. 프로세스에 대한 신뢰를 구축하세요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;신원 인식 네트워킹 파일럿&lt;/strong&gt; — 내부 서비스 경로 하나를 선택해서 Cilium으로 mTLS를 활성화하세요. 오버헤드를 측정하세요 (스포일러: 최소).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fleet Manager 평가&lt;/strong&gt; — 두 개 이상의 클러스터를 운영한다면, 크로스 클러스터 네트워킹은 커스텀 접착제 감소만으로도 투자 대비 이득.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;작은 실험, 빠른 피드백. 항상 정답인 방법입니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;KubeCon 발표는 압도적일 수 있지만, 이번 배치는 AKS의 .NET 팀에게 진정으로 바늘을 움직입니다. 메시 오버헤드 없는 더 나은 네트워크 보안, 진짜 GPU 관측성, 더 안전한 업그레이드, 그리고 더 강력한 AI 인프라 기반.&lt;/p&gt;
&lt;p&gt;이미 AKS를 사용하고 있다면, 운영 기준선을 강화할 좋은 시점입니다. .NET 워크로드를 Kubernetes로 이동할 계획이라면 — 플랫폼이 훨씬 더 프로덕션에 준비되었습니다.&lt;/p&gt;</content:encoded></item><item><title>Foundry Agent Service GA: .NET 에이전트 개발자에게 정말 중요한 것</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/foundry-agent-service-ga-what-matters/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/foundry-agent-service-ga-what-matters/</guid><description>Microsoft의 Foundry Agent Service가 프라이빗 네트워킹, Voice Live, 프로덕션 평가, 오픈 멀티모델 런타임으로 GA에 도달했습니다. 알아야 할 것들을 정리합니다.</description><content:encoded>&lt;p&gt;솔직히 말하면 — AI 에이전트 프로토타입을 만드는 건 쉬운 부분입니다. 어려운 건 그 이후의 모든 것: 적절한 네트워크 격리로 프로덕션에 올리기, 실제로 의미 있는 평가를 실행하기, 컴플라이언스 요구사항 처리하기, 새벽 2시에 아무것도 안 깨뜨리기.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/foundry/foundry-agent-service-ga/"&gt;Foundry Agent Service가 GA에 도달했습니다&lt;/a&gt;. 이 릴리스는 &amp;ldquo;그 이후의 모든 것&amp;rdquo; 간극에 레이저처럼 집중하고 있습니다.&lt;/p&gt;
&lt;h2 id="responses-api-위에-구축"&gt;Responses API 위에 구축&lt;/h2&gt;
&lt;p&gt;헤드라인: 차세대 Foundry Agent Service는 OpenAI Responses API 위에 구축되었습니다. 이미 그 와이어 프로토콜로 개발하고 있다면 Foundry로의 마이그레이션은 최소한의 코드 변경으로 가능합니다. 얻는 것: 엔터프라이즈 보안, 프라이빗 네트워킹, Entra RBAC, 완전한 트레이싱, 평가 — 기존 에이전트 로직 위에.&lt;/p&gt;
&lt;p&gt;아키텍처는 의도적으로 열려 있습니다. 하나의 모델 제공자나 하나의 오케스트레이션 프레임워크에 종속되지 않습니다. 계획에 DeepSeek, 생성에 OpenAI, 오케스트레이션에 LangGraph — 런타임이 일관성 레이어를 처리합니다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.ai.projects&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AIProjectClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;azure.ai.projects.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PromptAgentDefinition&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;with&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;DefaultAzureCredential&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;credential&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;AIProjectClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AZURE_AI_PROJECT_ENDPOINT&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;credential&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;project_client&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;project_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_openai_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;openai_client&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="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;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_version&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;agent_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-enterprise-agent&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;definition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PromptAgentDefinition&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;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AZURE_AI_MODEL_DEPLOYMENT_NAME&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;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;You are a helpful assistant.&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="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;conversation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conversations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&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;conversation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;What are best practices for building AI agents?&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;extra_body&lt;/span&gt;&lt;span class="o"&gt;=&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="s2"&gt;&amp;#34;agent_reference&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;agent_reference&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="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&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;blockquote&gt;
&lt;p&gt;&lt;code&gt;azure-ai-agents&lt;/code&gt; 패키지에서 오는 경우, 에이전트는 이제 &lt;code&gt;azure-ai-projects&lt;/code&gt;의 &lt;code&gt;AIProjectClient&lt;/code&gt;에서 퍼스트 클래스 작업입니다. 독립 의존성을 제거하고 &lt;code&gt;get_openai_client()&lt;/code&gt;를 사용하여 응답을 구동하세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="프라이빗-네트워킹-엔터프라이즈-블로커-제거"&gt;프라이빗 네트워킹: 엔터프라이즈 블로커 제거&lt;/h2&gt;
&lt;p&gt;이것이 엔터프라이즈 채택의 잠금을 해제하는 기능입니다. Foundry는 이제 BYO VNet으로 완전한 엔드투엔드 프라이빗 네트워킹을 지원합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;퍼블릭 이그레스 없음&lt;/strong&gt; — 에이전트 트래픽이 공개 인터넷에 접촉하지 않음&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;컨테이너/서브넷 인젝션&lt;/strong&gt;으로 로컬 통신을 위해 네트워크에 주입&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;도구 연결성 포함&lt;/strong&gt; — MCP 서버, Azure AI Search, Fabric 데이터 에이전트 모두 프라이빗 경로로 작동&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;마지막 포인트가 중요합니다. 프라이빗으로 유지되는 건 추론 호출만이 아닙니다 — 모든 도구 호출과 검색 콜도 네트워크 경계 내에 머무릅니다. 외부 라우팅을 금지하는 데이터 분류 정책 하에서 운영하는 팀에게 이것이 빠져있던 것입니다.&lt;/p&gt;
&lt;h2 id="mcp-인증-제대로-하기"&gt;MCP 인증 제대로 하기&lt;/h2&gt;
&lt;p&gt;MCP 서버 연결은 이제 인증 패턴의 전체 스펙트럼을 지원합니다:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;인증 방식&lt;/th&gt;
&lt;th&gt;사용 시점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;키 기반&lt;/td&gt;
&lt;td&gt;조직 전체 내부 도구의 간단한 공유 액세스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entra Agent Identity&lt;/td&gt;
&lt;td&gt;서비스 간; 에이전트가 자기 자신으로 인증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entra Managed Identity&lt;/td&gt;
&lt;td&gt;프로젝트별 격리; 자격증명 관리 불필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OAuth Identity Passthrough&lt;/td&gt;
&lt;td&gt;사용자 위임 액세스; 에이전트가 사용자를 대신하여 행동&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;OAuth Identity Passthrough가 흥미로운 것입니다. 사용자가 에이전트에 개인 데이터 — OneDrive, Salesforce 조직, 사용자별 스코프 SaaS API — 에 대한 액세스를 부여해야 할 때, 에이전트는 표준 OAuth 플로우로 사용자를 대신하여 행동합니다. 모든 사람인 척하는 공유 시스템 ID는 없습니다.&lt;/p&gt;
&lt;h2 id="voice-live-배관-없는-음성-대-음성"&gt;Voice Live: 배관 없는 음성 대 음성&lt;/h2&gt;
&lt;p&gt;에이전트에 음성을 추가하는 것은 STT, LLM, TTS를 연결하는 것을 의미했습니다 — 세 개의 서비스, 세 번의 지연 홉, 세 개의 과금 표면, 모두 수동 동기화. &lt;strong&gt;Voice Live&lt;/strong&gt;는 이것을 단일 관리 API로 압축합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;시맨틱 음성 활동 및 턴 종료 감지 (침묵이 아닌 의미를 이해)&lt;/li&gt;
&lt;li&gt;서버 측 노이즈 억제 및 에코 캔슬레이션&lt;/li&gt;
&lt;li&gt;끼어들기 지원 (사용자가 응답 중간에 끼어들 수 있음)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;음성 상호작용은 텍스트와 같은 에이전트 런타임을 통과합니다. 같은 평가자, 같은 트레이스, 같은 비용 가시성. 고객 지원, 현장 서비스, 접근성 시나리오에서 이전에 커스텀 오디오 파이프라인이 필요했던 것을 대체합니다.&lt;/p&gt;
&lt;h2 id="평가-체크박스에서-지속적-모니터링으로"&gt;평가: 체크박스에서 지속적 모니터링으로&lt;/h2&gt;
&lt;p&gt;여기서 Foundry는 프로덕션 품질에 대해 진지해집니다. 평가 시스템에는 이제 세 개의 레이어가 있습니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;기본 제공 평가자&lt;/strong&gt; — 일관성, 관련성, 근거성, 검색 품질, 안전성. 데이터셋이나 라이브 트래픽에 연결하여 점수를 받으세요.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;커스텀 평가자&lt;/strong&gt; — 자체 비즈니스 로직, 톤 표준, 도메인별 컴플라이언스 규칙을 인코딩하세요.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;지속적 평가&lt;/strong&gt; — Foundry가 라이브 프로덕션 트래픽을 샘플링하고, 평가자 스위트를 실행하고, 대시보드에 결과를 표시합니다. 근거성이 떨어지거나 안전 임계값이 초과되면 Azure Monitor 알림을 설정하세요.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;모든 것이 Azure Monitor Application Insights에 게시됩니다. 에이전트 품질, 인프라 상태, 비용, 앱 텔레메트리 — 모두 한 곳에.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;eval_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai_client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;evals&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&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;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Agent Quality Evaluation&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;data_source_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DataSourceConfigCustom&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="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;custom&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;item_schema&lt;/span&gt;&lt;span class="o"&gt;=&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="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;object&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="s2"&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;query&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;string&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="s2"&gt;&amp;#34;required&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;query&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="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;include_sample_schema&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&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="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;testing_criteria&lt;/span&gt;&lt;span class="o"&gt;=&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="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;azure_ai_evaluator&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="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fluency&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="s2"&gt;&amp;#34;evaluator_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;builtin.fluency&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="s2"&gt;&amp;#34;initialization_parameters&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&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="s2"&gt;&amp;#34;deployment_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;AZURE_AI_MODEL_DEPLOYMENT_NAME&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="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;data_mapping&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&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="s2"&gt;&amp;#34;query&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{{item.query}}&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="s2"&gt;&amp;#34;response&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{{sample.output_text}}&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="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;h2 id="호스티드-에이전트를-위한-6개-새-지역"&gt;호스티드 에이전트를 위한 6개 새 지역&lt;/h2&gt;
&lt;p&gt;호스티드 에이전트가 East US, North Central US, Sweden Central, Southeast Asia, Japan East 등에서 사용 가능합니다. 데이터 거주 요구사항과 에이전트가 데이터 소스 가까이에서 실행될 때 지연 시간을 압축하는 데 중요합니다.&lt;/p&gt;
&lt;h2 id="net-개발자에게-왜-중요한가"&gt;.NET 개발자에게 왜 중요한가&lt;/h2&gt;
&lt;p&gt;GA 공지의 코드 샘플은 Python 우선이지만, 기반 인프라는 언어에 구애받지 않습니다 — 그리고 &lt;code&gt;azure-ai-projects&lt;/code&gt;의 .NET SDK도 같은 패턴을 따릅니다. Responses API, 평가 프레임워크, 프라이빗 네트워킹, MCP 인증 — 이 모든 것이 .NET에서 사용 가능합니다.&lt;/p&gt;
&lt;p&gt;AI 에이전트가 &amp;ldquo;멋진 데모&amp;quot;에서 &amp;ldquo;실제로 직장에서 출하할 수 있는 것&amp;quot;으로 바뀌기를 기다리고 있었다면, 이 GA 릴리스가 그 신호입니다. 프라이빗 네트워킹, 적절한 인증, 지속적 평가, 프로덕션 모니터링이 빠져있던 퍼즐 조각입니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;Foundry Agent Service는 지금 사용할 수 있습니다. SDK를 설치하고, &lt;a href="https://ai.azure.com"&gt;포털&lt;/a&gt;을 열고, 빌드를 시작하세요. &lt;a href="https://learn.microsoft.com/azure/foundry/quickstarts/get-started-code"&gt;빠른 시작 가이드&lt;/a&gt;가 몇 분 만에 제로에서 동작하는 에이전트까지 안내합니다.&lt;/p&gt;
&lt;p&gt;모든 코드 샘플이 포함된 전체 기술 딥다이브는 &lt;a href="https://devblogs.microsoft.com/foundry/foundry-agent-service-ga/"&gt;GA 공지&lt;/a&gt;를 확인하세요.&lt;/p&gt;</content:encoded></item><item><title>Microsoft Agent Framework의 백그라운드 응답: 더 이상 타임아웃 걱정 없이</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/background-responses-agent-framework-long-running-tasks/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/background-responses-agent-framework-long-running-tasks/</guid><description>Microsoft Agent Framework가 이제 연속 토큰으로 장시간 실행 AI 작업을 오프로드할 수 있습니다. 백그라운드 응답의 작동 방식과 .NET 에이전트에 중요한 이유를 알아보세요.</description><content:encoded>&lt;p&gt;o3나 GPT-5.2 같은 추론 모델로 무언가를 만들어 본 적이 있다면, 그 고통을 알 것입니다. 에이전트가 복잡한 작업을 생각하기 시작하고, 클라이언트는 기다리고, &amp;ldquo;괜찮아&amp;quot;와 &amp;ldquo;크래시한 건가?&amp;rdquo; 사이 어딘가에서 연결이 타임아웃됩니다. 그 모든 작업은? 사라집니다.&lt;/p&gt;
&lt;p&gt;Microsoft Agent Framework가 &lt;a href="https://devblogs.microsoft.com/agent-framework/handling-long-running-operations-with-background-responses/"&gt;백그라운드 응답&lt;/a&gt;을 출시했습니다 — 솔직히, 이건 처음부터 있었어야 할 기능 중 하나입니다.&lt;/p&gt;
&lt;h2 id="블로킹-호출의-문제"&gt;블로킹 호출의 문제&lt;/h2&gt;
&lt;p&gt;전통적인 요청-응답 패턴에서는 에이전트가 끝날 때까지 클라이언트가 블로킹됩니다. 빠른 작업에는 잘 작동합니다. 하지만 추론 모델에 깊은 연구, 다단계 분석, 20페이지 보고서 생성을 요청하면? 실제 시간으로 몇 분이 걸립니다. 그 시간 동안:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP 연결이 타임아웃될 수 있음&lt;/li&gt;
&lt;li&gt;네트워크 끊김이 전체 작업을 죽임&lt;/li&gt;
&lt;li&gt;사용자는 스피너를 보며 무슨 일이 일어나고 있는지 궁금해 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;백그라운드 응답은 이것을 뒤집습니다.&lt;/p&gt;
&lt;h2 id="연속-토큰의-작동-방식"&gt;연속 토큰의 작동 방식&lt;/h2&gt;
&lt;p&gt;블로킹 대신, 에이전트 작업을 시작하고 &lt;strong&gt;연속 토큰&lt;/strong&gt;을 받습니다. 수리점의 픽업 티켓처럼 생각하세요 — 카운터에서 서서 기다릴 필요 없이, 준비되면 돌아오면 됩니다.&lt;/p&gt;
&lt;p&gt;흐름은 간단합니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;AllowBackgroundResponses = true&lt;/code&gt;로 요청 전송&lt;/li&gt;
&lt;li&gt;에이전트가 백그라운드 처리를 지원하면 연속 토큰을 받음&lt;/li&gt;
&lt;li&gt;토큰이 &lt;code&gt;null&lt;/code&gt;을 반환할 때까지 폴링 — 결과가 준비되었다는 의미&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;.NET 버전은 다음과 같습니다:&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="n"&gt;AIAgent&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AzureOpenAIClient&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="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://&amp;lt;myresource&amp;gt;.openai.azure.com&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="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DefaultAzureCredential&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetResponsesClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;lt;deployment-name&amp;gt;&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="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsAIAgent&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentRunOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&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="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;AllowBackgroundResponses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentSession&lt;/span&gt; &lt;span class="n"&gt;session&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;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateSessionAsync&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentResponse&lt;/span&gt; &lt;span class="n"&gt;response&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;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&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="s"&gt;&amp;#34;Write a detailed market analysis for the Q4 product launch.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 완료까지 폴링&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;null&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="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&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;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&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;response&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;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&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="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&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;/p&gt;
&lt;h2 id="재개가-가능한-스트리밍-진짜-마법"&gt;재개가 가능한 스트리밍: 진짜 마법&lt;/h2&gt;
&lt;p&gt;폴링은 fire-and-forget 시나리오에 괜찮지만, 실시간 진행 상황을 원한다면? 백그라운드 응답은 내장 재개 기능이 있는 스트리밍도 지원합니다.&lt;/p&gt;
&lt;p&gt;각 스트리밍 업데이트는 자체 연속 토큰을 가집니다. 스트리밍 중에 연결이 끊기면, 중단된 정확한 지점에서 재개합니다:&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="n"&gt;AgentRunOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&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="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;AllowBackgroundResponses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AgentSession&lt;/span&gt; &lt;span class="n"&gt;session&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;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateSessionAsync&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;AgentResponseUpdate&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;latestUpdate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunStreamingAsync&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="s"&gt;&amp;#34;Write a detailed market analysis for the Q4 product launch.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&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="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;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&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;latestUpdate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 네트워크 중단 시뮬레이션&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&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;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;latestUpdate&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;ContinuationToken&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="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RunStreamingAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&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="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;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&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="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;클라이언트에 무슨 일이 일어나든 에이전트는 서버 측에서 계속 처리합니다. 재시도 로직이나 서킷 브레이커를 작성하지 않고도 내장된 장애 허용입니다.&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;복잡한 추론 작업&lt;/strong&gt; — 다단계 분석, 깊은 연구, 추론 모델을 진지하게 생각하게 만드는 모든 것&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;긴 콘텐츠 생성&lt;/strong&gt; — 상세 보고서, 다중 파트 문서, 광범위한 분석&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;불안정한 네트워크&lt;/strong&gt; — 모바일 클라이언트, 엣지 배포, 불안정한 기업 VPN&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;비동기 UX 패턴&lt;/strong&gt; — 작업을 제출하고, 다른 일을 하고, 결과를 가지러 돌아옴&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;엔터프라이즈 앱을 구축하는 .NET 개발자에게 마지막 포인트가 특히 흥미롭습니다. 사용자가 복잡한 보고서를 요청하는 Blazor 앱을 생각해 보세요 — 에이전트 작업을 시작하고, 프로그레스 인디케이터를 보여주고, 계속 작업하게 합니다. WebSocket 곡예 없이, 커스텀 큐 인프라 없이, 토큰과 폴링 루프만 있으면 됩니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;백그라운드 응답은 Microsoft Agent Framework를 통해 .NET과 Python 모두에서 지금 사용할 수 있습니다. 단순한 Q&amp;amp;A 이상을 하는 에이전트를 구축하고 있다면, 툴킷에 추가할 가치가 있습니다. 연속 토큰 패턴은 매우 현실적인 프로덕션 문제를 해결하면서 것을 심플하게 유지합니다.&lt;/p&gt;
&lt;p&gt;전체 API 참조와 더 많은 예제는 &lt;a href="https://devblogs.microsoft.com/agent-framework/handling-long-running-operations-with-background-responses/"&gt;전체 문서&lt;/a&gt;를 확인하세요.&lt;/p&gt;</content:encoded></item><item><title>VS Code 1.112: .NET 개발자가 정말 주목해야 할 것들</title><link>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/vscode-1-112-dotnet-developers/</link><pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/ko/news/emiliano-montesdeoca/vscode-1-112-dotnet-developers/</guid><description>VS Code 1.112가 에이전트 업그레이드, 통합 브라우저 디버거, MCP 샌드박싱, 모노레포 지원으로 출시되었습니다. .NET으로 개발한다면 정말 중요한 것들을 정리합니다.</description><content:encoded>&lt;p&gt;VS Code 1.112가 도착했고, 솔직히? .NET 세계에서 매일을 보내고 있다면 이번 릴리스는 다르게 다가옵니다. &lt;a href="https://code.visualstudio.com/updates/v1_112"&gt;공식 릴리스 노트&lt;/a&gt;에 많은 내용이 있지만, 스크롤을 좀 줄여드리고 우리에게 정말 중요한 것에 집중하겠습니다.&lt;/p&gt;
&lt;h2 id="copilot-cli가-훨씬-유용해졌다"&gt;Copilot CLI가 훨씬 유용해졌다&lt;/h2&gt;
&lt;p&gt;이번 릴리스의 큰 테마는 &lt;strong&gt;에이전트 자율성&lt;/strong&gt; — Copilot에게 더 많은 자유를 주어 당신이 매 단계를 감시하지 않아도 되게 하는 것입니다.&lt;/p&gt;
&lt;h3 id="메시지-스티어링과-큐잉"&gt;메시지 스티어링과 큐잉&lt;/h3&gt;
&lt;p&gt;Copilot CLI가 작업 중간에 있는데 뭔가 말하는 걸 깜빡했다는 걸 깨닫는 그 순간 알죠? 전에는 기다려야 했습니다. 이제 요청이 아직 실행 중일 때도 메시지를 보낼 수 있습니다 — 현재 응답을 방향 전환하거나 후속 지시를 큐에 넣거나.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dotnet&lt;/code&gt; 스캐폴딩의 긴 작업을 보면서 &amp;ldquo;아 잠깐, MassTransit도 필요한데&amp;quot;라고 생각하는 경우에 이것은 대단합니다.&lt;/p&gt;
&lt;h3 id="권한-레벨"&gt;권한 레벨&lt;/h3&gt;
&lt;p&gt;이것이 가장 흥분되는 것입니다. Copilot CLI 세션이 이제 세 가지 권한 레벨을 지원합니다:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;기본 권한&lt;/strong&gt; — 도구가 실행 전에 확인을 요청하는 일반적인 흐름&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;승인 우회&lt;/strong&gt; — 모든 것을 자동 승인하고 오류 시 재시도&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;오토파일럿&lt;/strong&gt; — 완전 자율: 도구를 승인하고, 자체 질문에 답하고, 작업이 완료될 때까지 계속&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Entity Framework, 마이그레이션, Docker 설정으로 새 ASP.NET Core API를 만드는 것 같은 작업을 한다면 — 오토파일럿 모드는 원하는 것을 설명하고 커피를 가지러 가면 됩니다. 알아서 할 겁니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;chat.autopilot.enabled&lt;/code&gt; 설정으로 오토파일럿을 활성화할 수 있습니다.&lt;/p&gt;
&lt;h3 id="위임-전-변경사항-미리보기"&gt;위임 전 변경사항 미리보기&lt;/h3&gt;
&lt;p&gt;Copilot CLI에 작업을 위임하면 워크트리가 생성됩니다. 전에는 커밋하지 않은 변경사항이 있으면 소스 컨트롤을 확인해서 뭐가 영향받는지 봐야 했습니다. 이제 채팅 뷰에서 복사, 이동, 무시를 결정하기 전에 보류 중인 변경사항을 바로 보여줍니다.&lt;/p&gt;
&lt;p&gt;작은 것이지만 &amp;ldquo;잠깐, 스테이징에 뭐가 있었지?&amp;rdquo; 하는 순간을 없애줍니다.&lt;/p&gt;
&lt;h2 id="vs-code를-떠나지-않고-웹-앱-디버그"&gt;VS Code를 떠나지 않고 웹 앱 디버그&lt;/h2&gt;
&lt;p&gt;통합 브라우저가 이제 &lt;strong&gt;완전한 디버깅&lt;/strong&gt;을 지원합니다. 브레이크포인트를 설정하고, 코드를 스텝스루하고, 변수를 검사할 수 있습니다 — 모두 VS Code 안에서. Edge DevTools로 전환할 필요 없습니다.&lt;/p&gt;
&lt;p&gt;새로운 &lt;code&gt;editor-browser&lt;/code&gt; 디버그 타입이 있고, 이미 &lt;code&gt;msedge&lt;/code&gt;나 &lt;code&gt;chrome&lt;/code&gt; 실행 구성이 있다면 &lt;code&gt;launch.json&lt;/code&gt;의 &lt;code&gt;type&lt;/code&gt; 필드만 바꾸면 됩니다:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;editor-browser&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="nt"&gt;&amp;#34;request&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;launch&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="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Debug Blazor App&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="nt"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://localhost:5001&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;Blazor 개발자에게 이것은 게임 체인저입니다. 이미 터미널에서 &lt;code&gt;dotnet watch&lt;/code&gt;를 실행하고 있으니 — 이제 디버깅도 같은 창에 머무릅니다.&lt;/p&gt;
&lt;p&gt;브라우저에 독립적인 줌 레벨(드디어), 적절한 우클릭 컨텍스트 메뉴, 웹사이트별 줌 기억 기능도 추가되었습니다.&lt;/p&gt;
&lt;h2 id="mcp-서버-샌드박싱"&gt;MCP 서버 샌드박싱&lt;/h2&gt;
&lt;p&gt;이것은 생각보다 중요합니다. MCP 서버를 사용하고 있다면 — Azure 리소스나 데이터베이스 쿼리를 위한 커스텀 서버를 설정했을 수 있습니다 — VS Code 프로세스와 같은 권한으로 실행되고 있었습니다. 파일 시스템, 네트워크, 모든 것에 대한 전체 액세스를 의미합니다.&lt;/p&gt;
&lt;p&gt;이제 샌드박스처리할 수 있습니다. &lt;code&gt;mcp.json&lt;/code&gt;에서:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="nt"&gt;&amp;#34;servers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&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="nt"&gt;&amp;#34;my-azure-tools&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&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="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;node&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="nt"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./mcp-server.js&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="nt"&gt;&amp;#34;sandboxEnabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;샌드박스된 서버가 가지고 있지 않은 것에 대한 액세스가 필요하면 VS Code가 권한 부여를 요청합니다. &amp;ldquo;아무도 이상한 걸 안 하길 바라자&amp;rdquo; 접근방식보다 훨씬 낫습니다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;참고:&lt;/strong&gt; 샌드박싱은 현재 macOS와 Linux에서 사용 가능합니다. Windows 지원이 준비 중입니다 — WSL 같은 원격 시나리오는 작동합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="모노레포-커스터마이제이션-발견"&gt;모노레포 커스터마이제이션 발견&lt;/h2&gt;
&lt;p&gt;모노레포에서 작업하고 있다면 (솔직히 많은 엔터프라이즈 .NET 솔루션이 모노레포가 됩니다), 이것은 진짜 페인 포인트를 해결합니다.&lt;/p&gt;
&lt;p&gt;이전에는 레포의 하위 폴더를 열면 레포지토리 루트에 있는 &lt;code&gt;copilot-instructions.md&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, 커스텀 스킬을 VS Code가 찾지 못했습니다. 이제 &lt;code&gt;chat.useCustomizationsInParentRepositories&lt;/code&gt; 설정으로 &lt;code&gt;.git&lt;/code&gt; 루트까지 올라가서 모든 것을 발견합니다.&lt;/p&gt;
&lt;p&gt;팀이 모노레포의 모든 프로젝트에 걸쳐 에이전트 지시, 프롬프트 파일, 커스텀 도구를 공유할 수 있게 됩니다. 모두가 루트 폴더를 열 필요 없이.&lt;/p&gt;
&lt;h2 id="에이전트-디버깅을-위한-troubleshoot"&gt;에이전트 디버깅을 위한 /troubleshoot&lt;/h2&gt;
&lt;p&gt;커스텀 지시나 스킬을 설정한 후 왜 감지되지 않는지 궁금했던 적 있나요? 새로운 &lt;code&gt;/troubleshoot&lt;/code&gt; 스킬이 에이전트 디버그 로그를 읽고 무슨 일이 있었는지 알려줍니다 — 어떤 도구가 사용되거나 건너뛰어졌는지, 왜 지시가 로드되지 않았는지, 무엇이 느린 응답을 유발하는지.&lt;/p&gt;
&lt;p&gt;다음 설정으로 활성화하세요:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&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="nt"&gt;&amp;#34;github.copilot.chat.agentDebugLog.enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="nt"&gt;&amp;#34;github.copilot.chat.agentDebugLog.fileLogging.enabled&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&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;/troubleshoot why is my custom skill not loading?&lt;/code&gt;을 입력하면 됩니다.&lt;/p&gt;
&lt;p&gt;이 디버그 로그를 내보내기와 가져오기도 할 수 있어서, 뭔가 예상대로 작동하지 않을 때 팀과 공유하기 좋습니다.&lt;/p&gt;
&lt;h2 id="이미지와-바이너리-파일-지원"&gt;이미지와 바이너리 파일 지원&lt;/h2&gt;
&lt;p&gt;에이전트가 이제 디스크에서 이미지 파일과 바이너리 파일을 네이티브로 읽을 수 있습니다. 바이너리 파일은 hexdump 형식으로 표시되고, 이미지 출력(통합 브라우저의 스크린샷 등)은 캐러셀 뷰로 나타납니다.&lt;/p&gt;
&lt;p&gt;.NET 개발자의 경우: UI 버그의 스크린샷을 채팅에 붙여넣고 에이전트가 무엇이 잘못되었는지 이해하게 하거나, Blazor 컴포넌트 렌더링 출력을 분석하게 할 수 있습니다.&lt;/p&gt;
&lt;h2 id="자동-심볼-참조"&gt;자동 심볼 참조&lt;/h2&gt;
&lt;p&gt;작은 삶의 질 개선: 심볼 이름(클래스, 메서드 등)을 복사해서 채팅에 붙여넣으면, VS Code가 자동으로 &lt;code&gt;#sym:Name&lt;/code&gt; 참조로 변환합니다. 수동으로 추가하지 않아도 에이전트에 해당 심볼의 전체 컨텍스트를 제공합니다.&lt;/p&gt;
&lt;p&gt;일반 텍스트를 원하면 &lt;code&gt;Ctrl+Shift+V&lt;/code&gt;를 사용하세요.&lt;/p&gt;
&lt;h2 id="플러그인-활성화비활성화-가능"&gt;플러그인 활성화/비활성화 가능&lt;/h2&gt;
&lt;p&gt;이전에는 MCP 서버나 플러그인을 비활성화하려면 제거해야 했습니다. 이제 켜고 끌 수 있습니다 — 전역적으로도 워크스페이스별로도. 확장 뷰나 커스터마이제이션 뷰에서 우클릭하면 됩니다.&lt;/p&gt;
&lt;p&gt;npm과 pypi의 플러그인도 자동 업데이트가 가능하지만, 업데이트가 기기에서 새 코드를 실행하는 것을 의미하므로 먼저 승인을 요청합니다.&lt;/p&gt;
&lt;h2 id="마무리"&gt;마무리&lt;/h2&gt;
&lt;p&gt;VS Code 1.112는 확실히 에이전트 경험을 강하게 밀어붙이고 있습니다 — 더 많은 자율성, 더 나은 디버깅, 더 단단한 보안. .NET 개발자에게 통합 브라우저 디버깅과 Copilot CLI 개선이 두드러진 기능입니다.&lt;/p&gt;
&lt;p&gt;.NET 프로젝트를 위해 오토파일럿 모드에서 전체 Copilot CLI 세션을 아직 시도해보지 않았다면, 이번 릴리스가 시작하기 좋은 때입니다. 권한을 설정하고 맡기면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://code.visualstudio.com/updates/v1_112"&gt;VS Code 1.112 다운로드&lt;/a&gt; 또는 VS Code 내에서 &lt;strong&gt;도움말 &amp;gt; 업데이트 확인&lt;/strong&gt;으로 업데이트하세요.&lt;/p&gt;</content:encoded></item></channel></rss>