Version: Unity 6.0 (6000.0)
언어 : 한국어
관리되는 코드 스트리핑
Configure managed code stripping

Unity linker

Unity 빌드 프로세스는 Unity linker라는 툴을 사용하여 관리되는 코드를 스트리핑합니다. Unity linker는 Unity와 함께 사용할 수 있도록 커스터마이즈된 IL Linker 버전입니다. Unity linker의 커스텀 Unity 엔진별 부분은 공개적으로 제공되지 않습니다.

Unity linker는 관리되는 코드 스트리핑과 엔진 코드 스트리핑 프로세스의 일부를 담당하며 이는 미사용 엔진 코드를 제거하는__ IL2CPP__Unity에서 개발한 스크립팅 백엔드로, 여러 플랫폼용 프로젝트를 빌드할 때 Mono 대신 사용할 수 있습니다. 자세한 정보
See in Glossary
스크립트 백엔드를 통해 사용할 수 있는 별도의 프로세스입니다. 자세한 내용은 PlayerSettings.StripEngineCode를 참조하십시오.

Unity linker 동작 방식

Unity linker는 프로젝트의 모든 어셈블리를 분석합니다. 먼저 루트 유형, 메서드, 프로퍼티, 필드를 마킹합니다. 예를 들어 씬의 게임 오브젝트에 추가하는 MonoBehaviour 파생 클래스는 루트 유형입니다. \

그러면 Unity linker는 식별할 루트를 분석하고 이러한 루트가 종속되는 관리되는 코드를 마킹합니다. 정적 분석이 완료되면 애플리케이션 코드를 통한 모든 실행 경로에서 마킹되지 않은 남은 코드에 도달할 수 없으며 Unity linker는 해당 코드를 어셈블리에서 삭제합니다.

Unity linker가 어셈블리를 스트리핑하는 방법

Unity 에디터는 Unity 프로젝트의 씬에서 사용되는 유형을 포함하는 어셈블리의 리스트를 생성하고 이 리스트를 Unity linker에 전달합니다. 그런 다음 Unity linker는 해당 어셈블리, 해당 어셈블리의 레퍼런스, link.xml 파일에서 선언된 어셈블리, AlwaysLinkAssembly 속성이 있는 어셈블리를 처리합니다. 일반적으로 Unity linker는 이러한 카테고리 중 하나에 속하지 않는 프로젝트에 포함된 어셈블리를 처리하지 않으며 플레이어 빌드에서 제외합니다.

Unity linker가 어셈블리를 처리할 때마다 어셈블리 분류, 어셈블리가 씬에서 사용되는 유형을 포함하는지 여부, 해당 빌드에 대해 선택한 관리되되는 스트리핑 레벨에 따라 일련의 규칙을 준수합니다.

이러한 규칙에서 어셈블리는 다음과 같이 분류됩니다.

  • .NET Class Library 어셈블리 — mscorlib.dll 및 System.dll 같은 Mono 클래스 라이브러리 및 netstandard.dll 같은 .NET 클래스 라이브러리 파사드 어셈블리를 모두 포함합니다.
  • Platform SDK 어셈블리 — 플랫폼 SDK 전용의 관리되는 어셈블리를 포함합니다. 예를 들어 유니버설 Windows 플랫폼 SDK의 일부인 windows.winmd 어셈블리입니다.
  • Unity Engine Module 어셈블리 — UnityEngine.Core.dll 등 Unity 엔진을 구성하는 관리되는 어셈블리를 포함합니다.
  • Project 어셈블리 — 프로젝트 어셈블리를 포함합니다. 예:

마킹 규칙

Unity에서 프로젝트를 빌드할 때 빌드 프로세스는 C# 코드를 CIL(일반 중간 언어)이라는 .NET 바이트코드 포맷으로 컴파일합니다. Unity는 이 CIL 바이트 코드를 어셈블리라는 파일로 패키징합니다. 프로젝트에서 사용하는 플러그인의 .NET 프레임워크 라이브러리와 C# 라이브러리는 CIL 바이트코드의 어셈블리로 사전 패키징됩니다.

Unity linker는 정적 분석을 수행할 때 일련의 규칙을 따라 Unity linker가 빌드에 필요하다고 표시하는 CIL 바이트코드의 일부를 결정합니다. 루트 마킹 규칙에는 Unity linker가 빌드의 최상위 레벨 어셈블리를 식별하고 보존하는 방식을 결정합니다. 종속성 마킹 규칙에는 Unity linker가 루트 어셈블리가 의존하는 모든 코드를 식별하고 보존하는 방식을 결정합니다.

