다음을 통해 공유


iOS 및 Mac Catalyst에서 네이티브 AOT 배포

네이티브 AOT 배포는 iOS 및 Mac Catalyst에서 네이티브 코드로 컴파일된 AOT(Ahead-of-Time)인 .NET 다중 플랫폼 앱 UI(.NET MAUI) 앱을 생성합니다. 네이티브 AOT는 정적 프로그램 분석, 정적으로 참조되지 않는 코드를 제거하는 데 적극적인 앱의 전체 트리밍 및 미리 구성된 코드 생성을 수행합니다.

네이티브 AOT 앱을 게시하고 배포하면 다음과 같은 이점이 있습니다.

  • 앱 패키지 크기가 감소했습니다.
  • 시작 시간이 빨라집니다.
  • 빌드 시간이 빨라집니다.

네이티브 AOT는 .NET 런타임의 특정 측면에 대한 사용 제한 사항을 도입하며 앱 크기 및 성능이 중요한 시나리오에서만 사용해야 합니다. 앱을 네이티브 AOT 요구 사항에 맞게 조정해야 합니다. 즉, 앱이 완전히 트리밍되고 AOT가 호환되는지 확인합니다. 네이티브 AOT 제한 사항에 대한 자세한 내용은 네이티브 AOT 제한 사항을 참조 하세요.

네이티브 AOT 배포를 사용하도록 설정하면 빌드 시스템은 코드 및 모든 종속성을 분석하여 전체 트리밍 및 AOT 컴파일에 적합한지 확인합니다. 비호환성이 감지되면 트리밍 및 AOT 경고가 생성됩니다. 단일 트리밍 또는 AOT 경고는 앱이 네이티브 AOT 배포와 호환되지 않으며 제대로 작동하지 않을 수 있음을 의미합니다. 따라서 네이티브 AOT 배포용 앱을 빌드할 때 모든 트리밍 및 AOT 경고를 검토하고 수정해야 합니다. 이 작업을 수행하지 않으면 필요한 코드를 제거할 수 있으므로 런타임에 예외가 발생할 수 있습니다. 경고를 표시하지 않으면 AOT 배포된 앱을 철저히 테스트하여 제거된 앱에서 기능이 변경되지 않았는지 확인해야 합니다. 자세한 내용은 트리밍 경고 소개 및 AOT 경고 소개를 참조하세요.

참고 항목

타사 라이브러리에 대해 발생하는 경우와 같이 트리밍 및 AOT 경고를 수정할 수 없는 경우가 있을 수 있습니다. 이러한 경우 타사 라이브러리가 완전히 호환되도록 업데이트해야 합니다.

네이티브 AOT 성능 이점

네이티브 AOT 앱을 게시하고 배포하면 일반적으로 최대 2.5배 더 작은 앱과 일반적으로 최대 2배 더 빠르게 시작하는 앱이 생성됩니다. 그러나 정확한 성능 이점은 사용 중인 플랫폼, 앱이 실행 중인 디바이스 및 앱 자체를 포함하는 여러 요인에 따라 달라집니다.

Important

다음 차트는 iOS 및 Mac Catalyst에서 앱에 대한 네이 dotnet new maui 티브 AOT 배포의 일반적인 성능 이점을 보여 줍니다. 그러나 정확한 데이터는 하드웨어에 따라 달라지며 향후 릴리스에서 변경될 수 있습니다.

다음 차트에서는 다양한 배포 모델에서 iOS 및 Mac Catalyst의 앱에 대한 dotnet new maui 앱 패키지 크기를 보여 줍니다.

다양한 배포 모델에서 앱 패키지 크기를 보여 주는 차트입니다.

위의 차트는 일반적으로 Native AOT가 기본 배포 모델에 비해 iOS 및 Mac Catalyst 모두에 대해 2배 이상의 작은 앱을 생성한다는 것을 보여 줍니다.

다음 차트는 iOS 및 Mac Catalyst on Mono 및 Native AOT 배포의 앱에 대한 dotnet new maui 특정 하드웨어의 평균 시작 시간을 보여줍니다.

Mono 및 Native AOT의 평균 앱 시작 시간을 보여 주는 차트입니다.

위의 차트는 Native AOT가 일반적으로 iOS 디바이스에서 최대 2배 빠른 시작 시간과 Mono 배포에 비해 Mac Catalyst의 시작 시간이 1.2배 더 빠르다는 것을 보여줍니다.

