.NET 11 Preview 3 ์ถœ์‹œ

์›๋ฌธ: https://devblogs.microsoft.com/dotnet/dotnet-11-preview-3/

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—…๋ฐ์ดํŠธ

System.Text.Json: ์ด๋ฆ„ ์ง€์ • ๋ฐ ๋ฌด์‹œ ๊ธฐ๋ณธ๊ฐ’ ์ œ์–ด ์˜ต์…˜ ๊ฐ•ํ™”

Preview 3์—์„œ๋Š” System.Text.Json์˜ ๊ธฐ๋ณธ์ œ๊ณต ๋ช…๋ช… ๋ฐ ๋ฌด์‹œ ์˜ต์…˜์ด ํ™•์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์กด์˜ camel, snake, kebab ํ”„๋ฆฌ์…‹์— ๋”ํ•ด JsonNamingPolicy.PascalCase๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์œผ๋ฉฐ, [JsonNamingPolicy]๋ฅผ ํ†ตํ•ด ๊ฐœ๋ณ„ ๋ฉค๋ฒ„ ๋‹จ์œ„๋กœ ๋ช…๋ช… ์ •์ฑ…์„ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํ˜•์‹ ์ˆ˜์ค€์˜ [JsonIgnore(Condition = ...)]๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์˜ ๊ธฐ๋ณธ ๋ฌด์‹œ ๋™์ž‘์„ ํ•œ ๊ณณ์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (dotnet/runtime #124644, dotnet/runtime #124645, dotnet/runtime #124646).

using System.Text.Json;
using System.Text.Json.Serialization;

[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public sealed class EventData
{
    [JsonNamingPolicy(JsonKnownNamingPolicy.CamelCase)]
    public string EventName { get; set; } = "";

    public string? Notes { get; set; }
}

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.PascalCase
};

Zstandard: System.IO.Compression์œผ๋กœ ์ด๋™, ZIP ์ฝ๊ธฐ ์‹œ CRC32 ๊ฒ€์ฆ

์ด์ „์— .NET 11์—์„œ ์†Œ๊ฐœ๋˜์—ˆ๋˜ Zstandard API๊ฐ€ ์ด์ œ System.IO.Compression์— ํฌํ•จ๋˜์–ด DeflateStream, GZipStream, BrotliStream๊ณผ ๋‚˜๋ž€ํžˆ์œ„์น˜ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค (dotnet/runtime #124634). ๋˜ํ•œ Preview 3์—์„œ๋Š” ZIP ํ•ญ๋ชฉ์„ ์ฝ์„ ๋•Œ CRC32 ๊ฒ€์ฆ์ด ์ถ”๊ฐ€๋˜์–ด, ์†์ƒ๋œ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋ฌต์ธํ•˜๋Š” ๋Œ€์‹  InvalidDataException์œผ๋กœ ๋”๋น ๋ฅด๊ฒŒ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค(dotnet/runtime #124766). ์ด์ „ ํ”„๋ฆฌ๋ทฐ ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉ ์ค‘์ด์—ˆ๋‹ค๋ฉด ๋ณ„๋„์˜ System.IO.Compression.Zstandard ํŒจํ‚ค์ง€ ์ฐธ์กฐ๋ฅผ ์ œ๊ฑฐํ•˜์„ธ์š”.

-<PackageReference Include="System.IO.Compression.Zstandard" />

SafeFileHandle ๋ฐ RandomAccess: ํŒŒ์ดํ”„ ์ง€์› ํ™•์žฅ

Preview 3์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์ €์ˆ˜์ค€ I/O ์—…๋ฐ์ดํŠธ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. SafeFileHandle.Type์€ ํ•ธ๋“ค์ดํŒŒ์ผ, ํŒŒ์ดํ”„, ์†Œ์ผ“, ๋””๋ ‰ํ„ฐ๋ฆฌ ๋˜๋Š” ๊ธฐํƒ€ OS ๊ฐ์ฒด์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค(dotnet/runtime #124561). SafeFileHandle.CreateAnonymousPipe๋Š” ๊ฐ๋๋‹จ์˜ ๋น„๋™๊ธฐ ๋™์ž‘์„ ๋ถ„๋ฆฌํ•˜์—ฌ ํŒŒ์ดํ”„ ์Œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์œผ๋ฉฐ(dotnet/runtime #125220), RandomAccess. Read/Write๋Š” ํŒŒ์ดํ”„์ฒ˜๋Ÿผseek์ด ๋ถˆ๊ฐ€๋Šฅํ•œ ํ•ธ๋“ค์—์„œ๋„ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค(dotnet/runtime #125512). Windows์—์„œ๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋œstdout/stderr์— ๋Œ€ํ•ด ์˜ค๋ฒ„๋žฉ I/O๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์–ด, ๋งŽ์€ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋‹ค๋ฃจ๋Š” ์•ฑ์—์„œ ์Šค๋ ˆ๋“œ ํ’€ ๋ธ”๋กœํ‚น์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค (dotnet/runtime #125643).

using Microsoft.Win32.SafeHandles;
using System.IO;

SafeFileHandle.CreateAnonymousPipe(out SafeFileHandle readEnd, out SafeFileHandle writeEnd,
    asyncReads: true, asyncWrites: false);

Console.WriteLine(readEnd.Type); // Pipe

์ •๊ทœ์‹: ๋ชจ๋“  ์œ ๋‹ˆ์ฝ”๋“œ ์ค„๋ฐ”๊ฟˆ ์‹œํ€€์Šค ์ธ์‹

์ƒˆ๋กœ์šด RegexOptions.AnyNewLine ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ^, $, .๊ฐ€ \\n๋ฟ๋งŒ ์•„๋‹ˆ๋ผ์ „์ฒด ์œ ๋‹ˆ์ฝ”๋“œ ์ค„ ๋ฐ”๊ฟˆ ๋ฌธ์ž ์ง‘ํ•ฉ์„ ์ค„ ๋์œผ๋กœ ์ทจ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค(dotnet/runtime #124701). ์ด๋Š” Windows, Unix ๋ฐ ์œ ๋‹ˆ์ฝ”๋“œ ํŠน์ˆ˜ ์ค„ ๋ฐ”๊ฟˆ์ด ํ˜ผํ•ฉ๋  ์ˆ˜ ์žˆ๋Š” ํ…์ŠคํŠธ๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. Preview 3์—๋Š” ์ผ๋ฐ˜์ ์ธ ์ •๊ทœ์‹ ํŒจํ„ด์— ๋Œ€ํ•œ ์ตœ์ ํ™” ๊ฐœ์„  ์‚ฌํ•ญ๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

using System.Text.RegularExpressions;

string text = "line1\\r\\nline2\\u0085line3\\u2028line4";

var matches = Regex.Matches(
    text,
    @"^line\\d$",
    RegexOptions.Multiline | RegexOptions.AnyNewLine);

ํ˜ธํ™˜์„ฑ ํŒŒ๊ดด ๋ณ€๊ฒฝ ์‚ฌํ•ญ

  • ZipArchive๋Š” ์ด์ œํ•ญ๋ชฉ์„ ์ฝ๋Š” ๋™์•ˆ CRC32๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ์ด์ „์—๋Š” ํ†ต๊ณผ๋˜๋˜ ์†์ƒ๋˜๊ฑฐ๋‚˜ ์ž˜๋ฆฐ ์•„์นด์ด๋ธŒ๊ฐ€ ์ด์ œ InvalidDataException์„ ๋ฐœ์ƒ์‹œํ‚ฌ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/runtime #124766).

  • ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ BackgroundService ์˜ˆ์™ธ๋Š” ์ด์ œ ์กฐ์šฉํžˆ ๋ฌด์‹œ๋˜์ง€ ์•Š๊ณ  ํ˜ธ์ŠคํŠธ๋ฅผ ์ค‘์ง€์‹œํ‚ต๋‹ˆ๋‹ค(dotnet/runtime #124863).

  • ์„œ๋ฒ„์˜ ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ ๊ฒ€์ฆ ์ค‘ ์˜จ๋ผ์ธ AIA(Authority Information Access) ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„ํ™œ์„ฑํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์˜จ๋ผ์ธ AIA ๊ฐ€์ ธ์˜ค๊ธฐ์— ์˜์กดํ•˜๊ณ  ์žˆ์—ˆ๋‹ค๋ฉด ๊ฒ€์ฆ ๊ตฌ์„ฑ์„ ๋‹ค์‹œ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค(dotnet/runtime #125049).

  • TarWriter๋Š” ๋™์ผํ•œํ•˜๋“œ ๋งํฌ ํŒŒ์ผ์ด ์•„์นด์ด๋ธŒ์— ์—ฌ๋Ÿฌ ๋ฒˆ ํฌํ•จ๋  ๋•Œ HardLink ํ•ญ๋ชฉ์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค(dotnet/runtime #123874).

๋ฒ„๊ทธ ์ˆ˜์ • (Bug fixes)

  • ์˜์กด์„ฑ ์ฃผ์ž… (Dependency injection)

    • ํŒฉํ† ๋ฆฌ ๊ธฐ๋ฐ˜ ์ˆœํ™˜ ์ข…์†์„ฑ์€ ์ด์ œ ์œ ์šฉํ•˜์ง€ ์•Š์€ ์˜ค๋ฅ˜ ๋Œ€์‹  ๋ช…ํ™•ํ•œ InvalidOperationException์„ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค(dotnet/runtime #124331).
  • ๋กœ๊น… (Logging)

    • ๋กœ๊น… ์†Œ์Šค ์ƒ์„ฑ๊ธฐ๊ฐ€ ์ด์ œ ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค(dotnet/runtime #124638).
  • ๋„คํŠธ์›Œํ‚น (Networking)

    • Windows์˜ HttpListener์—์„œ HTTP.sys ์ปค๋„ ์‘๋‹ต ๋ฒ„ํผ๋ง์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/runtime #124720).

๋Ÿฐํƒ€์ž„ ์—…๋ฐ์ดํŠธ

Runtime async: ๋ฏธ๋ฆฌ ๋ณด๊ธฐ API ์˜ตํŠธ์ธ ์š”๊ตฌ ์‚ฌํ•ญ ์ œ๊ฑฐ

Runtime async๋Š” ์—ฌ์ „ํžˆ runtime-async=on ๊ธฐ๋Šฅ ์Šค์œ„์น˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ, Preview 3๋ถ€ํ„ฐ๋Š” API์— ์ ์šฉ๋˜์—ˆ๋˜ [RequiresPreviewFeatures] ๊ฒŒ์ดํŠธ๊ฐ€ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ net11.0 ํ”„๋กœ์ ํŠธ์—์„œ runtime-async=on์„ ์ผœ๊ธฐ์œ„ํ•ด์„œ๋งŒ \\<EnablePreviewFeatures>true\\</EnablePreviewFeatures>๋ฅผ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค(dotnet/runtime #124488).

๋˜ํ•œ ์ด๋ฒˆ ํ”„๋ฆฌ๋ทฐ์—๋Š” NativeAOT ๋ฐ ReadyToRun ์ง€์›๋„ ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/runtime #123952, dotnet/runtime #124203, dotnet/runtime #125420). ํ›„์† ์ž‘์—…์œผ๋กœ continuation ๊ฐ์ฒด๋ฅผ ๋ณด๋‹ค ์ ๊ทน์ ์œผ๋กœ ์žฌ์‚ฌ์šฉํ•˜๊ณ , ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€ ๋กœ์ปฌ ๊ฐ’์„ ์ €์žฅํ•˜์ง€ ์•Š๋„๋ก ํ•˜์—ฌ async ์ค‘์‹ฌ ์ฝ”๋“œ์—์„œ ํ• ๋‹น(alloc) ๋ถ€ํ•˜๋ฅผ ์ค„์˜€์Šต๋‹ˆ๋‹ค (dotnet/runtime #125556, dotnet/runtime #125615).

 <PropertyGroup>
   <Features>runtime-async=on</Features>
-  <EnablePreviewFeatures>true</EnablePreviewFeatures>
 </PropertyGroup>

JIT ์ตœ์ ํ™”: switch, ๊ฒฝ๊ณ„ ๊ฒ€์‚ฌ, ํ˜• ๋ณ€ํ™˜ ๊ฐœ์„ 

Preview 3๋Š” ์†Œ์Šค ์ฝ”๋“œ ๋ณ€๊ฒฝ ์—†์ด๋„ ์ผ๋ฐ˜ ์ฝ”๋“œ์— ์ด์ ์„ ์ œ๊ณตํ•˜๋Š” JIT ๊ฐœ์„  ์‚ฌํ•ญ์„ ๊ณ„์†ํ•ด์„œ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์ค‘ ๋Œ€์ƒ switch ํ‘œํ˜„์‹๊ณผ ๊ฐ™์€ ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ด ๋” ๋‹จ์ˆœํ•œ ๋ถ„๊ธฐ ์—†๋Š” ๊ฒ€์‚ฌ ํ˜•ํƒœ๋กœ ์ ‘ํ˜€์ง€๋ฉฐ(dotnet/runtime #124567), ์ธ๋ฑ์Šค-from-end ์ ‘๊ทผ ๋ฐฉ์‹์—์„œ ๋ถˆํ•„์š”ํ•œ ๊ฒฝ๊ณ„ ๊ฒ€์‚ฌ๋ฅผ ๋” ๋งŽ์ด ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์œผ๋ฉฐ(dotnet/runtime #124571), AVX-512 ์ด์ „์˜ x86 ํ•˜๋“œ์›จ์–ด์—์„œ uint โ†’ float/double ํ˜• ๋ณ€ํ™˜์ด ๋” ๋นจ๋ผ์กŒ์Šต๋‹ˆ๋‹ค(dotnet/runtime #124114).

์ปดํŒŒ์ผ๋Ÿฌ ์ธก์˜ ์ง€์› ์ž‘์—…์„ ํ†ตํ•ด JIT๊ฐ€ ์ด๋Ÿฌํ•œ ์ถ•์•ฝ์„ ๋” ๋งŽ์€ ์‹ค์ œ ์ฝ”๋“œ์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

bool isSmall = x is 0 or 1 or 2 or 3 or 4;
int tail = values[^1] + values[^2];
double d = someUint;

๋ธŒ๋ผ์šฐ์ € ๋ฐ WebAssembly: WebCIL ๋ฐ ๋””๋ฒ„๊น… ๊ฐœ์„ 

Preview 3๋Š” WebCIL ํŽ˜์ด๋กœ๋“œ ๋กœ๋”ฉ ์ง€์›์„ ํฌํ•จํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €/CoreCLR ์ž‘์—…์„ ํ™•์žฅํ–ˆ์œผ๋ฉฐ(dotnet/runtime #124758, dotnet/runtime #124904), ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ์‹ฌ๋ณผ ๋ฐ ์Šคํƒ ํŠธ๋ ˆ์ด์Šค ํ’ˆ์งˆ์„ ๊ฐœ์„ ํ–ˆ์œผ๋ฉฐ(dotnet/runtime #124500, dotnet/runtime #124483), JS ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด float[], Span<float>, ArraySegment<float>๋ฅผ ๋” ์ง์ ‘์ ์œผ๋กœ ๋งˆ์ƒฌ๋งํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/runtime #123642).

ํ˜ธํ™˜์„ฑ ๊นจ๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ (Breaking changes)

  • NativeAOT ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถœ๋ ฅ์€ ์ด์ œ Unix์—์„œ ๊ด€๋ก€์ ์ธ lib ์ ‘๋‘์‚ฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์Šคํฌ๋ฆฝํŠธ๊ฐ€ MyLib.so๋ฅผ ๊ธฐ๋Œ€ํ–ˆ๋‹ค๋ฉด libMyLib.so๋ฅผ ์ฐพ๋„๋ก์ˆ˜์ •ํ•˜์„ธ์š” (dotnet/runtime #124611).

๋ฒ„๊ทธ ์ˆ˜์ • (Bug fixes)

  • JIT

  • VM / ๋Ÿฐํƒ€์ž„ ๋น„๋™๊ธฐ

    • runtime-async ์žฌ๊ฐœ(resumption) ์Šคํ…์˜ ๊ฒฝํ•ฉ ๋ˆ„์ˆ˜(race leak)์™€, ๊ฒฝํ•ฉ ์‹œ ๊ต์ฐฉ ์ƒํƒœ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ž ๊ธˆ(lock) ์ˆ˜์ค€ ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/runtime #125407, dotnet/runtime #125675).

SDK ์—…๋ฐ์ดํŠธ

CLI์—์„œ ์†”๋ฃจ์…˜ ํ•„ํ„ฐ๋ฅผ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

dotnet sln ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ CLI์—์„œ ์ง์ ‘ ์†”๋ฃจ์…˜ ํ•„ํ„ฐ(.slnf)๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/sdk #51156). ์ด๋ฅผ ํ†ตํ•ด ๋Œ€๊ทœ๋ชจ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ์ฃผ ์†”๋ฃจ์…˜์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ์ผ๋ถ€ ํ”„๋กœ์ ํŠธ๋งŒ ๋กœ๋“œํ•˜๊ฑฐ๋‚˜ ๋นŒ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†”๋ฃจ์…˜ ํ•„ํ„ฐ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ฌธ์„œ์—์„œ ํ™•์ธํ• ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

dotnet new slnf --name MyApp.slnf
dotnet sln MyApp.slnf add src/Lib/Lib.csproj
dotnet sln MyApp.slnf list
dotnet sln MyApp.slnf remove src/Lib/Lib.csproj

ํŒŒ์ผ ๊ธฐ๋ฐ˜ ์•ฑ์„ ์—ฌ๋Ÿฌ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

ํŒŒ์ผ ๊ธฐ๋ฐ˜ ์•ฑ์ด ์ด์ œ #:include๋ฅผ ์ง€์›ํ•˜๋ฏ€๋กœ, ํŒŒ์ผ ๊ธฐ๋ฐ˜ ์›Œํฌํ”Œ๋กœ๋ฅผ ์œ ์ง€ํ•œ ์ฑ„๋กœ ๊ณต์šฉ ํ—ฌํผ๋ฅผ ๋ณ„๋„์˜ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/sdk #52347). Roslyn์€ ํ•ด๋‹น ์ง€์‹œ๋ฌธ์— ๋Œ€ํ•œ ํŽธ์ง‘๊ธฐ ์ž๋™ ์™„์„ฑ ๊ธฐ๋Šฅ๋„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/roslyn #82625).

#:include helpers.cs
#:include models/customer.cs

Console.WriteLine(Helpers.FormatOutput(new Customer()));

dotnet run-e๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…๋ น์ค„์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

dotnet run -e FOO=BAR๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด๋กœ์ปฌ ์•ฑ ์‹คํ–‰ ์‹œ ์…ธ ์ƒํƒœ๋ฅผ ๋‚ด๋ณด๋‚ด๊ฑฐ๋‚˜ ๋Ÿฐ์น˜ ํ”„๋กœํ•„์„ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋„ ๋ช…๋ น์ค„์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/sdk #52664). ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ„๋‹จํ•œ ์„ค์ • ์žฌ์ •์˜ ์‚ฌํ•ญ์„ ์…ธ ์ƒํƒœ๋‚˜ ๋Ÿฐ์น˜ ์„ค์ • ๋Œ€์‹  ๋ช…๋ น์ค„์— ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์œผ๋กœ ์ „๋‹ฌ๋œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” MSBuild ๋กœ์ง์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก RuntimeEnvironmentVariable ํ•ญ๋ชฉ์œผ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

dotnet run -e ASPNETCORE_ENVIRONMENT=Development -e LOG_LEVEL=Debug

dotnetwatch์— Aspire, ํฌ๋ž˜์‹œ ๋ณต๊ตฌ ๋ฐ Windows ๋ฐ์Šคํฌํ†ฑ ๊ฐœ์„  ์‚ฌํ•ญ์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Preview 3์—๋Š” ์žฅ์‹œ๊ฐ„ ๋กœ์ปฌ ๊ฐœ๋ฐœ ๋ฃจํ”„๋ฅผ ์œ„ํ•œ ์—ฌ๋Ÿฌ dotnet watch ์—…๋ฐ์ดํŠธ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. Aspire ์•ฑ ํ˜ธ์ŠคํŠธ์™€ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ๊ณ (dotnet/sdk #53192), ์ถฉ๋Œ ๋ฐœ์ƒ ํ›„ ๊ด€๋ จ ํŒŒ์ผ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๊ฐ์ง€๋˜๋ฉด ์ž๋™์œผ๋กœ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๋ฉฐ(dotnet/sdk #53314), WinForms ๋ฐ WPF์™€ ๊ฐ™์€ Windows ๋ฐ์Šคํฌํ†ฑ ์•ฑ์—์„œ Ctrl+C ์ฒ˜๋ฆฌ๋ฅผ ๋” ์›ํ™œํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค(dotnet/sdk #53127).

๊ธฐํƒ€ CLI ๊ฐœ์„  ์‚ฌํ•ญ

  • dotnet format์€ ์ด์ œ๋‹ค์ค‘ ๋Œ€์ƒ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด-framework์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค(dotnet/sdk #53202).

  • MTP๋ชจ๋“œ์˜ dotnet test๋Š” ์ด์ œ-artifacts-path๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค(dotnet/sdk #53353).

  • dotnet toolexec ๋ฐ dnx๊ฐ€ ๋”์ด์ƒ ์ถ”๊ฐ€ ์Šน์ธ ํ”„๋กฌํ”„ํŠธ๋กœ ์ธํ•ด ์ค‘์ง€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(dotnet/sdk #52956).

๋ฒ„๊ทธ ์ˆ˜์ •

  • ๊ธ€๋กœ๋ฒŒ ๋ฐ ๋กœ์ปฌ ๋„๊ตฌ์—๋Œ€ํ•ด dotnet tool install --source๊ฐ€ ์ ์šฉ๋˜์ง€์•Š๋˜ ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/sdk #52787).

  • dotnet remove package๊ฐ€ project์ธ์ˆ˜๋ฅผ ์ธ์‹ํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/sdk #53401).

  • dotnet run์ด ์„œ๋กœ๋‹ค๋ฅธ ๋Œ€์ƒ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•  ๋•Œ๋ฐœ์ƒํ•˜๋Š” NETSDK1005 ์˜ค๋ฅ˜๋ฅผ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/sdk #53523).

  • dotnet workload repair๋Š” ํ˜•์‹์ด์ž˜๋ชป๋˜์—ˆ๊ฑฐ๋‚˜ ์†์ƒ๋œ ์›Œํฌ๋กœ๋“œ ์„ธํŠธ๋ฅผ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/sdk #52434).

  • -self-contained ์˜ต์…˜์ด๋” ์ด์ƒํ•ญ์ƒ true๋ฅผ ์˜๋ฏธํ•˜์ง€์•Š๊ณ , ์ „๋‹ฌ๋œ ๊ฐ’์„ ๊ตฌ๋ฌธ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค(dotnet/sdk #52333).

C# ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด

์œ ๋‹ˆ์˜จ(union) ์œ ํ˜• ์ง€์›

Preview2์—์„œ ์œ ๋‹ˆ์˜จ ์œ ํ˜•์— ๋Œ€ํ•œ ์ปดํŒŒ์ผ๋Ÿฌ ์ง€์›์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Preview 3์—์„œ๋Š” ์œ ๋‹ˆ์˜จ ์œ ํ˜•์„ ๋‹ค๋ฃฐ ๋•Œ์˜ IDE ์ง€์›์ด ๋”์šฑ ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์œ ๋‹ˆ์˜จ ์œ ํ˜•์— ๋Œ€ํ•œ ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ๊ณผ C# ๊ฐ€์ด๋“œ์—์„œ ํ™•์ธํ• ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โ€œ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅโ€ ํŽ˜์ด์ง€์—๋Š” ์–ธ์–ด ์ฐธ์กฐ ๋งํฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์กฐ๋งŒ๊ฐ„ ํŠœํ† ๋ฆฌ์–ผ ๋“ฑ ์ถ”๊ฐ€ ์ž๋ฃŒ ๋งํฌ๋„ ์ถ”๊ฐ€๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ Preview 3์—์„œ๋Š” UnionAttribute ํƒ€์ž…๊ณผ IUnion ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ํด๋ฆฌํ•„์„ ์ง์ ‘ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

`namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)] public sealed class UnionAttribute : Attribute;

public interface IUnion
{
    object? Value { get; }
}

}`

ASP .NET Core

Zstandard ์‘๋‹ต ์••์ถ• ๋ฐ ์š”์ฒญ ์••์ถ• ํ•ด์ œ

ASP.NET Core๋Š” ์‘๋‹ต ์••์ถ•๊ณผ ์š”์ฒญ ์••์ถ• ํ•ด์ œ ๋ชจ๋‘์—์„œ Zstandard(zstd)๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค(dotnet/aspnetcore #65479). ๊ธฐ์กด์˜ response-compression ๋ฐ request-decompression ๋ฏธ๋“ค์›จ์–ด์— zstd ์ง€์›์ด ์ถ”๊ฐ€๋˜์—ˆ์œผ๋ฉฐ, ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCompression();
builder.Services.AddRequestDecompression();
builder.Services.Configure<ZstandardCompressionProviderOptions>(options =>
{
    options.CompressionOptions = new ZstandardCompressionOptions
    {
        Quality = 6 // 1-22, ๋†’์„์ˆ˜๋ก ๋” ์ž˜ ์••์ถ•๋˜์ง€๋งŒ ๋А๋ ค์ง‘๋‹ˆ๋‹ค
    };
});

์ด ๊ธฐ์—ฌ์— ๋Œ€ํ•ด @manandre ๋‹˜๊ป˜ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

Virtualize: ๋Ÿฐํƒ€์ž„์—์„œ ๋†’์ด ๊ฐ€๋ณ€ ํ•ญ๋ชฉ์— ์ ์‘

Blazor์˜ Virtualize<TItem> ์ปดํฌ๋„ŒํŠธ๋Š” ๋” ์ด์ƒ ๋ชจ๋“  ํ•ญ๋ชฉ์˜ ๋†’์ด๊ฐ€ ๋™์ผํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋Ÿฐํƒ€์ž„์—์„œ ์ธก์ •๋œ ํ•ญ๋ชฉ ํฌ๊ธฐ์— ๋งž์ถฐ ์ ์‘ํ•˜๋ฏ€๋กœ, ํ•ญ๋ชฉ ๋†’์ด๊ฐ€ ๋‹ค์–‘ํ•œ ๊ฒฝ์šฐ์—๋„ ์ž˜๋ชป๋œ ์—ฌ๋ฐฑ ๋ฐ ์Šคํฌ๋กค ๋ฌธ์ œ๋ฅผ ์ค„์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ํ‰๊ท  ํ•ญ๋ชฉ ๋†’์ด ๊ณ„์‚ฐ์˜ ์ •ํ™•๋„๋ฅผ ๋†’์ด๊ธฐ ์œ„ํ•ด OverscanCount์˜ ๊ธฐ๋ณธ๊ฐ’์ด 3์—์„œ 15๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ž ์žฌ์ ์ธ ์„ฑ๋Šฅ ์˜ํ–ฅ ๊ฐ€๋Šฅ์„ฑ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด QuickGrid๋Š” OverscanCount๋ฅผ ๊ณ„์† 3์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค(dotnet/aspnetcore #64964).

<Virtualize Items="messages" Context="message">
    <article class="message-card">
        <h4>@message.Author</h4>
        <p>@message.Text</p>
    </article>
</Virtualize>

HTTP/3: ๋” ์ด๋ฅธ ์‹œ์ ์— ์š”์ฒญ ์ฒ˜๋ฆฌ ์‹œ์ž‘

Kestrel์€ ์ด์ œ ์ œ์–ด ์ŠคํŠธ๋ฆผ๊ณผ SETTINGS ํ”„๋ ˆ์ž„์„ ๋จผ์ € ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  HTTP/3 ์š”์ฒญ ์ฒ˜๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•˜๋ฏ€๋กœ, ์ƒˆ ์—ฐ๊ฒฐ์—์„œ ์ฒซ ๋ฒˆ์งธ ์š”์ฒญ์˜ ์ง€์—ฐ ์‹œ๊ฐ„์„ ์ค„์ž…๋‹ˆ๋‹ค(dotnet/aspnetcore #65399).

๋ฒ„๊ทธ ์ˆ˜์ • (Bug fixes)

  • Blazor

    • Virtualize์—์„œ null์ฐธ์กฐ ์˜ค๋ฅ˜๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/aspnetcore #65207).

    • overflow-x๊ฐ€ ์„ค์ •๋œ๊ฒฝ์šฐ์˜ scroll-container ๊ฐ์ง€๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/aspnetcore #65744).

    • ๊ฒŒ์‹œ๋œ Blazor WebAssembly ์•ฑ์—์„œ Web Worker ํ…œํ”Œ๋ฆฟ ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/aspnetcore #65885).

    • TempData ์ง€์—ฐ ๋กœ๋”ฉ ์ˆ˜์ •: Get, Remove, Keep ๋ฐ ์—ด๊ฑฐ(enumeration) ๋™์ž‘์ด ์ด์ œ ์ง€์—ฐ ๋กœ๋”ฉ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค (dotnet/aspnetcore #65722).

    • ResourceCollectionProvider์—์„œ IJSObjectReference ๋ˆ„์ˆ˜๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/aspnetcore #65606).

    • Blazor ๋ฆฌ์†Œ์Šค ์ปฌ๋ ‰์…˜ ์—”๋“œํฌ์ธํŠธ์˜ ์บ์‹œ ํ—ค๋”์— no-transform์ด ํฌํ•จ๋˜๋„๋กํ•˜๊ณ , Vary ํ—ค๋”๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/aspnetcore #65513).

  • ๋ฐ์ดํ„ฐ ๋ณดํ˜ธ

    • .NET Framework ๋Œ€์ƒ์—์„œ ManagedAuthenticatedEncryptor ํ•ด์‹œ ๊ณ„์‚ฐ ๋ฐ ๋น„๊ต ๋™์ž‘์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65890).
  • HTTP / Kestrel

    • HTTP/2 HEADERS ํ”„๋ ˆ์ž„์˜ ํŒจ๋”ฉ ๊ธธ์ด ๊ฒ€์ฆ์ด PRIORITY ํ”Œ๋ž˜๊ทธ ๋ฐ”์ดํŠธ๋ฅผ ๊ณ ๋ คํ•˜๋„๋ก ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65729).

    • CONTINUATION ํ”„๋ ˆ์ž„์— ๊ฑธ์ณ ํŠธ๋ ˆ์ผ๋Ÿฌ๊ฐ€ ๋ถ„ํ• ๋  ๋•Œ ๋ฐœ์ƒํ•˜๋˜ HTTP/2 Content-Length ๋ถˆ์ผ์น˜๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65765).

    • HPACK/QPACK ๋””์ฝ”๋”๊ฐ€ MaxRequestHeaderFieldSize ๋ฌธ์„œ์— ๋”ฐ๋ผ ๋น„์••์ถ• ํ—ค๋” ํฌ๊ธฐ ์ œํ•œ์„ ๊ฒ€์ฆํ•˜๋„๋ก ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65771).

    • RFC 8446์— ๋”ฐ๋ผ TlsListener์—์„œ ์ง€๋‚˜์น˜๊ฒŒํฐ TLS ๋ ˆ์ฝ”๋“œ ๊ธธ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/aspnetcore #65558).

    • HTTP ์‘๋‹ต์— ๋Œ€ํ•œ ReasonPhrase ๊ฒ€์ฆ์„ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65797).

  • JSON ํŒจ์น˜

    • ๋ฐฐ์—ด ์š”์†Œ ๋‚ด๋ถ€ ์†์„ฑ์— ๋Œ€ํ•œ JsonPatchDocument ์ž‘์—…์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65470).
  • ๋ฏธ๋“ค์›จ์–ด

    • ์š”์ฒญ์ด ์บ์‹œ ์“ฐ๊ธฐ์™€ ๊ฐ™์€ ํ‹ฑ์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ์บ์‹œ๋œ ํ•ญ๋ชฉ์„ ์ž˜๋ชป ๊ฑฐ๋ถ€ํ•˜๋˜ ์ถœ๋ ฅ ์บ์‹ฑ ์‹ ์„ ๋„ ํ™•์ธ์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65659).
  • ์ตœ์†Œ API

    • JsonElement, Dictionary์™€ ๊ฐ™์ด ์ธ๋ฑ์„œ๊ฐ€์žˆ๋Š” ์œ ํ˜•์„ ๋งŒ๋‚ฌ์„ ๋•Œ ๊ฒ€์ฆ ์†Œ์Šค ์ƒ์„ฑ๊ธฐ๊ฐ€ ์ถฉ๋Œํ•˜๋˜ ๋ฌธ์ œ๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65432).
  • SignalR

    • StatefulReconnect์—์„œ ์ทจ์†Œ์ฒ˜๋ฆฌ(cancellation handling)๊ฐ€ ๋” ์ ๊ทน์ ์œผ๋กœ ์ž‘๋™ํ•˜๋„๋ก ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค (dotnet/aspnetcore #65732).

MAUI

Maps: ํด๋Ÿฌ์Šคํ„ฐ๋ง, ์Šคํƒ€์ผ๋ง, ๋”์šฑ ํ’๋ถ€ํ•œ ์ƒํ˜ธ์ž‘์šฉ API ์ถ”๊ฐ€

Preview 3์—์„œ Map ์ปจํŠธ๋กค์€ ๋Œ€๊ทœ๋ชจ ๊ธฐ๋Šฅ ํ™•์žฅ์„ ๊ฑฐ์ณค์Šต๋‹ˆ๋‹ค. ํ•€ ํด๋Ÿฌ์Šคํ„ฐ๋ง, ์‚ฌ์šฉ์ž ์ง€์ • ํ•€ ์•„์ด์ฝ˜, ์‚ฌ์šฉ์ž ์ง€์ • JSON ์Šคํƒ€์ผ๋ง, MapLongClicked, ์›ยท๋‹ค๊ฐํ˜•ยทํด๋ฆฌ๋ผ์ธ ํด๋ฆญ ์ด๋ฒคํŠธ, MapElement.IsVisible ๋ฐ ZIndex, ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์˜ ์ •๋ณด ์ฐฝ ์ œ์–ด, ๋” ๋ถ€๋“œ๋Ÿฌ์šด ์˜์—ญ ๋ณ€๊ฒฝ, ๋” ํ’๋ถ€ํ•œ ์‚ฌ์šฉ์ž ์œ„์น˜ ์ด๋ฒคํŠธ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค (dotnet/maui #29101, dotnet/maui #33831, dotnet/maui #33950, dotnet/maui #33982, dotnet/maui #33985, dotnet/maui #33792, dotnet/maui #33799, dotnet/maui #33991, dotnet/maui #33993). ์ด API ๋•๋ถ„์— ํ”Œ๋žซํผ๋ณ„ ๊ตฌํ˜„์œผ๋กœ ๋˜๋Œ์•„๊ฐ€์ง€ ์•Š๊ณ ๋„ ๊ณ ๋ฐ€๋„์ด๋ฉฐ ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒํ•œ ์ง€๋„ ๊ฒฝํ—˜์„ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<maps:Map IsClusteringEnabled="True"
          MapLongClicked="OnMapLongClicked">
    <maps:Pin Label="Seattle"
              Location="47.6062,-122.3321"
              ClusteringIdentifier="stores"
              ImageSource="store.png" />
</maps:Map>

XAML ๋ฐ ์Šคํƒ€์ผ๋ง ๊ฐœ์„ : ์‹œ์ž‘ ์‹œ ์ž‘์—… ๊ฐ์†Œ ๋ฐ ๋ฐ˜๋ณต ์†๋„ ํ–ฅ์ƒ

XAML ์†Œ์Šค ์ƒ์„ฑ์ด ์ด์ œ ResourceDictionary ํ•ญ๋ชฉ์„ ํŒฉํ† ๋ฆฌ๋กœ ๋“ฑ๋กํ•˜๊ณ , ํŽ˜์ด์ง€ ์‹œ์ž‘ ์‹œ ๋ชจ๋“  ์Šคํƒ€์ผ๊ณผ ๋ธŒ๋Ÿฌ์‹œ๋ฅผ ์ฆ‰์‹œ ์ƒ์„ฑํ•˜๋Š” ๋Œ€์‹  ํ•„์š”ํ•  ๋•Œ(on demand) ๋กœ๋“œํ•˜๋„๋ก ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/maui #33826). ๋˜ํ•œ Preview 3์—์„œ๋Š” ์•”์‹œ์  XAML ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์„ ์–ธ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋˜์—ˆ์œผ๋ฉฐ, Hot Reload ๋˜๋Š” ๋™์  UI ์—…๋ฐ์ดํŠธ ์ค‘์— ๋ณ€๊ฒฝ๋œ ์Šคํƒ€์ผ๊ณผ ์‹œ๊ฐ์  ์ƒํƒœ๋ฅผ ๋‹ค์‹œ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ช…์‹œ์  API๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์•ฑ์ด ์Šคํƒ€์ผ์‹œํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ MAUI CSS๋ฅผ ํŠธ๋ฆฌ๋ฐํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์•ฑ ํฌ๊ธฐ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/maui #33834, dotnet/maui #34723, dotnet/maui #33160).

ํŠนํžˆ,InvalidateStyle()๋ฐ VisualStateManager.InvalidateVisualStates()๋Š” ํˆด๋ง ๋ฐ ์•ฑ ์ฝ”๋“œ์—์„œ ์š”์†Œ ํŠธ๋ฆฌ๋ฅผ ๋‹ค์‹œ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ์ธํ”Œ๋ ˆ์ด์Šค ์Šคํƒ€์ผ ๋ฐ ์‹œ๊ฐ์  ์ƒํƒœ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋‹ค์‹œ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ช…์‹œ์ ์ธ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

<ContentPage.Resources>
    <Style x:Key="PrimaryButtonStyle" TargetType="Button">
        <Setter Property="Padding" Value="12,8" />
    </Style>
</ContentPage.Resources>

LongPressGestureRecognizer๊ฐ€ ์ด์ œ .NET MAUI์— ๋‚ด์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค

.NET MAUI์—๋Š” ์ด์ œ ํ”Œ๋žซํผ ์ „๋ฐ˜์— ๊ฑธ์ณ ์ง€์† ์‹œ๊ฐ„, ์ด๋™ ์ž„๊ณ„๊ฐ’, ์ƒํƒœ ๋ณ€๊ฒฝ ๋ฐ ๋ช…๋ น์„ ์ง€์›ํ•˜๋Š”๋‚ด์žฅ LongPressGestureRecognizer๊ฐ€ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/maui #33432). ์ด๋ฅผ ํ†ตํ•ด ํˆดํ‚ท ๋™์ž‘์ด๋‚˜ ์‚ฌ์šฉ์ž ์ง€์ • ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š” ์—†์ด ๊ธธ๊ฒŒ ๋ˆ„๋ฅด๊ธฐ ์ƒํ˜ธ ์ž‘์šฉ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<Image Source="avatar.png">
    <Image.GestureRecognizers>
        <LongPressGestureRecognizer
            MinimumPressDuration="750"
            Command="{Binding ShowContextMenuCommand}" />
    </Image.GestureRecognizers>
</Image>

ํ”Œ๋žซํผ ํ†ตํ•ฉ์„ ํ†ตํ•œ iOS ์•Œ๋ฆผ ๊ถŒํ•œ ์ง€์› ์ถ”๊ฐ€

Preview 3์—๋Š”iOS์˜ PostNotifications ๊ถŒํ•œ๊ตฌํ˜„์ด ์ถ”๊ฐ€๋˜์–ด, ์•ฑ์ด ํ”Œ๋žซํผ๋ณ„ ์ฝ”๋“œ๋กœ ์ „ํ™˜ํ•˜์ง€ ์•Š๊ณ ๋„ ํฌ๋กœ์Šค ํ”Œ๋žซํผ Permissions API๋ฅผ ํ†ตํ•ด ์•Œ๋ฆผ ๊ถŒํ•œ์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/maui #30132).

var status = await Permissions.RequestAsync<Permissions.PostNotifications>();

.NET for Android, Android 17 / API 37 ํ”„๋ฆฌ๋ทฐ ์ง€์› ์ถ”๊ฐ€

.NET for Android Preview 3์€ Android 17 / API 37 ํ”„๋ฆฌ๋ทฐ์™€ ํ˜ธํ™˜๋˜๋ฏ€๋กœ, ์•ฑ์€ ๊ณง ์ถœ์‹œ๋  ํ”Œ๋žซํผ์— ๋Œ€ํ•ด ๋ฏธ๋ฆฌ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

.NET 11 Preview 3 ์ถœ์‹œ๋ฅผ ์ค€๋น„ํ•˜๋Š” ๊ณผ์ •์—์„œ .NET MAUI ํŒ€๊ณผ ๊ธด๋ฐ€ํžˆ ํ˜‘๋ ฅํ•ด์ค€ Uno Platform ํŒ€์—๊นŠ์€ ๊ฐ์‚ฌ๋ฅผ ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋“ค์˜ ๊ธฐ์—ฌ ๋•๋ถ„์— .NET for Android๊ฐ€ Google์˜ ์ตœ์‹  ํ”Œ๋žซํผ ์—…๋ฐ์ดํŠธ์™€ ์™„๋ฒฝํ•˜๊ฒŒ ํ˜ธํ™˜๋˜์–ด, ๊ฐœ๋ฐœ์ž๋“ค์ด Android 17 ํ”„๋ฆฌ๋ทฐ ๋ฐ API 37์„ ์ฆ‰์‹œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŒŒํŠธ๋„ˆ์‹ญ์€ .NET ์ƒํƒœ๊ณ„๋ฅผ ๊ฐ•ํ™”ํ•˜๊ณ , ๊ณ ํ’ˆ์งˆ์˜ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ๊ฐœ๋ฐœ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•˜๋ ค๋Š” ์šฐ๋ฆฌ์˜ ๊ณต๋™ ์˜์ง€๋ฅผ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

API 37์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด.csproj ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•˜์„ธ์š”:

<PropertyGroup>
  <TargetFramework>net11.0-android37</TargetFramework>
  <EnablePreviewFeatures>true</EnablePreviewFeatures>
</PropertyGroup>

Visual Studio์—์„œ API 37์„์„ค์น˜ํ•˜๋ ค๋ฉด ๋„๊ตฌ > Android > Android SDK ๊ด€๋ฆฌ์ž > ์ €์žฅ์†Œ > ์ „์ฒด ๋ชฉ๋ก์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค:

์ฐธ๊ณ 

๊ธฐ๋ณธ์ ์œผ๋กœ SDK๊ด€๋ฆฌ์ž๋Š” C:\\Program Files (x86)\\Android\\android-sdk\\platforms\\android-37.0์— ์„ค์น˜๋˜๋ฉฐ, .NET for Android๋Š” ์ด ๊ฒฝ๋กœ๋ฅผ ์ž๋™์œผ๋กœ ์ฐพ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ํ–ฅํ›„ ๋ฆด๋ฆฌ์Šค์—์„œ ์ด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋  ๋•Œ๊นŒ์ง€ ์ž„์‹œ ํ•ด๊ฒฐ์ฑ…์œผ๋กœ ํด๋”์ด๋ฆ„์„ C:\\Program Files (x86)\\Android\\android-sdk\\platforms\\android-37๋กœ ๋ณ€๊ฒฝํ•˜์‹ญ์‹œ์˜ค.

Android 17์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ „์ฒด์˜ˆ์ œ๋Š” API-37 HPKE ์•”ํ˜ธํ™” ์ƒ˜ํ”Œ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. ๋ณ€๊ฒฝ ์‚ฌํ•ญ์˜ ์ „์ฒด ๋ชฉ๋ก์€.NET for Android Preview 3 ๋ฆด๋ฆฌ์Šค ๋…ธํŠธ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

.NET for Android์˜ CLI ๊ธฐ๋ฐ˜ ๊ธฐ๊ธฐ ๊ฒ€์ƒ‰ ๋ฐ ๋ฐฐํฌ ํ๋ฆ„ ๊ฐœ์„ 

์ด์ œ dotnet run์„ ์‚ฌ์šฉํ•˜์—ฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ๋‚˜์—ดํ•˜๊ณ  ๋ฐฐํฌ ์ „์— ์„ ํƒํ•œ AVD๋ฅผ ์ž๋™์œผ๋กœ ๋ถ€ํŒ…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/android #10826). ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์œผ๋กœ ์ธํ•ด CLI ์šฐ์„  Android ๊ฐœ๋ฐœ์ด IDE ์ „์šฉ ์žฅ์น˜ ๊ด€๋ฆฌ์— ๋œ ์˜์กดํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Apple ์›Œํฌ๋กœ๋“œ์šฉ .NET, ํŒจํ‚ค์ง• ๋ฐ ๋ฐ”์ธ๋”ฉ ํ’ˆ์งˆ ๊ฐœ์„ 

Preview 3์€ ํ›„์ฒ˜๋ฆฌ ๊ณผ์ •์—์„œ ์ •์  ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์•ฑ ๋ฒˆ๋“ค์— ์‹ค์ œ๋กœ ํฌํ•จ๋œ ํ”„๋ ˆ์ž„์›Œํฌ์— ๋Œ€ํ•ด์„œ๋งŒ ์ŠคํŠธ๋ฆฌํ•‘ ๋ฐ ์‹ฌ๋ณผ ์ฒ˜๋ฆฌ๊ฐ€ ์ด๋ฃจ์–ด์ง€๋„๋ก ํ•จ์œผ๋กœ์จ Apple ์›Œํฌ๋กœ๋“œ ํŒจํ‚ค์ง•์„ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/macios #24845). ๋ฆด๋ฆฌ์Šค๋ธŒ๋žœ์น˜์—๋Š” NSArray API์—๋Œ€ํ•œ nullability ์–ด๋…ธํ…Œ์ด์…˜ ๊ฐœ์„ ๊ณผ ๊ฐ™์€ ๋ฐ”์ธ๋”ฉ ํ’ˆ์งˆ ๊ด€๋ จ ์ž‘์—…๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/macios #24907).

Apple์šฉ .NET์˜ Xcode 26.3 ์ง€์›

์ด์ œ Apple ํ”Œ๋žซํผ์„ ๋Œ€์ƒ์œผ๋กœ ํ•  ๋•Œ Xcode 26.3์ด ์ง€์›๋ฉ๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด API๋Š” ๋„์ž…๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

Apple ํ”Œ๋žซํผ์˜ CoreCLR ๊ฐœ์„  ์‚ฌํ•ญ

์ด ํ”„๋ฆฌ๋ทฐ์—๋Š” ๋ชจ๋“  Apple ํ”Œ๋žซํผ(iOS, macOS, Mac Catalyst ๋ฐ tvOS)์— ๊ฑธ์นœ ์—ฌ๋Ÿฌ CoreCLR ๊ฐœ์„  ์‚ฌํ•ญ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

  • ๋” ์ž‘์•„์ง„ ๋ฆด๋ฆฌ์Šค ๋นŒ๋“œ. ๋„ค์ดํ‹ฐ๋ธŒ ์‹ฌ๋ณผ ์ œ๊ฑฐ ๊ธฐ๋Šฅ์ด ์ด์ œ CoreCLR ๋ฐ ReadyToRun(R2R) ํ”„๋ ˆ์ž„์›Œํฌ๊นŒ์ง€ ์ ์šฉ๋˜์–ด, MAUI ํ…œํ”Œ๋ฆฟ ์•ฑ์˜ ๋ฒˆ๋“ค ํฌ๊ธฐ๊ฐ€ 77.8MB์—์„œ 41.6MB๋กœ ์ค„์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/macios #24678).

  • ๋” ๋น ๋ฅธ ์ฆ๋ถ„ ๋นŒ๋“œ. ์‚ฌ์šฉ์ž ์–ด์…ˆ๋ธ”๋ฆฌ๋งŒ ๋ณ€๊ฒฝ๋  ๋•Œ R2R ๋ณตํ•ฉ ์ด๋ฏธ์ง€๊ฐ€ ์บ์‹œ๋˜์–ด ์ฆ๋ถ„ ๋นŒ๋“œ ์‹œ๊ฐ„์ด ์•ฝ 39์ดˆ์—์„œ ์•ฝ 26์ดˆ๋กœ ๋‹จ์ถ•๋˜์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/macios #24735).

  • ๋” ์Šค๋งˆํŠธํ•œ ์ฝ”๋“œ ์ƒ์„ฑ. R2R ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์ด์ œ ๋ฐฐํฌ ๋Œ€์ƒ์— ํ•„์š”ํ•œ ์ตœ์†Œ ๋ช…๋ น์–ด ์„ธํŠธ(์˜ˆ: iOS 16+์˜ ๊ฒฝ์šฐ ARMv8.2-A)๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜์—ฌ, ๊ธฐ๊ธฐ ํ˜ธํ™˜์„ฑ์„ ์ €ํ•ดํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ๋” ์šฐ์ˆ˜ํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค(dotnet/macios #24621).

  • macOS์—์„œ์˜ R2R. ReadyToRun ์ปดํŒŒ์ผ์ด ์ด์ œ macOS์—์„œ ์ž‘๋™ํ•˜๋ฉฐ, ๋ชจ๋“  Apple ํ”Œ๋žซํผ์— ๋Œ€ํ•œ R2R ์ง€์›์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/macios #25080).

Entity Framework Core

ChangeTracker.GetEntriesForState()๋Š”๋ถˆํ•„์š”ํ•œ ๋ณ€๊ฒฝ ๊ฐ์ง€๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค

ChangeTracker์˜์ƒˆ๋กœ์šดGetEntriesForState()API๋Š” ๋จผ์ €DetectChanges()๋ฅผ ๊ฐ•์ œ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ๋„ ์„ ํƒ๋œ ์ƒํƒœ์˜ ์ถ”์ ๋œ ์—”ํ„ฐํ‹ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค(dotnet/efcore #37847). ์ด๋ฅผ ํ†ตํ•ด ๊ด€์‹ฌ ์žˆ๋Š” ์ƒํƒœ๋ฅผ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋Š” ์žฅ๊ธฐ ์ปจํ…์ŠคํŠธ๋‚˜ ๋Œ€๋Ÿ‰์˜ ๋ณ€๊ฒฝ ์ถ”์  ์ฝ”๋“œ์—์„œ ๋ถˆํ•„์š”ํ•œDetectChanges()ํ˜ธ์ถœ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var modified = context.ChangeTracker.GetEntriesForState(
    added: false,
    modified: true,
    deleted: false,
    unchanged: false);

DbContext ๊ตฌ์„ฑ์„ ํ†ตํ•ด ์ œ๊ณต์ž๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ํ’€๋ง๋œ ํŒฉํ† ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

Preview 3์—์„œ๋Š” ๋‹ค๋ฅธ ๊ณต๊ธ‰์ž๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ ์ „์— ์ด์ „ ๊ณต๊ธ‰์ž ๊ตฌ์„ฑ์„ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•œRemoveDbContext()/RemoveExtension()ํ—ฌํผ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/efcore #37891). ์ด๋Š” ํ”„๋กœ๋•์…˜์šฉ SQL Server ๊ตฌ์„ฑ์„ ๋ฉ”๋ชจ๋ฆฌ ๋‚ด ๋˜๋Š” SQLite ๊ณต๊ธ‰์ž๋กœ ๋Œ€์ฒดํ•˜๋Š” ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ํŠนํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

AddPooledDbContextFactory<TContext>()์—๋„ ์ด์ œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” ์˜ค๋ฒ„๋กœ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด,ConfigureDbContext<TContext>()๋‚ด์— ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๊ตฌ์„ฑ์— ๋Œ€ํ•ด ๋” ์ด์ƒ ์ถ”๊ฐ€์ ์ธ ์„ค์ • ๋ณด์ผ๋Ÿฌํ”Œ๋ ˆ์ดํŠธ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(dotnet/efcore #37144).

services.RemoveDbContext<MyContext>();
services.AddPooledDbContextFactory<MyContext>();

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์— ๋Œ€ํ•œ ์ œ์–ด๋ ฅ ๊ฐ•ํ™” ๋ฐ ๋ช…ํ™•ํ•œ ํ”ผ๋“œ๋ฐฑ ์ œ๊ณต

์ด์ œ EF Core์—์„œ๋Š”ExcludeForeignKeyFromMigrations(true)๋ฅผ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์—์„œ ์™ธ๋ž˜ ํ‚ค ์ œ์•ฝ ์กฐ๊ฑด์„ ์ œ์™ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/efcore #37815). ๋˜ํ•œ ๋ชจ๋ธ ์Šค๋ƒ…์ƒท์— ์ตœ์‹  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ID๊ฐ€ ๊ธฐ๋ก๋˜๋ฏ€๋กœ, ํŒ€ ์›Œํฌํ”Œ๋กœ์—์„œ EF๊ฐ€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŠธ๋ฆฌ์˜ ๋ถ„๊ธฐ๋ฅผ ๋” ์ผ์ฐ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(dotnet/efcore #37689).

modelBuilder.Entity<Order>()
    .HasOne(o => o.Customer)
    .WithMany(c => c.Orders)
    .ExcludeForeignKeyFromMigrations(true);

SQL ์ƒ์„ฑ ์‹œ ๋ถˆํ•„์š”ํ•œ ์กฐ์ธ์ด ์ œ๊ฑฐ๋˜๊ณ  SQL Server์— JSON API๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค

1:1 ์กฐ์ธ์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ ์ƒ์„ฑ์ด ์ด์ œ ์ผ๋ฐ˜์ ์ธ ์ƒํ™ฉ์—์„œ ๋ถˆํ•„์š”ํ•œ ์กฐ์ธ์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค(dotnet/efcore #37819). SQL Server 2025๋Š” ์ด์ œEF.Functions.JsonContains()๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ๋ช…ํ™•์„ฑ์„ ์œ„ํ•ด ์ด์ „ ํ”„๋ฆฌ๋ทฐ API์˜ ์ด๋ฆ„์ดJsonPathExists()๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/efcore #37714,dotnet/efcore #37732).

ํ˜ธํ™˜์„ฑ ๋ณ€๊ฒฝ ์‚ฌํ•ญ

  • RelationalEventId.MigrationsNotFound๋Š”์ด์ œ ์ •๋ณด์„ฑ ๋ฉ”์‹œ์ง€๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๋Œ€์‹  ๊ธฐ๋ณธ์ ์œผ๋กœ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค(dotnet/efcore #37839).

  • Microsoft.EntityFrameworkCore.Tools๋ฐMicrosoft.EntityFrameworkCore.Tasks๋Š”๋” ์ด์ƒMicrosoft.EntityFrameworkCore.Design์— ์ง์ ‘ ์˜์กดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(dotnet/efcore #37837).

  • EFOptimizeContextMSBuild ์†์„ฑ์ด ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋‚˜ ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ด ์†์„ฑ์„ ์„ค์ •ํ•œ ๊ฒฝ์šฐ, ์ด๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๋Œ€์‹ EFScaffoldModelStage๋ฐEFPrecompileQueriesStage์†์„ฑ์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค(dotnet/efcore #37838).

  • SqlVector์†์„ฑ์€ ๋” ์ด์ƒ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋กœ๋“œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋ฒกํ„ฐ ๊ฐ’์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ช…์‹œ์ ์œผ๋กœ ํˆฌ์˜ํ•˜๊ฑฐ๋‚˜ ๋กœ๋“œํ•˜์‹ญ์‹œ์˜ค(dotnet/efcore #37829).

  • Preview 3์—์„œ๋Š”Microsoft.Data.SqlClient๊ฐ€7.0.0์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ณต๊ธ‰์ž๋ณ„ SQL Server ๋™์ž‘์— ์˜์กดํ•˜๋Š” ๊ฒฝ์šฐ SqlClient ๋ฆด๋ฆฌ์Šค ๋…ธํŠธ๋ฅผ ๊ฒ€ํ† ํ•˜์‹ญ์‹œ์˜ค(dotnet/efcore #37949).

๋ฒ„๊ทธ ์ˆ˜์ •

  • ์˜ˆ์ƒ๋˜๋Š” ๊ณต๊ธ‰์ž ๊ตฌ์„ฑ ์—†์ด ๊ณต๊ฐ„ํ˜• ๋˜๋Š”HierarchyId์œ ํ˜•์ด ์‚ฌ์šฉ๋  ๋•Œ ์˜ค๋ฅ˜ ๋ณด๊ณ  ๊ธฐ๋Šฅ์ด ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(dotnet/efcore #37733).

  • ์†์„ฑ์˜ ๋ฐฑ์—… ํ•„๋“œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ๋” ๋ช…ํ™•ํ•œ ์˜ˆ์™ธ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/efcore #36720).

  • ์Šค์นผ๋ผ ํˆฌ์˜ ๋ฐ nullable-value-typeSetProperty๋žŒ๋‹ค์— ๋Œ€ํ•œExecuteUpdate๋ฅผ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/efcore #37791,dotnet/efcore #37975).

  • ์ฟผ๋ฆฌ ๋ณ€ํ™˜ ๋ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์—์„œ ์—ฌ๋Ÿฌ JSON ๋ฐ ๋ณตํ•ฉ ์†์„ฑ ์—์ง€ ์ผ€์ด์Šค๋ฅผ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค(dotnet/efcore #37823,dotnet/efcore #37855,dotnet/efcore #37965).

์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€

.NET ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€์— ์„œ๋ช… ์ ์šฉ

์ด์ œ ๋ชจ๋“  .NET ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€๋Š”Notary Project์‚ฌ์–‘์— ๋”ฐ๋ผ Microsoft์—์„œ ์•”ํ˜ธํ•™์ ์œผ๋กœ ์„œ๋ช…ํ•ฉ๋‹ˆ๋‹ค.์ด๋ฏธ์ง€ ์„œ๋ช…์„๊ฒ€์‚ฌํ•˜๊ณ  ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ตœ์‹  ๋ฌธ์„œ๋Š”์ด๋ฏธ์ง€ ์„œ๋ช… ๋ฌธ์„œ๋ฅผ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

Notary CLI๋˜๋Š”ORAS CLI๋ฅผ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ช… ์•„ํ‹ฐํŒฉํŠธ์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜์„ธ์š”:

notation inspect mcr.microsoft.com/dotnet/sdk:11.0.100-preview.3 oras discover mcr.microsoft.com/dotnet/sdk:11.0.100-preview.3

2๊ฐœ์˜ ์ข‹์•„์š”

#:include ์ง€์‹œ์–ด๊ฐ€ ๋“œ๋””์–ด ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ ๊ธฐ๋ฐ˜ ์•ฑ ๊ฐœ๋ฐœ์ด ๋ณธ๊ฒฉ์ ์œผ๋กœ ์˜๋ฏธ์žˆ๊ฒŒ ์“ฐ์ผ ์ˆ˜ ์žˆ๋Š” ์ฒซ ์‹ ํ˜ธํƒ„์ด ๋  ๊ฒƒ ๊ฐ™์•„ ๊ธฐ๋Œ€๊ฐ€ ๋งŽ์ด ๋ฉ๋‹ˆ๋‹ค. :smiley:

5๊ฐœ์˜ ์ข‹์•„์š”

๋‹ท๋„ท 11์—์„œ ์ด API๋“ค์„ ์“ฐ๋˜ ํ”„๋กœ๊ทธ๋žจ๋“ค์€ ์ฝ”๋“œ ์ˆ˜์ • ์—†์ด๋Š” ์ปดํŒŒ์ผ์ด ์•ˆ ๋˜๊ฒ ๊ตฐ์š”. ๋ฌผ๋ก  ์ด๋Ÿฐ Breaking Change๋“ค์ด ์–ธ์ œ๋“ ์ง€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š”๊ฒŒ ํ”„๋ฆฌ๋ทฐ๋‹ˆโ€ฆ

https://x.com/DamianEdwards/status/2044510681211543570

.NET ํŒ€์—์„œ Principal Architect๋กœ ์ผํ•˜๊ณ  ์žˆ๋Š” Damian Edwards์˜ ํŠธ์œ—์— ๋”ฐ๋ฅด๋ฉด, .NET 11 Preview 3์—์„œ ์†Œ๊ฐœ๋œ #:include ์ง€์‹œ์ž๊ฐ€ .NET 10 LTS ์—…๋ฐ์ดํŠธ์ธ 10.0.300์—๋„ Backporting์ด ์˜ˆ์ •๋˜์–ด์žˆ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ง€์‹œ์ž๊ฐ€ ๋น ์ ธ์žˆ๋‹ค๋ฉด ์ •๋ง ์•„์‰ฌ์› ์„๊ฑด๋ฐ ์ข‹์€ ์†Œ์‹์ž…๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์ด ํฌํ•จ๋จ์œผ๋กœ ์ธํ•ด์„œ Visual Studio์˜ ๊ทธ๋ฆผ์ž๊ฐ€ ๋ฎ์ง€ ์•Š์€ ์ƒˆ๋กœ์šด C# ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์ด ๋“œ๋””์–ด ๋ณธ ๊ถค๋„์— ์ง„์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

5๊ฐœ์˜ ์ข‹์•„์š”