트리밍 옵션

다음 MSBuild 속성 및 항목은 트리밍된 자체 포함 배포의 동작에 영향을 줍니다. 일부 옵션에는 트리밍을 구현하는 기본 도구의 이름인 ILLink가 언급됩니다. 기본 도구에 대한 자세한 내용은 트리머 설명서를 참조하세요.

PublishTrimmed를 사용하는 트리밍은 .NET Core 3.0에서 도입되었습니다. 다른 옵션은 .NET 5 이상 버전에서만 사용할 수 있습니다.

트리밍 사용

  • <PublishTrimmed>true</PublishTrimmed>

    게시 중에 트리밍을 사용하도록 설정합니다. 또한 트리밍과 호환되지 않는 기능을 해제하고 빌드 중에 트리밍 분석을 사용하도록 설정합니다.

참고 항목

명령줄에서 사용하도록 트리밍을 지정하면 디버깅 환경이 달라지고 최종 제품에서 추가 버그가 발생할 수 있습니다.

이 설정을 프로젝트 파일에 배치하여 dotnet publish뿐만 아니라 dotnet build 중에도 이 설정이 적용되도록 합니다.

이 설정은 트리밍을 사용하도록 설정하고 기본적으로 모든 어셈블리를 트리밍합니다. .NET 6에서는 [AssemblyMetadata("IsTrimmable", "True")]를 통해 트리밍에 옵트인된 어셈블리만 기본적으로 트리밍됩니다. <TrimMode>partial</TrimMode>를 사용하여 이전 동작으로 돌아갈 수 있습니다.

이 설정은 트리밍하도록 구성된 모든 어셈블리를 트리밍합니다. .NET 6에서 Microsoft.NET.Sdk를 사용하면 [AssemblyMetadata("IsTrimmable", "True")]가 있는 모든 어셈블리가 포함됩니다. 이 경우는 .NET 런타임 어셈블리입니다. .NET 5에서는 netcoreapp 런타임 팩의 어셈블리가 <IsTrimmable> MSBuild 메타데이터를 통한 트리밍에 구성됩니다. 다른 SDK는 서로 다른 기본값을 정의할 수 있습니다.

또한 이 설정은 트리밍 호환성 Roslyn 분석기는 사용하도록 설정하고 트리밍과 호환되지 않는 기능은 사용하지 않도록 설정합니다.

트리밍 세분성

TrimMode 속성을 사용하여 트리밍 세분성을 partial 또는 full 중 하나로 설정합니다. 콘솔 앱(및 .NET 8부터 웹 SDK 앱)에 대한 기본 설정은 full입니다.

<TrimMode>full</TrimMode>

트리밍에 옵트인된 어셈블리만 트리밍하려면 속성을 partial로 설정합니다.

<TrimMode>partial</TrimMode>

트리밍 모드를 partial로 변경하면 <TrimmableAssembly> MSBuild 항목을 사용하여 개별 어셈블리를 트리밍에 옵트인할 수 있습니다.

<ItemGroup>
  <TrimmableAssembly Include="MyAssembly" />
</ItemGroup>

이는 어셈블리를 빌드할 때 [AssemblyMetadata("IsTrimmable", "True")]를 설정하는 것과 같습니다.

다음 세분성 설정은 적극적으로 사용되지 않는 IL을 삭제하는 방법을 제어합니다. 모든 트리머 입력 어셈블리에 영향을 주는 속성으로 설정하거나 속성 설정을 재정의하는 개별 어셈블리의 메타데이터로 설정할 수 있습니다.

  • <TrimMode>link</TrimMode>

    멤버 수준 트리밍을 사용하면 형식에서 사용되지 않는 멤버가 제거됩니다. 이는 .NET 6 이상에서 기본 동작입니다.

  • <TrimMode>copyused</TrimMode>

    어셈블리 수준 트리밍을 사용하도록 설정하면 어셈블리의 일부가 정적으로 인식되는 방식으로 사용되는 경우 전체 어셈블리가 유지됩니다.