다음 차트는 다양한 배포 모델에서 iOS 및 Mac Catalyst의 앱에 대한 dotnet new maui 특정 하드웨어의 평균 빌드 시간을 보여 줍니다.

Mono 및 Native AOT의 평균 앱 빌드 시간을 보여 주는 차트입니다.

위의 차트는 일반적으로 네이티브 AOT가 기본 배포 모델에 비해 iOS 디바이스에서 빌드 시간이 최대 2.8배 더 빠르다는 것을 보여줍니다. Mac Catalyst의 경우 빌드 시간은 arm64 단일 RID 앱과 비교할 수 있지만 Mono 배포에 비해 유니버설 앱의 경우 약간 느립니다.

Important

많은 시나리오에서 Native AOT는 더 작고 빠른 앱을 생성합니다. 그러나 일부 시나리오에서는 네이티브 AOT가 더 작고 빠른 앱을 생성하지 않을 수 있습니다. 따라서 네이티브 AOT 배포를 사용하도록 설정한 결과를 확인하기 위해 앱을 테스트하고 프로파일링하는 것이 중요합니다.

네이티브 AOT를 사용하여 게시

네이티브 AOT 배포 모델은 빌드 속성 및 명령을 사용하여 사용하도록 설정 $(PublishAot) 됩니다 dotnet publish . 다음 예제에서는 iOS 및 Mac Catalyst에서 네이티브 AOT 배포를 사용하도록 프로젝트 파일을 수정하는 방법을 보여 줍니다.

<PropertyGroup>
  <!-- enable trimming and AOT analyzers on all platforms -->
  <IsAotCompatible>true</IsAotCompatible>

  <!-- select platforms to use with NativeAOT -->
  <PublishAot Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">true</PublishAot>
  <PublishAot Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">true</PublishAot>
</PropertyGroup>

$(IsAotCompatible) 빌드 속성을 모든 플랫폼에 true대해 트리밍 및 AOT 분석기를 사용하도록 설정합니다. 이러한 분석기는 트리밍 또는 AOT와 호환되지 않는 코드를 식별하는 데 도움이 됩니다.

iOS 및 Mac Catalyst의 경우 조건부로 true설정 $(PublishAot) 하면 게시 중에 빌드 및 네이티브 AOT 컴파일 중에 동적 코드 사용 현황 분석을 사용할 수 있습니다. 네이티브 AOT 분석에는 앱의 모든 코드와 앱이 의존하는 라이브러리가 포함됩니다.

Warning

빌드 속성은 $(PublishAot) 빌드 구성에 의해 조건화되어서는 안 됩니다. 트리밍 기능 스위치는 빌드 속성의 $(PublishAot) 값에 따라 사용하거나 사용하지 않도록 설정되며, 코드가 동일하게 작동하도록 모든 빌드 구성에서 동일한 기능을 사용하거나 사용하지 않도록 설정해야 합니다. 기능 스위치 트리밍에 대한 자세한 내용은 기능 스위치 트리밍을 참조 하세요.

네이티브 AOT 앱이 올바르게 작동하는지 확인하는 유일한 방법은 이를 사용하여 dotnet publish 게시하고 코드 및 해당 종속성에 의해 생성되는 트리밍 또는 AOT 경고가 없는지 확인하는 것입니다. 특히 . dotnet build -t:Publish dotnet publish

다음 dotnet publish 명령을 사용하여 네이티브 AOT 배포를 사용하여 iOS 및 Mac Catalyst에 앱을 게시합니다.

# iOS
dotnet publish -f net9.0-ios -r ios-arm64

# Mac Catalyst
dotnet publish -f net9.0-maccatalyst -r maccatalyst-arm64
dotnet publish -f net9.0-maccatalyst -r maccatalyst-x64

# Universal Mac Catalyst apps
# (when <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> is set in the project file)
dotnet publish -f net9.0-maccatalyst

개발 수명 주기 초기에 트리밍 또는 AOT 문제를 검색하기 위해 앱을 자주 게시합니다.

네이티브 AOT 제한 사항

네이티브 AOT는 .NET 런타임의 특정 측면에 대한 사용 제한 사항을 도입하며 앱 크기 및 성능이 중요한 시나리오에서만 사용해야 합니다. 앱을 네이티브 AOT 요구 사항에 맞게 조정해야 합니다. 즉, 앱이 완전히 트리밍되고 AOT와 호환되도록 해야 하며, 이렇게 하려면 많은 작업이 필요할 수 있습니다. 네이티브 AOT 배포.NET 제한 사항 외에도 .NET MAUI용 네이티브 AOT 배포에는 추가 제한 사항이 있습니다.

