C# NativeAOT 크로스 빌드 테스트 프로젝트. Windows x64에서 AWS EC2 ARM64(Graviton)으로 소스를 전송하고, linux-arm64 네이티브 바이너리를 생성하는 워크플로우를 검증한다.
Cross-OS NativeAOT는 지원되지 않는다. Windows에서
dotnet publish -r linux-arm64 -p:PublishAot=true는 실패한다. 반드시 타겟 OS에서 빌드해야 한다.
[Windows x64 Host] [EC2 ARM64 (c8g/c7g)]
.NET SDK 10.0 .NET SDK 10.0
AWS CLI 2.x clang 18, zlib
SSH (ed25519) Ubuntu 24.04 LTS aarch64
| |
+---- scp (source) ----------->+
+---- ssh (build cmd) -------->+
+<--- scp (binary) -----------+
-
AWS CLI v2 설치
-
AWS 로그인
aws login aws configure set region ap-northeast-2
-
.env초기 설정.\ec2.ps1 init
인터랙티브 위저드가 실행되며, 두 가지 모드를 지원한다:
- 기존 인스턴스 선택 — 계정의 EC2 인스턴스를 조회하여 선택. AMI, 보안 그룹, 키페어를 자동 조회한다.
- 새 인스턴스 생성 — AMI 조회, 키페어 생성, 보안 그룹 생성, 인스턴스 생성까지 자동 수행한다.
수동 설정이 필요하면
.env.example을 복사하여 값을 채운다:copy .env.example .env
.env에서 설정을 로드하여 EC2 인스턴스를 제어한다.
.\ec2.ps1 init # .env 초기 설정 (기존 인스턴스 선택 or 새로 생성)
.\ec2.ps1 start # 인스턴스 시작 + IP/SSH 명령 출력
.\ec2.ps1 stop # 인스턴스 중지
.\ec2.ps1 status # 현재 상태 확인
.\ec2.ps1 ssh # SSH 바로 접속
.\ec2.ps1 ip # Public IP만 출력
.\ec2.ps1 web # AWS Console EC2 대시보드 열기# 1. 인스턴스 시작
.\ec2.ps1 start
# 2. 소스 전송
$IP = .\ec2.ps1 ip
scp -i $env:EC2_KEY_PATH -r AvaloniaCounter $env:EC2_SSH_USER@${IP}:~/
# 3. 원격 빌드
ssh -i $env:EC2_KEY_PATH $env:EC2_SSH_USER@$IP 'bash ~/remote-avalonia-aot.sh'
# 4. 바이너리 회수
scp -i $env:EC2_KEY_PATH $env:EC2_SSH_USER@${IP}:~/AvaloniaCounter/publish/AvaloniaCounter ./AvaloniaCounter-linux-arm64
# 5. 인스턴스 중지 (비용 절감)
.\ec2.ps1 stopaws-cli-test/
├── .env # 민감 정보 (git 제외)
├── .env.example # .env 템플릿
├── .gitignore
├── ec2.ps1 # EC2 관리 스크립트 (init/start/stop/ssh/web 등)
├── AvaloniaCounter/ # Avalonia 11 MVVM 카운터 앱
├── docs/
│ ├── aws-cli-setup.md # AWS CLI 설치/로그인
│ ├── ec2-arm64-instance.md # EC2 ARM64 인스턴스 관리
│ ├── dotnet-aot-environment.md # .NET AOT 빌드 환경
│ ├── cross-compilation.md # 크로스 컴파일 제약/전략
│ ├── avalonia-aot-build.md # Avalonia 11 AOT 빌드
│ ├── aot-benchmark.md # ARM vCPU/세대별 빌드 벤치마크
│ └── tag-index.md # 태그 레지스트리
├── benchmark.ps1 # ARM vCPU별 AOT 벤치마크
├── remote-benchmark.sh # EC2 빌드 타이머 (cold/warm)
├── remote-setup.sh # EC2 .NET 설치 확인
├── remote-aot-test.sh # EC2 콘솔 AOT 빌드
├── remote-avalonia-aot.sh # EC2 Avalonia AOT 빌드
├── fix-key.ps1 # SSH 키 줄바꿈 수정
├── block-device.json # EC2 EBS 설정
└── tags.json # EC2 태그 설정
| 항목 | .NET 9 (9.0.312) | .NET 10 (10.0.201) | 변화 |
|---|---|---|---|
| 바이너리 크기 | 23.0 MB | 17.5 MB | −24% |
| Cold 빌드 | 40.2s | 31.7s | −21% |
| Warm 빌드 | 37.4s | 28.0s | −25% |
| 포맷 | ELF 64-bit ARM aarch64 | ELF 64-bit ARM aarch64 | — |
.NET 10의 ILC 개선으로 바이너리 크기와 빌드 시간 모두 유의미하게 감소.
| Instance | 세대 | vCPU | Cold | Warm | 빌드당 비용 |
|---|---|---|---|---|---|
| c7g.xlarge | Graviton3 | 4 | 40.2s | 37.9s | ~$0.002 |
| c7g.2xlarge | Graviton3 | 8 | 36.7s | 32.6s | ~$0.003 |
| c8g.2xlarge | Graviton4 | 8 | 31.0s | 25.9s | ~$0.003 |
| c8g.4xlarge | Graviton4 | 16 | 32.1s | 26.7s | ~$0.005 |
| c8g.8xlarge | Graviton4 | 32 | 29.9s | 24.8s | ~$0.009 |
가성비 최적: c8g.2xlarge (8코어) — 8코어 이상은 ILC 링킹 병목으로 효과 미미. 상세 분석은
docs/aot-benchmark.md참조.
docs/ 디렉토리에 YAML frontmatter 포맷으로 작성되어 있다. docs/tag-index.md에서 태그로 관련 문서를 검색할 수 있다.
grep -rl "tags:.*native-aot" docs/