Managed Stripping Level 프로퍼티는 Unity linker가 사용하는 규칙 세트를 변경합니다. 다음 섹션에서는 Managed Stripping Level 프로퍼티에 대해 가능한 각 설정에 대한 마킹 규칙을 설명합니다.

루트 마킹 규칙

다음 표에서는 Unity linker가 어셈블리의 상위 레벨 유형을 식별하는 방식을 설명합니다.

|어셈블리 유형:||||마킹 규칙:| | :— | :— | :— | :— | :— | | | 최소 | 낮음 | 중간 | 높음 | |.NET 클래스 & 플랫폼 SDK 및 UnityEngine 어셈블리| 예방적 보존과 모든 link.xml에 정의된 모든 보존을 적용합니다. | 예방적 보존과 모든 link.xml에 정의된 모든 보존을 적용합니다. | 모든 link.xml 파일에 정의된 모든 보존을 적용합니다. | 모든 link.xml 파일에 정의된 모든 보존을 적용합니다. | |씬에서 참조된 유형을 포함한 어셈블리| 어셈블리의 모든 유형과 멤버 마킹. | 어셈블리의 모든 유형과 멤버 마킹. | 다음을 마킹합니다.
[RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성이 있는 모든 메서드
• 모든 link.xml에 정의된 보존
• 사전 컴파일된 어셈블리, 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour 및 스크립터블 오브젝트에서 파생된 모든 유형을 마킹합니다. | 다음을 마킹합니다.
[RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성이 있는 모든 메서드
• 모든 link.xml에 정의된 보존
• 사전 컴파일된 어셈블리, 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour 및 스크립터블 오브젝트에서 파생된 모든 유형을 마킹합니다. | |기타| 어셈블리의 모든 유형과 멤버 마킹. | 다음을 마킹합니다.
• 모든 공용 유형과 해당 유형의 공용 멤버
[RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성이 있는 모든 메서드
• 모든 link.xml에 정의된 보존
• 사전 컴파일된 어셈블리, 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour 및 스크립터블 오브젝트에서 파생된 모든 유형 | 다음을 마킹합니다.
• 모든 공용 유형과 해당 유형의 공용 멤버
[RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성이 있는 모든 메서드
• 모든 link.xml에 정의된 보존
• 사전 컴파일된 어셈블리, 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour 및 스크립터블 오브젝트에서 파생된 모든 유형 | 다음을 마킹합니다.
[RuntimeInitializeOnLoadMethod] 또는 [Preserve] 속성이 있는 모든 메서드
• 모든 link.xml에 정의된 보존
• 사전 컴파일된 어셈블리, 패키지, Unity 스크립트 또는 어셈블리 정의 어셈블리의 MonoBehaviour 및 스크립터블 오브젝트에서 파생된 모든 유형 | |테스트| [UnityTest] 속성이 있는 모든 메서드와 NUnit.Framework에서 정의한 속성으로 표시된 모든 메서드를 마킹합니다. |||||

종속성 마킹 규칙

Unity linker는 어셈블리의 루트를 식별한 후 해당 루트가 의존하는 코드를 식별해야 합니다. 다음 표에서는 Unity linker가 어셈블리의 루트 유형 종속성을 식별하는 방식을 설명합니다.

|규칙 타겟||||각 스트리핑 레벨의 행동| | :— | :— | :— | :— | :— | | | 최소 | 낮음 | 중간 | 높음 | |MonoBehaviour| Unity linker는 유형을 마킹할 때 MonoBehaviour 유형의 모든 멤버를 마킹합니다. |||| |스크립터블 오브젝트| Unity linker는 유형을 마킹할 때 스크립터블 오브젝트 유형의 모든 멤버를 마킹합니다. |||| |속성| Unity linker가 어셈블리, 유형이나 다른 코드 구조체를 마킹할 때 Unity linker는 또한 해당 구조체의 모든 속성을 마킹합니다. | Unity linker가 어셈블리, 유형이나 다른 코드 구조체를 마킹할 때 Unity linker는 또한 해당 구조체의 모든 속성을 마킹합니다. | Unity linker가 어셈블리, 유형이나 다른 코드 구조체를 마킹할 때 속성 유형도 마킹되는 경우 Unity linker는 해당 구조체의 속성만 마킹합니다. | Unity linker가 어셈블리, 유형이나 다른 코드 구조체를 마킹할 때 속성 유형도 마킹되는 경우 Unity linker는 해당 구조체의 속성만 마킹합니다. | |디버깅 속성| 스크립트 디버깅을 활성화하면 Unity linker는 해당 멤버를 사용하는 코드 경로가 없어도 [DebuggerDisplay] 속성이 있는 모든 멤버를 마킹합니다. | 스크립트 디버깅을 활성화하면 Unity linker는 해당 멤버를 사용하는 코드 경로가 없어도 [DebuggerDisplay] 속성이 있는 모든 멤버를 마킹합니다. | Unity linker는 DebuggerDisplayAttribute 및 DebuggerTypeProxyAttribute 같은 디버깅 속성을 항상 제거합니다. | Unity linker는 DebuggerDisplayAttribute 및 DebuggerTypeProxyAttribute 같은 디버깅 속성을 항상 제거합니다. | |.NET 파사드 클래스 라이브러리| 파사드 어셈블리는 런타임 시 필요하지 않기 때문에 제거합니다. |||||

Link XML 기능 태그 제외

Link.xml 파일은 자주 사용되지 않는 ‘기능’ XML 속성을 지원합니다. 예시에서 mscorlib.dll에 내장된 mscorlib.xml 파일은 이 속성을 사용하지만, 필요한 경우 모든 link.xml 파일에서 사용할 수 있습니다.

High 스트리핑 레벨을 사용할 때 Unity linker는 현재 빌드에 대한 설정을 기준으로 지원되지 않는 기능의 보존을 제외합니다.

  1. remoting — IL2CPP 스크립팅 백엔드를 타겟팅하는 경우 제외됩니다.
  2. sre — IL2CPP 스크립팅 백엔드를 타겟팅하는 경우 제외됩니다.
  3. com — COM을 지원하지 않는 플랫폼을 타겟팅하는 경우 제외됩니다.

예를 들어 다음의 link.xml 파일은 COM을 지원하는 플랫폼에 포함된 유형의 메서드 1가지 및 모든 플랫폼의 메서드 1가지를 지원합니다.

<linker>

    <assembly fullname="Foo">

        <type fullname="Type1">

            <!--Preserve FeatureOne on platforms that support COM-->

            <method signature="System.Void FeatureOne()" feature="com"/>

            <!--Preserve FeatureTwo on all platforms-->

            <method signature="System.Void FeatureTwo()"/>

        </type>

    </assembly>

</linker>

메서드 바디 편집

High 스트리핑 레벨을 사용하면 Unity linker는 코드 크기를 더 줄이기 위해 메서드 바디를 편집합니다. 이 섹션에서는 Unity linker가 메서드 바디에 적용한 주요 수정 사항을 요약합니다.

Unity linker는 .NET Class Library 어셈블리의 메서드 바디만 편집합니다. 메서드 바디 편집 후에는 어셈블리의 소스 코드가 더 이상 어셈블리의 컴파일된 코드와 일치하지 않으므로 디버깅이 더 어려워질 수 있습니다.

다음 리스트에서는 Unity linker가 메서드 바디를 편집하기 위해 수행할 수 있는 행동을 설명합니다.

  • 도달할 수 없는 브랜치 제거 - Unity linker는 System.Environment.OSVersion.Platform을 확인하고 현재 타겟인 플랫폼에 도달할 수 없는 If문 블록을 제거합니다.
  • 필드에만 액세스하는 인라인 메서드 - Unity linker는 필드를 가져오거나 설정하는 메서드에 대한 호출을 필드에 대한 직접 액세스로 대체합니다. 이렇게 하면 종종 메서드를 완전히 제거할 수 있습니다. Mono 백엔드를 사용하는 경우 Unity linker는 필드 가시성에 따라 메서드의 호출자가 필드에 직접 액세스할 수 있도록 허용된 경우에만 이 변경을 수행합니다. IL2CPP의 경우 가시성 규칙이 적용되지 않으므로 Unity linker는 적절한 경우 이 변경을 수행합니다.
  • const 값을 반환하는 인라인 메서드 - const 값만 반환하는 메서드 호출을 인라이닝합니다.
  • 비어 있는 비 반환 호출 제거 - Unity linker는 비어 있고 유효한 반환 유형이 있는 메서드에 대한 호출을 제거합니다.
  • 비어 있는 범위 제거 - Finally 블록이 비어 있을 때 Unity linker가 Try/Finally 블록을 제거합니다. 빈 호출을 제거하면 빈 Finally 블록이 생성될 수 있습니다. 메서드 편집 중에 발생하면 Unity linker가 Try/Finally 블록 전체를 제거합니다. 이러한 일은 컴파일러가 Dispose()를 호출하기 위해 Foreach 루프의 일부로 Try/Finally 블록을 생성하는 경우에 발생할 수 있습니다.

추가 리소스

관리되는 코드 스트리핑
Configure managed code stripping