앱이 사용하는 타사 라이브러리는 AOT와 호환되지 않을 수 있습니다. 라이브러리가 트리밍되고 AOT가 호환되는지 확인하는 유일한 방법은 네이티브 AOT 배포 및 명령을 사용하여 앱을 게시하고 dotnet publish 네이티브 AOT 컴파일러가 라이브러리에 대한 경고를 생성하는지 확인하는 것입니다. 고유한 라이브러리 AOT 호환성에 대한 자세한 내용은 네이티브 AOT와 호환되는 라이브러리를 만드는 방법을 참조하세요.

리플렉션 및 동적 코드

네이티브 AOT 배포는 코드 및 해당 종속성에서 리플렉션 사용을 제한하며, 네이티브 AOT 컴파일러가 리플렉션 패턴을 이해하는 데 도움이 되도록 주석을 사용해야 할 수 있습니다. 컴파일러가 리플렉션 패턴을 발견하면 정적으로 분석할 수 없으므로 앱을 빌드할 수 없으므로 트리밍 경고가 생성됩니다. 네이티브 AOT를 사용하면 앱에서 동적 코드를 사용할 수 없게 됩니다. 예를 들어 컴파일은 System.Linq.Expressions 예상대로 작동하지 않으며 런타임에 어셈블리를 로드하고 실행할 수 없습니다. 컴파일러에서 미리 컴파일할 수 없는 동적 패턴이 발견되면 AOT 경고가 생성됩니다.

.NET MAUI 앱에서 이는 다음을 의미합니다.

  • 모든 XAML은 미리 컴파일되어야 합니다. 따라서 XAML 컴파일을 사용하지 않도록 설정하지 않았는지, 모든 바인딩이 컴파일되었는지 확인합니다. 자세한 내용은 XAML 컴파일컴파일된 바인딩을 참조하세요.
  • 모든 바인딩 식은 문자열로 설정된 바인딩 경로가 아니라 컴파일된 바인딩을 사용해야 합니다. 자세한 내용은 컴파일된 바인딩을 참조 하세요.
  • XAML의 속성에 호환되지 않는 형식의 값을 할당하거나 다른 형식의 두 속성이 데이터 바인딩을 사용하는 경우 암시적 변환 연산자를 호출하지 않을 수 있습니다. 대신, 형식에 대한 a를 TypeConverter 정의하고 TypeConverterAttribute. 자세한 내용은 암시적 변환 연산자를 대체할 TypeConverter 정의를 참조 하세요.
  • 메서드를 사용하여 런타임 LoadFromXaml 에 XAML을 구문 분석할 수 없습니다. 런타임 DynamicallyAccessedMembers 에 로드할 수 있는 모든 형식에 특성 또는 DynamicDependency 특성에 주석을 추가하여 트리밍을 안전하게 만들 수 있지만 이는 오류가 발생하기 쉬울 수 있으며 권장되지 않습니다.
  • 이 옵션을 사용하여 QueryPropertyAttribute 탐색 데이터를 받는 것은 작동하지 않습니다. 대신 쿼리 매개 변수를 IQueryAttributable 수락해야 하는 형식에 대한 인터페이스를 구현해야 합니다. 자세한 내용은 단일 메서드를 사용하여 탐색 데이터 처리를 참조하세요.
  • 속성이 SearchHandler.DisplayMemberName 작동하지 않을 수 있습니다. 대신 결과의 모양을 SearchHandler 정의하는 방법을 제공해야 ItemTemplate 합니다. 자세한 내용은 검색 결과 항목 모양 정의를 참조 하세요.

Important

Mono 인터프리터는 네이티브 AOT 배포 $(UseInterpreter) 와 호환되지 않으므로 네이티브 AOT를 사용할 때 MSBuild 속성과 $(MtouchInterpreter) MSBuild 속성은 영향을 주지 않습니다. Mono 인터프리터에 대한 자세한 내용은 iOS 및 Mac Catalyst의 Mono 인터프리터를 참조하세요.

트리밍 경고에 대한 자세한 내용은 트리밍 경고 소개를 참조 하세요. AOT 경고에 대한 자세한 내용은 AOT 경고 소개를 참조 하세요.

네이티브 AOT 배포에 앱 조정