<IsTrimmable>true</IsTrimmable> 메타데이터가 있지만 명시적 TrimMode가 없는 어셈블리는 전역 TrimMode를 사용합니다. Microsoft.NET.Sdk의 기본값 TrimMode는 .NET 6 이상에서는 link이고 이전 버전에서는 copyused입니다.

추가 어셈블리 트리밍

.NET 6 이상에서 PublishTrimmed는 다음 어셈블리 수준 특성을 사용하여 어셈블리를 트리밍합니다.

[AssemblyMetadata("IsTrimmable", "True")]

프레임워크 라이브러리에 이 특성이 있습니다. .NET 6 이상에서는 이름(.dll 확장명 제외)을 기준으로 어셈블리를 지정하여 이 특성 없이 라이브러리에 대한 트리밍을 선택할 수도 있습니다.

개별 어셈블리에 대한 트리밍 설정

트리밍된 앱을 게시하면 SDK는 트리밍을 위해 처리할 파일 세트를 나타내는 ManagedAssemblyToLink라는 ItemGroup을 계산합니다. ManagedAssemblyToLink에는 어셈블리별로 트리밍 동작을 제어하는 메타데이터가 있을 수 있습니다. 해당 메타데이터를 설정하려면 기본 제공 PrepareForILLink 대상 전에 실행되는 대상을 만듭니다. 다음 예제에서는 MyAssembly 트리밍을 사용하도록 설정하는 방법을 보여 줍니다.

<Target Name="ConfigureTrimming"
        BeforeTargets="PrepareForILLink">
  <ItemGroup>
    <ManagedAssemblyToLink Condition="'%(Filename)' == 'MyAssembly'">
      <IsTrimmable>true</IsTrimmable>
    </ManagedAssemblyToLink>
  </ItemGroup>
</Target>

위 예제에서 [AssemblyMetadata("IsTrimmable", "True"])가 있는 어셈블리에 <IsTrimmable>false</IsTrimmable>를 설정하여 라이브러리 작성자가 지정한 트리밍 동작을 재정의할 수도 있습니다.

SDK는 게시 중에 해당 세트를 계산하고 변경하지 않을 것으로 예상하기 때문에 ManagedAssemblyToLink에서 항목을 추가하거나 제거하지 마세요. 지원되는 메타데이터는 다음과 같습니다.

  • <IsTrimmable>true</IsTrimmable>

    지정된 어셈블리가 트리밍되는지 여부를 제어합니다.

  • <TrimMode>copyused</TrimMode> 또는 <TrimMode>link</TrimMode>

    해당 어셈블리의 트리밍 세분성을 제어합니다. 이 옵션은 전역 TrimMode보다 우선합니다. 어셈블리에서 TrimMode를 설정하는 것은 <IsTrimmable>true</IsTrimmable>을 의미합니다.

  • <TrimmerSingleWarn>True</TrimmerSingleWarn> 또는 <TrimmerSingleWarn>False</TrimmerSingleWarn>

    이 어셈블리에 대한 단일 경고를 표시할지 여부를 제어합니다.

루트 어셈블리

어셈블리가 트리밍되지 않은 경우 "rooted"로 간주됩니다. 즉, 해당 어셈블리와 정적으로 인식되는 모든 종속성이 유지됩니다. 추가 어셈블리는 이름(.dll 확장명이 없음)으로 “루트로 지정” 될 수 있습니다.

<ItemGroup>
  <TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>

루트 설명자

분석을 위한 루트를 지정하는 또 다른 방법은 트리머 설명자 형식을 사용하는 XML 파일을 사용하는 것입니다. 이렇게 하면 전체 어셈블리가 아닌 특정 멤버를 루트로 지정할 수 있습니다.

<ItemGroup>
  <TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>

예를 들어 MyRoots.xml은 애플리케이션에서 동적으로 액세스하는 특정 메서드를 루트로 지정할 수 있습니다.

