Skip to content

dotnetdev-kr/dotnet-fba-examples

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

9 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

C# File-Based Application (FBA) Zero to Hero

๐Ÿš€ .NET์˜ ๊ฐ•๋ ฅํ•œ FBA(File-Based Application) ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•œ ์‹ค์ „ ์˜ˆ์ œ ๋ชจ์Œ

C# File-Based Application (FBA) ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•œ ๋‹ค์–‘ํ•œ ์˜ˆ์ œ ์ฝ”๋“œ ๋ชจ์Œ์ž…๋‹ˆ๋‹ค. .NET 10 ์ด์ƒ์˜ FBA ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์ผ ํŒŒ์ผ๋กœ ์ž‘์„ฑ๋œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ C# ์Šคํฌ๋ฆฝํŠธ ์˜ˆ์ œ๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ฐœํ‘œ ์ž๋ฃŒ ๊ฐ™์ด๋ณด๊ธฐ: https://1drv.ms/p/c/318484c5aad6b73d/EQNehpg4jN5CmVcTh-qDoecBGqBe3gMwuGh3bbHf7EW4yQ?e=M1RstJ

๐ŸŽฏ FBA๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

File-Based Application(FBA)์€ .NET์˜ ํ˜์‹ ์ ์ธ ๊ธฐ๋Šฅ์œผ๋กœ, ๋‹จ์ผ C# ํŒŒ์ผ์„ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ(.csproj) ์—†์ด ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

  • โœจ ๊ฐ„ํŽธํ•œ ์‹œ์ž‘: ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์—†์ด ๋‹จ์ผ ํŒŒ์ผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž‘์„ฑ
  • ๐Ÿ”ง ๋น ๋ฅธ ํ”„๋กœํ† ํƒ€์ดํ•‘: ์•„์ด๋””์–ด๋ฅผ ๋น ๋ฅด๊ฒŒ ํ…Œ์ŠคํŠธํ•˜๊ณ  ๊ฒ€์ฆ
  • ๐Ÿ“ฆ ์˜์กด์„ฑ ๊ด€๋ฆฌ: #:package ๋””๋ ‰ํ‹ฐ๋ธŒ๋กœ NuGet ํŒจํ‚ค์ง€ ์ง์ ‘ ์ฐธ์กฐ
  • ๐ŸŽญ SDK ์„ ํƒ: #:sdk ๋””๋ ‰ํ‹ฐ๋ธŒ๋กœ ํ•„์š”ํ•œ SDK ์ง€์ •
  • โš™๏ธ ๋นŒ๋“œ ์†์„ฑ: #:property ๋””๋ ‰ํ‹ฐ๋ธŒ๋กœ MSBuild ์†์„ฑ ์„ค์ •
  • ๐Ÿš ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰: Shebang(#!/usr/bin/env dotnet)์„ ํ†ตํ•œ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰

๐Ÿ“‹ ๋ชฉ์ฐจ

๐Ÿ’ป ์š”๊ตฌ์‚ฌํ•ญ

ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ

  • .NET 10.0 SDK ์ด์ƒ
    • FBA ๊ธฐ๋Šฅ์„ ์™„์ „ํžˆ ์ง€์›ํ•˜๋Š” ์ตœ์‹  ๋ฒ„์ „ ์‚ฌ์šฉ ๊ถŒ์žฅ
    • ์„ค์น˜ ํ™•์ธ: dotnet --version
  • ์šด์˜์ฒด์ œ: macOS, Linux, ๋˜๋Š” Windows
    • ๋ชจ๋“  ์˜ˆ์ œ๋Š” ํฌ๋กœ์Šค ํ”Œ๋žซํผ์œผ๋กœ ์„ค๊ณ„๋จ

์„ ํƒ์  ์š”๊ตฌ์‚ฌํ•ญ

  • Python 3.x (05-native-aot.py ์‹คํ–‰ ์‹œ)
    • Native AOT ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์˜ˆ์ œ์— ํ•„์š”
  • Java 17+ ๋ฐ wget (05-native-aot.java ์‹คํ–‰ ์‹œ)
    • Java์—์„œ Native AOT ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์˜ˆ์ œ์— ํ•„์š”
    • JNA(Java Native Access) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž๋™ ๋‹ค์šด๋กœ๋“œ
  • Node.js 18+ ๋ฐ npm (05-native-aot.js ์‹คํ–‰ ์‹œ)
    • Node.js์—์„œ Native AOT ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์˜ˆ์ œ์— ํ•„์š”
    • koffi ํŒจํ‚ค์ง€ ์ž๋™ ์„ค์น˜
  • GCC/Clang (05-staticlib-c.c ์ปดํŒŒ์ผ ์‹œ)
    • C ์ปดํŒŒ์ผ๋Ÿฌ ๋ฐ iconv ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
    • macOS: Xcode Command Line Tools (xcode-select --install)
    • Linux: build-essential ํŒจํ‚ค์ง€
  • OpenRouter API ํ‚ค (06-agui-server.cs ์‹คํ–‰ ์‹œ)
    • AI ์—์ด์ „ํŠธ ์˜ˆ์ œ์— ํ•„์š”
    • OpenRouter์—์„œ ๋ฌด๋ฃŒ ๊ณ„์ • ์ƒ์„ฑ ๊ฐ€๋Šฅ

๊ฐœ๋ฐœ ๋„๊ตฌ (๊ถŒ์žฅ)

  • Visual Studio Code + C# Dev Kit ํ™•์žฅ
  • JetBrains Rider
  • Visual Studio 2022 (Windows)
  • LINQPad 8 (์ด ์ €์žฅ์†Œ์˜ ์›๋ž˜ ์‹คํ–‰ ํ™˜๊ฒฝ)

๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘

# ์ €์žฅ์†Œ ํด๋ก 
git clone <repository-url>
cd csharp-fba-zero-to-hero

# ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ ์‹คํ–‰
chmod +x 01-shell-standard.cs
./01-shell-standard.cs

# ์›น API ์˜ˆ์ œ ์‹คํ–‰
chmod +x 02-random-webapi.cs
./02-random-webapi.cs
# ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์—์„œ: curl http://localhost:5000/

๐Ÿ“š ์˜ˆ์ œ ์„ค๋ช…

๊ฐ ์˜ˆ์ œ๋Š” FBA์˜ ํŠน์ • ๊ธฐ๋Šฅ๊ณผ ์‹ค์ œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๋‚œ์ด๋„ ์ˆœ์œผ๋กœ ์ •๋ ฌ๋˜์–ด ์žˆ์œผ๋ฉฐ, ๊ธฐ์ดˆ๋ถ€ํ„ฐ ๊ณ ๊ธ‰ ์ฃผ์ œ๊นŒ์ง€ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

01. Shell Scripts

๐ŸŽ“ ํ•™์Šต ๋ชฉํ‘œ: FBA์˜ ๊ธฐ๋ณธ Shebang ์‚ฌ์šฉ๋ฒ•๊ณผ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ ๋ฐฉ์‹ ์ดํ•ด

๊ฐ„๋‹จํ•œ "Hello World" ์Šคํƒ€์ผ์˜ ์‰˜ ์Šคํฌ๋ฆฝํŠธ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. C# ํŒŒ์ผ์„ Unix/Linux ์Šคํƒ€์ผ์˜ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…:

  • Shebang(#!)์„ ์‚ฌ์šฉํ•œ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์ง€์ •
  • ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ (chmod +x)
  • ์ง์ ‘ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ C# ํŒŒ์ผ

01-shell-standard.cs

ํ‘œ์ค€ shebang ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ ๊ธฐ๋ณธ ์Šคํฌ๋ฆฝํŠธ์ž…๋‹ˆ๋‹ค.

์‹คํ–‰ ๋ฐฉ๋ฒ•:

# ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x 01-shell-standard.cs

# ์‹คํ–‰
./01-shell-standard.cs

์ถœ๋ ฅ:

No lemon, no melon.

01-shell-alt.cs

๋Œ€์ฒด shebang ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ ์Šคํฌ๋ฆฝํŠธ์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ์‹์€ JBang์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

์‹คํ–‰ ๋ฐฉ๋ฒ•:

# ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x 01-shell-alt.cs

# ์‹คํ–‰
./01-shell-alt.cs

์ถœ๋ ฅ:

No lemon, No melon.

02. Web API

๐ŸŽ“ ํ•™์Šต ๋ชฉํ‘œ: FBA์—์„œ ASP.NET Core ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž‘์„ฑ ๋ฐฉ๋ฒ•, SDK ์ง€์ • ๋ฐ ์˜์กด์„ฑ ์ฃผ์ž… ์ดํ•ด

ASP.NET Core๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•œ ์›น API ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. ๋žœ๋ค ์ˆซ์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…:

  • #:sdk Microsoft.NET.Sdk.Web - Web SDK ์‚ฌ์šฉ
  • #:property PublishAot=false - AOT ์ปดํŒŒ์ผ ๋น„ํ™œ์„ฑํ™”
  • Minimal API ํŒจํ„ด
  • Dependency Injection (DI)
  • Singleton ์„œ๋น„์Šค ๋“ฑ๋ก (Random.Shared)

02-random-webapi.cs

์‹คํ–‰ ๋ฐฉ๋ฒ•:

# ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x 02-random-webapi.cs

# ์‹คํ–‰
./02-random-webapi.cs

ํ…Œ์ŠคํŠธ:

# ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์—์„œ ์‹คํ–‰
curl http://localhost:5000/

์‘๋‹ต ์˜ˆ์‹œ:

{
  "ts": "2025-11-26T12:34:56.7890123Z",
  "val": 7
}

03. Aspire App Host

๐ŸŽ“ ํ•™์Šต ๋ชฉํ‘œ: .NET Aspire๋ฅผ ์‚ฌ์šฉํ•œ ๋ถ„์‚ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์ถ•, ์„œ๋น„์Šค ๊ฐ„ ํ†ต์‹  ๋ฐ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜

.NET Aspire๋ฅผ ์‚ฌ์šฉํ•œ ๋ถ„์‚ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. Garnet(Redis ํ˜ธํ™˜) ์บ์‹œ ์„œ๋ฒ„, Worker ์„œ๋น„์Šค, Minimal API๋ฅผ ํ•จ๊ป˜ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…:

  • #:sdk Aspire.AppHost.Sdk - Aspire AppHost SDK ์‚ฌ์šฉ
  • #:package ๋””๋ ‰ํ‹ฐ๋ธŒ๋กœ NuGet ํŒจํ‚ค์ง€ ์ฐธ์กฐ
  • ์„œ๋น„์Šค ๋””์Šค์ปค๋ฒ„๋ฆฌ ๋ฐ ์ฐธ์กฐ ๊ด€๋ฆฌ
  • WaitFor ํŒจํ„ด์œผ๋กœ ์„œ๋น„์Šค ์‹œ์ž‘ ์ˆœ์„œ ์ œ์–ด
  • User Secrets๋ฅผ ํ†ตํ•œ ๋น„๋ฐ€ ์ •๋ณด ๊ด€๋ฆฌ
  • Aspire Dashboard๋ฅผ ํ†ตํ•œ ๋ถ„์‚ฐ ์ถ”์  ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง

๊ตฌ์„ฑ ์š”์†Œ

  • 03-apphost.cs: ์•ฑ ํ˜ธ์ŠคํŠธ - ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ
  • 03-minapi.cs: Minimal API - Redis์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ์–ด ๋ฐ˜ํ™˜ํ•˜๋Š” ์›น API
  • 03-worker.cs: Background Worker - 1์ดˆ๋งˆ๋‹ค Redis์— ํ˜„์žฌ ์‹œ๊ฐ„์„ ์—…๋ฐ์ดํŠธ
  • 03-apphost.json: ์•ฑ ํ˜ธ์ŠคํŠธ ์„ค์ • ํŒŒ์ผ

์‹คํ–‰ ๋ฐฉ๋ฒ•:

# ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x 03-apphost.cs

# ์‹คํ–‰
./03-apphost.cs

ํŠน์ง•:

  • Aspire Dashboard๊ฐ€ ์ž๋™์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค (http://localhost:18888)
  • Garnet (Redis ํ˜ธํ™˜) ์บ์‹œ ์„œ๋ฒ„๊ฐ€ ์ž๋™์œผ๋กœ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค
  • Worker๊ฐ€ 1์ดˆ๋งˆ๋‹ค LastUpdated ํ‚ค๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค
  • Minimal API๊ฐ€ ๋ฉ”์‹œ์ง€์™€ ๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ ์‹œ๊ฐ„์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค

ํ…Œ์ŠคํŠธ:

# Aspire Dashboard์—์„œ minapi์˜ ํฌํŠธ ํ™•์ธ ํ›„
curl http://localhost:<minapi-port>/

์•„ํ‚คํ…์ฒ˜ ํ๋ฆ„:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Worker    โ”‚โ”€โ”€โ”€โ”€โ”€>โ”‚   Garnet    โ”‚<โ”€โ”€โ”€โ”€โ”€โ”‚   MinAPI    โ”‚
โ”‚ (03-worker) โ”‚ writeโ”‚  (Redis)    โ”‚ read โ”‚ (03-minapi) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
      โ†“                                           โ†“
  ๋งค 1์ดˆ๋งˆ๋‹ค                               HTTP ์š”์ฒญ ์‹œ
 LastUpdated ์—…๋ฐ์ดํŠธ                    ๋ฉ”์‹œ์ง€ ์กฐํšŒ ๋ฐ ๋ฐ˜ํ™˜

04. Avalonia GUI

๐ŸŽ“ ํ•™์Šต ๋ชฉํ‘œ: FBA์—์„œ ํฌ๋กœ์Šค ํ”Œ๋žซํผ GUI ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ž‘์„ฑ, MVVM ํŒจํ„ด ์ ์šฉ

Avalonia UI๋ฅผ ์‚ฌ์šฉํ•œ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ๋ฐ์Šคํฌํ†ฑ ๊ณ„์‚ฐ๊ธฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค. WPF์™€ ์œ ์‚ฌํ•œ XAML ๊ธฐ๋ฐ˜ UI๋ฅผ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…:

  • #:property OutputType=WinExe - Windows ์‹คํ–‰ ํŒŒ์ผ๋กœ ๋นŒ๋“œ
  • Avalonia UI ํ”„๋ ˆ์ž„์›Œํฌ
  • MVVM (Model-View-ViewModel) ํŒจํ„ด
  • CommunityToolkit.Mvvm์„ ํ™œ์šฉํ•œ ๊ด€์ฐฐ ๊ฐ€๋Šฅ ์†์„ฑ
  • RelayCommand๋ฅผ ํ†ตํ•œ ์ปค๋งจ๋“œ ํŒจํ„ด
  • Dependency Injection๊ณผ ์„œ๋น„์Šค ์ƒ๋ช…์ฃผ๊ธฐ
  • ์ฝ”๋“œ ๊ธฐ๋ฐ˜ UI ๊ตฌ์„ฑ (Code-behind UI)

04-avalonia.cs

์‹คํ–‰ ๋ฐฉ๋ฒ•:

# ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x 04-avalonia.cs

# ์‹คํ–‰
./04-avalonia.cs

ํŠน์ง•:

  • CommunityToolkit.Mvvm์„ ์‚ฌ์šฉํ•œ MVVM ํŒจํ„ด ๊ตฌํ˜„
  • ๊ธฐ๋ณธ ์‚ฌ์น™์—ฐ์‚ฐ ๊ธฐ๋Šฅ (+, -, ร—, รท)
  • ํฌ๋กœ์Šค ํ”Œ๋žซํผ ์ง€์› (Windows, macOS, Linux)
  • Dependency Injection์„ ํ™œ์šฉํ•œ ์„œ๋น„์Šค ๊ตฌ์กฐ

05. Native AOT

๐ŸŽ“ ํ•™์Šต ๋ชฉํ‘œ: Native AOT ์ปดํŒŒ์ผ์„ ํ†ตํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ƒ์„ฑ, ๋‹ค๋ฅธ ์–ธ์–ด์™€์˜ ์ƒํ˜ธ์šด์šฉ์„ฑ

Native AOT ์ปดํŒŒ์ผ์„ ํ†ตํ•ด C# ์ฝ”๋“œ๋ฅผ ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ๋‹ค์–‘ํ•œ ์–ธ์–ด(Python, C)์—์„œ ํ˜ธ์ถœํ•˜๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. C#์˜ ์„ฑ๋Šฅ๊ณผ ๋‹ค๋ฅธ ์–ธ์–ด์˜ ์œ ์—ฐ์„ฑ์„ ๊ฒฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…:

  • #:property PublishAot=True - Native AOT ์ปดํŒŒ์ผ ํ™œ์„ฑํ™”
  • #:property OutputType=Library - ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋นŒ๋“œ
  • #:property NativeLib=Static - ์ •์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ƒ์„ฑ
  • #:property RuntimeIdentifier=osx-arm64 - ํƒ€๊ฒŸ ํ”Œ๋žซํผ ์ง€์ •
  • UnmanagedCallersOnly ์†์„ฑ - ๋„ค์ดํ‹ฐ๋ธŒ ํ•จ์ˆ˜ ๋…ธ์ถœ
  • P/Invoke ์—ญ๋ฐฉํ–ฅ (C#์—์„œ ๋„ค์ดํ‹ฐ๋ธŒ๋กœ)
  • ์–ธ์–ด ๊ฐ„ ์ƒํ˜ธ์šด์šฉ์„ฑ (C# โ†” Python/C)
  • ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์—ด ๋งˆ์ƒฌ๋ง
  • iconv๋ฅผ ํ†ตํ•œ UTF-8 โ†” UTF-16 ๋ณ€ํ™˜

์˜ˆ์ œ ํŒŒ์ผ

  • 05-native-aot.cs: C# ๋„ค์ดํ‹ฐ๋ธŒ ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์†Œ์Šค (.dylib)
  • 05-native-aot.py: Python์—์„œ ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์˜ˆ์ œ
  • 05-native-aot.java: Java์—์„œ ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์˜ˆ์ œ (JNA ์‚ฌ์šฉ)
  • 05-native-aot.js: Node.js์—์„œ ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์˜ˆ์ œ (koffi ์‚ฌ์šฉ)
  • 05-staticlib-aot.cs: C# ๋„ค์ดํ‹ฐ๋ธŒ ์ •์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์†Œ์Šค (.a)
  • 05-staticlib-c.c: C์—์„œ ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ ์˜ˆ์ œ

๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (.dylib) ์˜ˆ์ œ

๋นŒ๋“œ ๋ฐฉ๋ฒ•:

# C# ์ฝ”๋“œ๋ฅผ ๋„ค์ดํ‹ฐ๋ธŒ ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ปดํŒŒ์ผ
dotnet publish ./05-native-aot.cs

Python์—์„œ ์‚ฌ์šฉ:

# ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x 05-native-aot.py

# ์‹คํ–‰
./05-native-aot.py

C์—์„œ ์‚ฌ์šฉ:

# ์ปดํŒŒ์ผ ๋ฐ ์‹คํ–‰
gcc -o 05-staticlib-c 05-staticlib-c.c artifacts/05-native-aot/05-native-aot.dylib -Wl,-rpath,artifacts/05-native-aot -liconv
./05-staticlib-c

Java์—์„œ ์‚ฌ์šฉ:

# JNA ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‹ค์šด๋กœ๋“œ (์ตœ์ดˆ 1ํšŒ)
wget -nc https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.14.0/jna-5.14.0.jar

# ์ปดํŒŒ์ผ
javac -cp jna-5.14.0.jar 05-native-aot.java

# ์‹คํ–‰
java -cp .:jna-5.14.0.jar NativeAotExample

Node.js์—์„œ ์‚ฌ์šฉ:

# koffi ํŒจํ‚ค์ง€ ์„ค์น˜ (์ตœ์ดˆ 1ํšŒ)
npm install koffi

# ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x 05-native-aot.js

# ์‹คํ–‰
./05-native-aot.js
# ๋˜๋Š”
node 05-native-aot.js

์ถœ๋ ฅ ์˜ˆ์‹œ:

Testing Native AOT library from Node.js
==========================================

2025. 11. 26. ์˜คํ›„ 11:56:52 Hello from Node.js!
2025. 11. 26. ์˜คํ›„ 11:56:52 Native AOT ํ˜ธ์ถœ ํ…Œ์ŠคํŠธ
2025. 11. 26. ์˜คํ›„ 11:56:52 ์•ˆ๋…•ํ•˜์„ธ์š”!

All calls completed.

์ •์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (.a) ์˜ˆ์ œ

๋นŒ๋“œ ๋ฐฉ๋ฒ•:

# C# ์ฝ”๋“œ๋ฅผ ๋„ค์ดํ‹ฐ๋ธŒ ์ •์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ปดํŒŒ์ผ
dotnet publish ./05-staticlib-aot.cs

โš ๏ธ ์ฐธ๊ณ : ์ •์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” .NET ๋Ÿฐํƒ€์ž„ ์ข…์†์„ฑ์ด ํฌํ•จ๋˜์ง€ ์•Š์•„ ์ง์ ‘ ๋งํฌ ์‹œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(.dylib) ์‚ฌ์šฉ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

ํŠน์ง•:

  • UnmanagedCallersOnly ์†์„ฑ์„ ์‚ฌ์šฉํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ํ•จ์ˆ˜ ๋…ธ์ถœ
  • Python ctypes, Java JNA, Node.js koffi, C์—์„œ C# ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜ธ์ถœ
  • UTF-16 ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž์—ด ์ „๋‹ฌ ์ง€์› (ํ•œ๊ธ€ ํฌํ•จ)
  • iconv ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•œ ๊ฐ„๋‹จํ•œ ๋ฌธ์ž ์ธ์ฝ”๋”ฉ ๋ณ€ํ™˜ (C)
  • Java JNA์™€ Node.js koffi๋ฅผ ํ†ตํ•œ ๊ฐ„ํŽธํ•œ ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ ‘๊ทผ
  • JIT ์ปดํŒŒ์ผ๋Ÿฌ ์—†์ด ๋น ๋ฅธ ์‹œ์ž‘ ์‹œ๊ฐ„
  • ์ž‘์€ ๋ฐฐํฌ ํฌ๊ธฐ (๋‹จ์ผ ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)
  • .NET ๋Ÿฐํƒ€์ž„ ๋ถˆํ•„์š” (self-contained)

์‚ฌ์šฉ ์‚ฌ๋ก€:

  • Python/Java/Node.js/C ํ”„๋กœ์ ํŠธ์— ๊ณ ์„ฑ๋Šฅ C# ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ†ตํ•ฉ
  • ๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ๊ณผ์˜ ์—ฐ๋™
  • ์—ฃ์ง€ ๋””๋ฐ”์ด์Šค์šฉ ๊ฒฝ๋Ÿ‰ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • ๊ฒŒ์ž„ ์—”์ง„ ํ”Œ๋Ÿฌ๊ทธ์ธ
  • ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ์šฉ ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋“ˆ
  • JVM ๊ธฐ๋ฐ˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ .NET ์ฝ”๋“œ ํ™œ์šฉ
  • Node.js ๋ฐฑ์—”๋“œ์—์„œ ๊ณ ์„ฑ๋Šฅ .NET ๋ชจ๋“ˆ ํ™œ์šฉ

06. AG-UI (AI Agents)

๐ŸŽ“ ํ•™์Šต ๋ชฉํ‘œ: AI ์—์ด์ „ํŠธ ๊ตฌ์ถ•, ์ปค์Šคํ…€ ๋„๊ตฌ ํ†ตํ•ฉ, ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์ฒ˜๋ฆฌ

Microsoft Agents AI ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•œ AI ์—์ด์ „ํŠธ ์„œ๋ฒ„/ํด๋ผ์ด์–ธํŠธ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. OpenAI ํ˜ธํ™˜ API๋ฅผ ํ†ตํ•ด Grok ๋ชจ๋ธ์„ ํ™œ์šฉํ•˜๋ฉฐ, ์ปค์Šคํ…€ ๋„๊ตฌ(Function Calling)๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…:

  • Microsoft.Agents.AI ํ”„๋ ˆ์ž„์›Œํฌ

  • AG-UI (Agent Gateway User Interface) ํ”„๋กœํ† ์ฝœ

  • OpenAI ํ˜ธํ™˜ API ์‚ฌ์šฉ (OpenRouter๋ฅผ ํ†ตํ•œ Grok ์ ‘๊ทผ)

  • Function Calling / Tool Use ํŒจํ„ด

  • AIFunctionFactory๋ฅผ ํ†ตํ•œ ํ•จ์ˆ˜ ๋“ฑ๋ก

  • ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์ฒ˜๋ฆฌ

  • User Secrets๋ฅผ ํ†ตํ•œ API ํ‚ค ๊ด€๋ฆฌ

  • IChatClient ์ธํ„ฐํŽ˜์ด์Šค ํ™œ์šฉ

  • 06-agui-server.cs: AG-UI ์„œ๋ฒ„ - AI ์—์ด์ „ํŠธ ํ˜ธ์ŠคํŒ…

  • 06-agui-client.cs: AG-UI ํด๋ผ์ด์–ธํŠธ - ์—์ด์ „ํŠธ์™€ ๋Œ€ํ™”

์„œ๋ฒ„ ์„ค์ •:

# OpenRouter API ํ‚ค ์„ค์ •
dotnet user-secrets --id 06-agui-server set openrouter-key "YOUR_API_KEY_HERE"

์„œ๋ฒ„ ์‹คํ–‰:

# ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x 06-agui-server.cs

# ์‹คํ–‰
./06-agui-server.cs

ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰:

# ์ƒˆ ํ„ฐ๋ฏธ๋„์—์„œ
chmod +x 06-agui-client.cs

# ์‹คํ–‰
./06-agui-client.cs

ํŠน์ง•:

  • OpenAI ํ˜ธํ™˜ API๋ฅผ ํ†ตํ•œ Grok 4.1 ๋ชจ๋ธ ์‚ฌ์šฉ
  • ์ปค์Šคํ…€ ๋„๊ตฌ(Tools) ์ง€์› (๋ง์…ˆ, ๋บ„์…ˆ)
  • ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต ์ง€์›
  • ๋Œ€ํ™”ํ˜• CLI ์ธํ„ฐํŽ˜์ด์Šค

์‚ฌ์šฉ ์˜ˆ์‹œ:

User (:q or quit to exit): 25 ๋”ํ•˜๊ธฐ 17์€?
[Run Started - Thread: xxx, Run: yyy]
25 ๋”ํ•˜๊ธฐ 17์€ 42์ž…๋‹ˆ๋‹ค.
[Run Finished - Thread: xxx]

User (:q or quit to exit): :q

๐Ÿ“– FBA ๋””๋ ‰ํ‹ฐ๋ธŒ ๊ฐ€์ด๋“œ

FBA์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฃผ์š” ๋””๋ ‰ํ‹ฐ๋ธŒ๋“ค์ž…๋‹ˆ๋‹ค:

SDK ์ง€์ •

#:sdk Microsoft.NET.Sdk           // ๊ธฐ๋ณธ ์ฝ˜์†” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
#:sdk Microsoft.NET.Sdk.Web       // ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
#:sdk Microsoft.NET.Sdk.Worker    // Worker ์„œ๋น„์Šค
#:sdk Aspire.AppHost.Sdk@13.0.0   // Aspire AppHost (๋ฒ„์ „ ์ง€์ •)

ํŒจํ‚ค์ง€ ์ฐธ์กฐ

#:package Newtonsoft.Json                    // ์ตœ์‹  ๋ฒ„์ „
#:package Newtonsoft.Json@13.0.3             // ํŠน์ • ๋ฒ„์ „
#:package Microsoft.Extensions.Hosting@10.*  // ์™€์ผ๋“œ์นด๋“œ ๋ฒ„์ „

๋นŒ๋“œ ์†์„ฑ

#:property OutputType=Library                // ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋นŒ๋“œ
#:property OutputType=WinExe                 // Windows ์‹คํ–‰ ํŒŒ์ผ
#:property PublishAot=true                   // Native AOT ํ™œ์„ฑํ™”
#:property PublishAot=false                  // Native AOT ๋น„ํ™œ์„ฑํ™”
#:property RuntimeIdentifier=osx-arm64       // ํƒ€๊ฒŸ ํ”Œ๋žซํผ ์ง€์ •
#:property TargetFramework=net10.0           // ํƒ€๊ฒŸ ํ”„๋ ˆ์ž„์›Œํฌ

Shebang ์Šคํƒ€์ผ

#!/usr/bin/env dotnet              // ํ‘œ์ค€ ๋ฐฉ์‹
///usr/bin/env dotnet "$0" "$@" ; exit $?  // JBang ์Šคํƒ€์ผ

๐Ÿ”ง ๋ฌธ์ œ ํ•ด๊ฒฐ

์‹คํ–‰ ๊ถŒํ•œ ์˜ค๋ฅ˜

๋ฌธ์ œ: Permission denied ์˜ค๋ฅ˜ ๋ฐœ์ƒ

ํ•ด๊ฒฐ:

chmod +x <ํŒŒ์ผ๋ช…>.cs

ํŒจํ‚ค์ง€ ๋ณต์› ์˜ค๋ฅ˜

๋ฌธ์ œ: ํŒจํ‚ค์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๊ฑฐ๋‚˜ ๋ฒ„์ „ ์ถฉ๋Œ

ํ•ด๊ฒฐ:

# NuGet ์บ์‹œ ์ •๋ฆฌ
dotnet nuget locals all --clear

# ๋‹ค์‹œ ์‹คํ–‰
./<ํŒŒ์ผ๋ช…>.cs

Native AOT ๋นŒ๋“œ ์‹คํŒจ

๋ฌธ์ œ: Native AOT ์ปดํŒŒ์ผ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ

ํ•ด๊ฒฐ:

  • ํ”Œ๋žซํผ์— ๋งž๋Š” ๋นŒ๋“œ ๋„๊ตฌ ์„ค์น˜ ํ•„์š”
  • macOS: Xcode Command Line Tools (xcode-select --install)
  • Linux: GCC/Clang ๋ฐ ๊ฐœ๋ฐœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • Windows: Visual Studio Build Tools

Aspire Dashboard ์ ‘๊ทผ ๋ถˆ๊ฐ€

๋ฌธ์ œ: Dashboard์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Œ

ํ•ด๊ฒฐ:

# ํฌํŠธ ์ถฉ๋Œ ํ™•์ธ
lsof -i :18888

# 03-apphost.json์—์„œ ํฌํŠธ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

OpenRouter API ํ‚ค ์˜ค๋ฅ˜

๋ฌธ์ œ: openrouter-key is missing ์˜ค๋ฅ˜

ํ•ด๊ฒฐ:

# User Secrets ์„ค์ • ํ™•์ธ
dotnet user-secrets list --id 06-agui-server

# ๋‹ค์‹œ ์„ค์ •
dotnet user-secrets --id 06-agui-server set openrouter-key "your-api-key"

๐Ÿค ๊ธฐ์—ฌํ•˜๊ธฐ

์ด ํ”„๋กœ์ ํŠธ์— ๊ธฐ์—ฌํ•˜๊ณ  ์‹ถ์œผ์‹ ๊ฐ€์š”? ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!

  1. ์ด ์ €์žฅ์†Œ๋ฅผ Fork ํ•˜์„ธ์š”
  2. Feature ๋ธŒ๋žœ์น˜๋ฅผ ์ƒ์„ฑํ•˜์„ธ์š” (git checkout -b feature/AmazingFeature)
  3. ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ปค๋ฐ‹ํ•˜์„ธ์š” (git commit -m 'Add some AmazingFeature')
  4. ๋ธŒ๋žœ์น˜์— Push ํ•˜์„ธ์š” (git push origin feature/AmazingFeature)
  5. Pull Request๋ฅผ ์—ด์–ด์ฃผ์„ธ์š”

๊ธฐ์—ฌ ์•„์ด๋””์–ด:

  • ์ƒˆ๋กœ์šด ์˜ˆ์ œ ์ถ”๊ฐ€ (gRPC, SignalR, Blazor ๋“ฑ)
  • ๊ธฐ์กด ์˜ˆ์ œ ๊ฐœ์„  ๋ฐ ๋ฒ„๊ทธ ์ˆ˜์ •
  • ๋ฌธ์„œ ๋ฒˆ์—ญ (์˜์–ด, ์ผ๋ณธ์–ด ๋“ฑ)
  • ์„ฑ๋Šฅ ์ตœ์ ํ™”
  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€

๐Ÿ“„ ๋ผ์ด์„ ์Šค

์ด ํ”„๋กœ์ ํŠธ๋Š” MIT ๋ผ์ด์„ ์Šค ํ•˜์— ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค.

MIT License

Copyright (c) 2025

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

๐Ÿ”— ์ฐธ๊ณ  ์ž๋ฃŒ

๊ณต์‹ ๋ฌธ์„œ

ํ”„๋ ˆ์ž„์›Œํฌ ๋ฐ ๋„๊ตฌ

  • Microsoft Agents AI - AI ์—์ด์ „ํŠธ ํ”„๋ ˆ์ž„์›Œํฌ
  • OpenRouter - ํ†ตํ•ฉ LLM API ๊ฒŒ์ดํŠธ์›จ์ด
  • Garnet - Microsoft์˜ Redis ํ˜ธํ™˜ ์บ์‹œ
  • LINQPad - .NET ๊ฐœ๋ฐœ ๋ฐ ์ฟผ๋ฆฌ ๋„๊ตฌ

์ปค๋ฎค๋‹ˆํ‹ฐ

๊ด€๋ จ ํ”„๋กœ์ ํŠธ


โญ ์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ๋„์›€์ด ๋˜์…จ๋‹ค๋ฉด Star๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”!

๐Ÿ’ฌ ์งˆ๋ฌธ์ด๋‚˜ ์ œ์•ˆ์‚ฌํ•ญ์ด ์žˆ์œผ์‹œ๋ฉด Issue๋ฅผ ์ƒ์„ฑํ•ด ์ฃผ์„ธ์š”.

About

.NET File-based App Example Codes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published