다음 검사 목록을 사용하여 네이티브 AOT 배포 요구 사항에 맞게 앱을 조정할 수 있습니다.

  • 모든 XAML이 컴파일되었는지 확인합니다.
    • 모든 [XamlCompilation(XamlCompilationOptions.Skip)] 사용량을 제거합니다.
    • 모든 <?xaml-comp compile="false" ?> 사용량을 제거합니다.
  • 메서드에 대한 모든 호출을 제거합니다 LoadFromXaml .
  • 모든 데이터 바인딩이 컴파일되었는지 확인합니다. 자세한 내용은 컴파일된 바인딩을 참조 하세요.
    • 모든 XAML 데이터 바인딩에 주석이 추가 x:DataType되었는지 확인합니다.
    • 모든 코드 데이터 바인딩이 모든 문자열 기반 바인딩을 람다 기반 바인딩으로 대체해야 합니다.
  • 모든 [QueryProperty(...)] 사용을 인터페이스의 구현으로 IQueryAttributable 바꿉니다. 자세한 내용은 단일 메서드를 사용하여 탐색 데이터 처리를 참조하세요.
  • 모든 SearchHandler.DisplayMemberName 사용량을 .로 대체 ItemTemplate합니다. 자세한 내용은 검색 결과 항목 모양 정의를 참조 하세요.
  • XAML에서 사용되는 형식에 대한 모든 암시적 변환 연산자를 a로 TypeConverter바꾸고 , 이 연산자를 TypeConverterAttribute사용하여 형식에 연결합니다. 자세한 내용은 암시적 변환 연산자를 대체할 TypeConverter 정의를 참조 하세요.
    • 형식에서 형식 A BConvertTo 으로 변환할 때 연결된 A 형식 변환기에서 메서드가 사용되거나 ConvertFrom 연결된 B 형식 변환기에서 메서드가 사용됩니다.
    • 원본 및 대상 형식 모두에 연결된 형식 변환기가 있는 경우 둘 중 하나를 사용할 수 있습니다.
  • 원본 생성기를 사용하여 모든 정규식을 컴파일합니다. 자세한 내용은 .NET 정규식 원본 생성기를 참조하세요.
  • JSON serialization 및 deserialization에서 원본 생성 컨텍스트를 사용하는지 확인합니다. 자세한 내용은 최소 API 및 JSON 페이로드를 참조 하세요.
  • 트리밍 또는 AOT 경고를 검토하고 수정합니다. 자세한 내용은 트리밍 경고 소개 및 AOT 경고 소개를 참조하세요.
  • 앱을 철저히 테스트합니다.

iOS 및 Mac Catalyst에서 네이티브 AOT 진단 지원

네이티브 AOT 및 Mono는 진단 및 계측 기능의 하위 집합을 공유합니다. Mono의 다양한 진단 도구로 인해 네이티브 AOT 대신 Mono 내에서 문제를 진단하고 디버그하는 것이 도움이 될 수 있습니다. 트리밍 및 AOT 호환 앱은 동작 차이가 없어야 하므로 조사는 두 런타임에 모두 적용되는 경우가 많습니다.

다음 표에서는 iOS 및 Mac Catalyst에서 Native AOT를 사용하는 진단 지원을 보여 줍니다.

기능 완벽하게 지원 부분적으로 지원됨 지원되지 않음
관측 가능성 및 원격 분석 부분적으로 지원됨
개발 시간 진단 완전하게 지원됨
네이티브 디버깅 부분적으로 지원됨
CPU 프로파일링 부분적으로 지원됨
힙 분석 지원되지 않음

다음 섹션에서는 이 진단 지원에 대한 추가 정보를 제공합니다.

가시성 및 원격 분석

TCP/IP를 통해 iOS 및 Mac Catalyst에서 실행되는 .NET 애플리케이션과 진단 도구를 연결하는 dotnet-dsrouter를 통해 모바일 플랫폼에서 .NET MAUI 애플리케이션 추적을 사용할 수 있습니다. 그러나 Native AOT는 TCP/IP 스택으로 빌드된 EventPipe/DiagnosticServer 구성 요소를 지원하지 않으므로 현재 이 시나리오와 호환되지 않습니다. 관찰성은 여전히 코드에서 명시적으로 달성할 수 있습니다.

개발 시간 진단