<linker>
  <assembly fullname="MyAssembly">
    <type fullname="MyAssembly.MyClass">
      <method name="DynamicallyAccessedMethod" />
    </type>
  </assembly>
</linker>

분석 경고

  • <SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>

    트리밍 분석 경고를 사용합니다.

트리밍은 정적으로 연결할 수 없는 IL을 제거합니다. 리플렉션을 사용하는 앱 또는 동적 종속성을 만드는 다른 패턴은 트리밍을 통해 중단될 수 있습니다. 이러한 패턴에 관해 경고하려면 <SuppressTrimAnalysisWarnings>false로 설정합니다. 여기에는 고유한 코드, 라이브러리 코드 및 프레임워크 코드를 비롯한 전체 앱에 관한 경고가 포함됩니다.

Roslyn 분석기

.NET 6 이상에서 PublishTrimmed를 설정하면 제한된 분석 경고 집합을 표시하는 Roslyn 분석기도 사용하도록 설정됩니다. 분석기를 PublishTrimmed와 독립적으로 사용하거나 사용하지 않도록 설정할 수도 있습니다.

  • <EnableTrimAnalyzer>true</EnableTrimAnalyzer>

    트리밍 분석 경고의 하위 집합에 Roslyn 분석기를 사용하도록 설정합니다.

경고 표시 안 함

NoWarn, WarningsAsErrors, WarningsNotAsErrorsTreatWarningsAsErrors를 포함하여 도구 체인에서 적용하는 일반적인 MSBuild 속성을 사용하여 개별 경고 코드를 표시하지 않을 수 있습니다. ILLink 오류로 경고 동작을 독립적으로 제어하는 추가 옵션이 있습니다.

  • <ILLinkTreatWarningsAsErrors>false</ILLinkTreatWarningsAsErrors>

    ILLink 경고를 오류로 처리하지 마세요. 이렇게 하면 전역으로 컴파일러 경고를 오류로 처리할 때 트리밍 분석 경고를 오류로 전환하지 않을 수 있습니다.

자세한 경고 표시

.NET 6 이상에서 트리밍 분석은 PackageReference에서 제공되는 각 어셈블리에 대해 최대 하나의 경고를 생성하여 어셈블리의 내부가 트리밍과 호환되지 않음을 나타냅니다. 모든 어셈블리의 개별 경고를 표시할 수도 있습니다.

  • <TrimmerSingleWarn>false</TrimmerSingleWarn>

    어셈블리당 단일 경고로 축소하지 않고 자세한 경고를 모두 표시합니다.

기호 제거

기호는 일반적으로 잘린 어셈블리와 일치하도록 잘립니다. 모든 기호를 제거할 수도 있습니다.

  • <TrimmerRemoveSymbols>true</TrimmerRemoveSymbols>

    포함된 PDB 및 별도 PDB 파일을 포함하여 트리밍된 애플리케이션에서 기호를 제거합니다. 이는 애플리케이션 코드 및 기호와 함께 제공되는 모든 종속성 둘 다에 다 적용됩니다.

SDK를 사용하여 DebuggerSupport 속성을 통해 디버거 지원을 사용하지 않도록 설정할 수도 있습니다. 디버거 지원이 사용되지 않으면 트리밍은 기호를 자동으로 제거합니다(TrimmerRemoveSymbols가 기본적으로 true로 설정됨).

프레임워크 라이브러리 기능 트리밍

