안녕하세요, 남정현입니다.
File-based App에 대한 개인적인 연구 결과들을 종합한 또 다른 커뮤니티 프로젝트인 Cadenza를 기획했고, 실제 테스트를 거쳐 v1.0.7까지 다듬어 공개합니다.
-
NuGet: Cadenza · Cadenza.Worker · Cadenza.Web · Cadenza.Mcp
Cadenza가 무엇인가
.cs 파일 한 장이 곧 프로그램이 되는 .NET 10의 file-based apps 모드를 ergonomic하게 만들어주는 custom MSBuild SDK 가족입니다. 4개 변종을 같은 원리로 묶어 두었습니다:
| SDK | Use case | 기반 |
|---|---|---|
Cadenza |
콘솔 스크립트, CLI 유틸리티 | Microsoft.NET.Sdk |
Cadenza.Worker |
백그라운드 서비스, 데몬 | Microsoft.NET.Sdk.Worker |
Cadenza.Web |
웹 API, Minimal API 스크립트 | Microsoft.NET.Sdk.Web |
Cadenza.Mcp |
MCP 서버 (Claude Desktop · Cursor · Cline) | 공식 ModelContextProtocol SDK |
가장 짧은 예시 — 마크다운 파일 크기 출력:
#!/usr/bin/env dotnet run
#:sdk Cadenza@1.0.7
foreach (var file in Glob("**/*.md"))
WriteLine($"{file}: {ReadText(file).Length:N0} bytes");
Glob, ReadText, WriteLine, Run 등이 global using static을 통해 접두사 없이 호출됩니다. .cs 한 파일로 콘솔 도구 한 개가 완성되고, 그 자체로 publish하면 단일 자체 포함 바이너리가 됩니다.
왜 만들었는가
.NET 10이 file-based apps라는 기능을 가져왔습니다. dotnet run app.cs 한 줄로 csproj 없이 .cs 파일을 실행할 수 있게 됐죠. 그런데 막상 써보니 capability는 SDK에 있는데 ergonomics가 비어 있다는 인상이 강했습니다. 여전히 using 문, PackageReference, 호스트 부트스트랩을 사용자가 매번 직접 써야 했습니다.
Cadenza는 그 자리를 채웁니다. SDK 안에 wiring을 미리 박아두고, 사용자는 #:sdk Cadenza@1.0.7 한 줄과 비즈니스 로직만 작성합니다. 4개 변종이 같은 패턴을 공유하므로 학습 비용도 한 번이면 됩니다.
이름의 배경 — 카덴차(cadenza)는 협주곡 중 오케스트라가 멎고 독주자가 홀로 연주하는 구간입니다. 솔로지만 완성된 음악이고, 협주곡과 대립이 아니라 같은 음악의 다른 부분이죠. 한 파일 .cs 스크립트가 .NET이라는 음악의 카덴차 — csproj 기반 .NET을 부정하지 않으면서 .NET의 다른 모드로 존재한다는 의미를 담았습니다. C#이 이미 #(sharp) 음악 기호로 이름지어진 언어라는 점도 자연스럽게 맞물립니다.
시작하기
.NET 10 SDK 10.0.300 이상이 필요합니다.
# 1) 빈 디렉토리에서 hello.cs 작성
cat > hello.cs << 'EOF'
#!/usr/bin/env dotnet run
#:sdk Cadenza@1.0.7
WriteLine("Hello, Cadenza!");
EOF
# 2) 실행
dotnet run hello.cs
# 3) 단일 바이너리 배포 (선택)
dotnet publish hello.cs -r linux-x64 -c Release
VS Code + C# Dev Kit 환경에서도 정상 동작하는 것을 확인했습니다. 자세한 사용법과 변종별 tier 1 API는 GitHub README와 spec 문서에서 확인하실 수 있습니다.
한 가지 주의점
#:sdk 지시자의 버전은 정확한 SemVer만 허용됩니다. Cadenza@1.* 같은 floating 패턴은 MSBuild SDK resolver가 평가하지 못합니다 — restore 이전 단계에서 SDK가 결정되어야 하기 때문이고, PackageReference와 다른 자리입니다. 새 릴리스로 이동할 때는 #:sdk 줄을 직접 갱신하거나, 같은 디렉토리의 global.json의 msbuild-sdks에 버전을 중앙화하는 방식이 있습니다. README의 troubleshooting 섹션에 자세히 적어두었습니다.