.NET CLI 도구는 다음과 같은 build publish별도의 명령을 제공합니다. dotnet build (또는 Start Debugging (F5) Visual Studio Code에서) .NET MAUI iOS 또는 Mac Catalyst 애플리케이션을 빌드하거나 시작할 때 기본적으로 Mono를 사용합니다. dotnet publish 이 배포 모델이 프로젝트 파일에서 사용하도록 설정된 경우에만 네이티브 AOT 애플리케이션을 만듭니다.

모든 진단 도구가 게시된 네이티브 AOT 애플리케이션에서 원활하게 작동하는 것은 아닙니다. 그러나 트리밍 및 AOT 호환되는 모든 애플리케이션(즉, 빌드 시 트리밍 및 AOT 경고를 생성하지 않는 애플리케이션)에는 Mono와 Native AOT 간의 동작 차이가 없어야 합니다. 따라서 모바일 애플리케이션 개발 주기 동안 개발자는 핫 다시 로드 같은 모든 .NET 개발 시간 진단 도구를 계속 사용할 수 있습니다.

평소와 같이 애플리케이션을 개발, 디버그 및 테스트하고 마지막 단계 중 하나로 Native AOT를 사용하여 최종 앱을 게시해야 합니다.

네이티브 디버깅

개발 중에 .NET MAUI iOS 또는 Mac Catalyst 애플리케이션을 실행하면 기본적으로 Mono에서 실행됩니다. 그러나 프로젝트 파일에서 네이티브 AOT 배포를 사용하는 경우 애플리케이션이 빌드 시 트리밍 및 AOT 경고를 생성하지 않는 경우 Mono와 Native AOT 간에 동작이 동일해야 합니다. 애플리케이션이 이 요구 사항을 충족하는 경우 개발 및 테스트에 표준 Visual Studio Code 관리 디버깅 엔진을 사용할 수 있습니다.

게시 후 네이티브 AOT 애플리케이션은 진정한 네이티브 이진 파일이므로 관리되는 디버거가 작동하지 않습니다. 그러나 네이티브 AOT 컴파일러는 디버그 lldb할 수 있는 완전히 네이티브 실행 파일을 생성합니다. Mac Catalyst 앱을 lldb 사용하여 디버깅하는 것은 동일한 시스템에서 실행되므로 바로 진행됩니다. 그러나 NativeAOT iOS 애플리케이션을 디버깅하려면 추가 작업이 필요합니다.

Native AOT를 사용하여 .NET MAUI iOS 애플리케이션 디버그

네이티브 AOT와 호환되고 이 배포 모델을 사용하여 올바르게 구성되고 게시된 .NET MAUI iOS 애플리케이션은 다음과 같이 디버그할 수 있습니다.

  1. 네이티브 AOT 대상 지정을 사용하여 ios-arm64 앱을 게시하고 다음 정보를 기록해 둡다.

    • 애플리케이션 이름(아래 <app-name>참조).
    • 번들 식별자(아래에서 <bundle-identifier>참조).
    • 게시된 애플리케이션의 보관 .ipa 파일 경로입니다(아래에서 <path-to-ipa>참조).
  2. 물리적 디바이스 ID 가져오기(아래 참조):<device-identifier>

    xcrun devicectl list devices
    
  3. 물리적 디바이스에 앱을 설치합니다.

    xcrun devicectl device install app --device <device-identifier> <path-to-ipa>
    
  4. 물리적 디바이스에서 앱을 시작합니다.

    xcrun devicectl device process launch --device <device-identifier> --start-stopped <bundle-identifier>
    
  5. 물리적 디바이스를 열고 lldb 연결합니다.

    (lldb) device select <device-identifier>
    (lldb) device process attach -n <app-name>
    

이러한 단계를 성공적으로 완료하면 네이티브 AOT .NET MAUI iOS 애플리케이션 lldb디버깅을 시작할 수 있습니다.

기호 파일의 중요도

기본적으로 디버그 기호는 애플리케이션의 이진 파일에서 .dSYM 파일로 제거됩니다. 이 파일은 디버거 및 사후 분석 도구에서 로컬 변수, 소스 줄 번호에 대한 정보를 표시하고 크래시 덤프의 스택 추적을 다시 만드는 데 사용됩니다. 따라서 애플리케이션을 App Store에 제출하기 전에 기호 파일을 유지해야 합니다.

CPU 프로파일링

Xcode 계측 을 사용하여 네이티브 AOT 애플리케이션의 CPU 샘플을 수집할 수 있습니다.

힙 분석

힙 분석은 현재 Native AOT에서 지원되지 않습니다.

참고 항목