프레임워크 라이브러리의 여러 기능 영역은 사용할 수 없는 기능의 코드를 제거할 수 있도록 설정하는 트리머 지시문과 함께 제공됩니다.

  • <AutoreleasePoolSupport>false</AutoreleasePoolSupport> (기본값)

    지원되는 플랫폼에서 autorelease 풀을 만드는 코드를 제거합니다. 관리형 스레드의 AutoreleasePool을 참조하세요. .NET SDK의 기본값입니다.

  • <DebuggerSupport>false</DebuggerSupport>

    더 나은 디버깅 환경을 가능하게 하는 코드를 제거합니다. 이 설정은 기호도 제거합니다.

  • <EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>

    BinaryFormatter serialization 지원을 제거합니다. 자세한 내용은 BinaryFormatter serialization 메서드가 사용되지 않음을 참조하세요.

  • <EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>

    안전하지 않은 UTF-7 인코딩 코드를 제거합니다. 자세한 내용은 UTF-7 코드 경로가 사용되지 않음을 참조하세요.

  • <EventSourceSupport>false</EventSourceSupport>

    EventSource 관련 코드 또는 논리를 제거합니다.

  • <HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>

    System.Net.Http의 진단 지원과 관련된 코드를 제거합니다.

  • <InvariantGlobalization>true</InvariantGlobalization>

    세계화 관련 코드 및 데이터를 제거합니다. 자세한 내용은 고정 모드를 참조하세요.

  • <MetadataUpdaterSupport>false</MetadataUpdaterSupport>

    핫 다시 로드와 관련된 메타데이터 업데이트 관련 논리를 제거합니다.

  • <StackTraceSupport>false</StackTraceSupport>(.NET 8+)

    런타임에 의한 스택 추적 생성(예: Environment.StackTrace 또는 Exception.ToString)에 대한 지원을 제거합니다. 스택 추적 문자열에서 제거되는 정보의 양은 다른 배포 옵션에 따라 달라질 수 있습니다. 이 옵션은 디버거에서 생성된 스택 추적에 영향을 주지 않습니다.

  • <UseNativeHttpHandler>true</UseNativeHttpHandler>

    Android/iOS용 HttpMessageHandler의 기본 플랫폼 구현을 사용하고 관리형 구현을 제거합니다.

  • <UseSystemResourceKeys>true</UseSystemResourceKeys>

    System.* 어셈블리에 대한 예외 메시지를 제거합니다. System.* 어셈블리에서 예외가 throw되면 메시지는 전체 메시지가 아니라 단순화된 리소스 ID입니다.

해당 속성은 관련 코드가 트리밍되도록 하며 runtimeconfig 파일을 통해 기능도 사용하지 않도록 설정합니다. 해당 runtimeconfig 옵션을 포함하여 이러한 속성에 대한 자세한 내용은 기능 스위치를 참조하세요. 일부 SDK에는 해당 속성의 기본값이 있을 수 있습니다.

트리밍할 때 사용할 수 없는 프레임워크 기능

다음 기능은 정적으로 참조되지 않는 코드가 필요하기 때문에 트리밍과 호환되지 않습니다. 따라서 트리밍된 앱에서는 기본적으로 사용하지 않도록 설정됩니다.

Warning

이러한 기능을 사용하도록 설정할 때는 주의해야 합니다. 동적으로 참조된 코드를 유지하기 위해 트리밍된 앱을 추가 작업 없이 중단할 수 있기 때문입니다.

  • <BuiltInComInteropSupport>

    기본 제공 COM 지원을 사용할 수 없습니다.

  • <CustomResourceTypesSupport>

    사용자 지정 리소스 종류를 사용할 수 없습니다. 사용자 지정 리소스 종류에 리플렉션을 사용하는 ResourceManager 코드 경로가 트리밍됩니다.

  • <EnableCppCLIHostActivation>

    C++/CLI 호스트 활성화를 사용할 수 없습니다.

  • <EnableUnsafeBinaryFormatterInDesigntimeLicenseContextSerialization>

    BinaryFormatter serialization의 DesigntimeLicenseContextSerializer 사용은 불가능합니다.

  • <StartupHookSupport>

    DOTNET_STARTUP_HOOKS를 사용하여 Main보다 먼저 코드를 실행할 수 없습니다. 자세한 내용은 host startup hook(호스트 시작 후크)를 참조하세요.