IL2CPP(C++로 변환하기 위한 중간 언어) 스크립팅 백엔드는 Mono 백엔드의 대안입니다. IL2CPP는 더욱 다양한 플랫폼에서 애플리케이션에 대해 더 나은 지원을 제공합니다. IL2CPP 백엔드는 MSIL(Microsoft 중간 언어) 코드(예: 스크립트 내의 C# 코드)를 C++ 코드로 전환한 뒤 C++ 코드를 사용하여 선택한 플랫폼에 대한 네이티브 바이너리 파일(예: .exe, .apk, .xap)을 생성합니다.
Unity가 네이티브 바이너리를 빌드할 때 특히 타겟 플랫폼에 대해 코드를 컴파일하는 이런 유형의 컴파일을 AOT(Ahead-Of-Time) 컴파일이라고 부릅니다. Mono 백엔드는 JIT(just-in-time) 컴파일이라는 기법을 통해 런타임 시 코드를 컴파일합니다.
이 페이지에서는 다음의 내용을 다룹니다.
일부 플랫폼은 AOT 컴파일을 지원하지 않으므로__ IL2CPP__ 백엔드는 모든 플랫폼에서 작동하지는 않습니다. 다른 플랫폼은 AOT 및 IL2CPP를 지원하지만 JIT 컴파일을 허용하지 않으므로 Mono 백엔드를 지원할 수 없습니다. 플랫폼이 두 백엔드를 모두 지원할 수 있는 경우 Mono가 기본값입니다. 자세한 내용은 스크립팅 제한 사항을 참조하십시오.
IL2CPP는 다양한 플랫폼에서 성능을 향상시킬 수 있지만, 빌드된 애플리케이션에 기계어 코드를 포함해야 하기 때문에 빌드 시간과 최종 빌드된 애플리케이션의 크기가 모두 증가합니다. 자세한 내용은 IL2CPP 작동 방식과 블로그에서 시리즈로 다룬 IL2CPP 원리 소개를 참조하십시오.
IL2CPP는 Mono 스크립팅 백엔드와 동일한 방식으로 관리되는 코드의 디버깅을 지원합니다. 자세한 내용은 Unity에서 C# 코드 디버깅을 참조하십시오.
IL2CPP를 사용하여 프로젝트를 빌드하려면 Unity 설치에 백엔드를 설치해야 합니다. Unity 버전을 처음 설치할 경우, 선택적 모듈로 IL2CPP를 선택하거나 Unity Hub를 통해 기존 설치에 IL2CPP 지원을 추가할 수 있습니다. 자세한 내용은 Unity Hub 설치 및 Unity 에디터에 모듈 추가를 참조하십시오.
또한 IL2CPP로 C++ 코드를 생성하려면 타겟 플랫폼의 특정한 시스템 환경이 필요합니다. 즉 특정 플랫폼에서 IL2CPP를 사용하려면 해당 플랫폼에서 애플리케이션을 빌드해야 한다는 뜻입니다. 예를 들어 IL2CPP를 사용할 때 MacOS를 빌드 타겟으로 하려면 MacOS를 사용하는 컴퓨터에서 애플리케이션을 빌드해야 합니다. 개별 플랫폼에 대한 IL2CPP 요구 사항을 포함하는 데스크톱 플랫폼에 대한 상세 시스템 요구 사항은 Unity용 시스템 요구 사항의 데스크톱 섹션을 참조하십시오.
Unity가 사용하는 스크립팅 백엔드를 변경하여 다음 두 가지 방법 중 하나로 애플리케이션을 빌드할 수 있습니다.
에디터의 Player Settings 메뉴를 사용하는 방법입니다. Player Settings 메뉴를 통해 스크립팅 백엔드를 변경하려면 다음 단계를 수행해야 합니다.
Build Profiles 창에서 Player Settings 메뉴를 열 수도 있습니다. File > Build Profiles로 이동하여 Player Settings 탭을 클릭하면 됩니다.
에디터 스크립팅 API를 사용하는 방법입니다. PlayerSettings.SetSkriptingBackend 프로퍼티를 사용하여 Unity가 사용하는 스크립팅 백엔드를 변경합니다.
빌드 프로세스를 시작하려면 Build Profiles 창을 열고 Build 버튼을 클릭합니다. 그러면 Unity는 C# 코드와 어셈블리를 C++로 전환한 후 마지막으로 타겟 플랫폼에 바이너리 파일을 생성합니다.
IL2CPP를 사용하여 빌드를 시작하면 Unity는 자동으로 다음의 단계를 수행합니다.
IL2CPP와 Mono 모두 스크립트의 속성을 통해 제어할 수 있는 몇 가지 유용한 옵션을 제공합니다. 자세한 내용은 플랫폼에 따른 컴파일을 참조하십시오.
Unity는 IL2CPP를 사용하여 특정 플랫폼에 대한 코드를 사전에 컴파일할 수 있습니다. 이 프로세스가 끝날 때 Unity가 생성하는 바이너리 파일에는 타겟 플랫폼용 필수 기계어 코드가 이미 포함되어 있으나, Mono는 실행 중 런타임 시에 이 기계어 코드를 컴파일해야 합니다. AOT 컴파일은 빌드 시간을 늘리지만, 타겟 플랫폼과의 호환성을 높이고 성능을 개선할 수 있습니다.
두 스크립팅 백엔드에는 타게팅하려는 각 플랫폼에 대한 새로운 빌드가 필요합니다. 예를 들어 Android와 iOS 플랫폼 둘 다를 지원하려면 애플리케이션을 두 번 빌드하고 바이너리 파일도 두 개 생성해야 합니다.
어셈블리 스트리핑 단계는 최종 바이너리 크기를 줄이는 데 도움이 됩니다. Unity는 최종 빌드된 애플리케이션이 사용하지 않는 바이트코드를 제거합니다.
IL2CPP를 사용할 때 프로젝트 빌드 시간은 Mono를 사용할 때보다 훨씬 길어질 수 있습니다. 하지만 몇 가지 방법을 사용해 빌드 시간을 단축할 수 있습니다.
멀웨어 차단 소프트웨어 검사에서 프로젝트 제외
프로젝트를 빌드하기 전에 멀웨어 차단 소프트웨어 검사에서 Unity 프로젝트 폴더와 타겟 빌드 폴더를 제외할 수 있습니다.
SSD(Solid State Drive)에 프로젝트와 타겟 빌드 폴더 저장
SSD(솔리드 스테이트 드라이브)는 기존 HDD(하드 디스크 드라이브)에 비해 읽기/쓰기 속도가 빠릅니다. IL 코드를 C++로 전환하고 컴파일하려면 수많은 읽기/쓰기 작업이 필요하기 때문에 저장 장치가 빠를수록 처리 속도도 빨라집니다.
Player 설정에서 IL2CPP 코드 생성 옵션 변경
IL2CPP가 코드를 생성하는 방법을 변경하려면 Player Settings를 열어 IL2CPP 코드 생성 옵션을 설정합니다. 기본적으로 Faster runtime 옵션이 활성화되며 이는 런타임 시 IL2CPP의 영향을 줄여주는 기계어 코드를 더 많이 생성합니다. 빌드 시간을 줄이려면 이 옵션을 Faster (smaller) builds로 설정하면 됩니다. 이 메서드는 바이너리 실행 파일에 기계어 코드를 더 적게 생성하고 포함하므로 런타임 시 성능이 저하될 수 있지만, 빌드 시간과 바이너리 크기를 크게 줄여줍니다.
IL2CPP 스크립팅 백엔드를 사용하면 il2cpp.exe가 C++ 코드를 생성하는 방식을 제어할 수 있습니다. Il2CppSetOption 속성을 사용하여 다음 런타임 체크를 활성화하거나 비활성화할 수 있습니다.
| 프로퍼티: | 설명: | 기본값: |
|---|---|---|
| Null checks | 이 옵션을 활성화하면 IL2CPP가 생성하는 C++ 코드가 null 체크가 포함되며 필요한 경우 관리되는 NullReferenceException 예외가 발생합니다. 이 옵션을 비활성화하면 IL2CPP는 생성된 C++ 코드에 null 체크를 내보내지 않습니다. 일부 프로젝트에서는 이 옵션을 비활성화하면 런타임 성능이 향상될 수도 있습니다. 이 설정을 비활성화하면 Unity는 생성된 코드의 null 값에 액세스하려는 시도를 방지하지 않으므로 잘못된 동작이 발생할 수 있습니다. 애플리케이션이 null 값을 역참조하면 곧바로 충돌이 발생할 수 있습니다. Unity에서는 이 옵션을 비활성화하지 않는 것이 좋습니다. |
활성화 |
| Array bounds checks | 이 옵션을 활성화하면 IL2CPP가 생성하는 C++ 코드에 배열 바운드 체크가 포함되며 필요한 경우 관리되는 IndexOutOfRangeException 예외가 발생합니다. 이 옵션을 비활성화하면 IL2CPP는 생성된 C++ 코드에 배열 바운드 체크를 내보내지 않습니다. 일부 프로젝트에서는 이 옵션을 비활성화하면 런타임 성능이 향상될 수도 있습니다. 하지만 이 옵션을 비활성화하면 Unity는 생성된 코드의 유효하지 않은 인덱스를 가진 배열에 액세스하려는 시도를 차단하지 않으므로 임의의 메모리 위치에서 읽거나 쓰는 등의 잘못된 동작을 일으킬 수 있습니다. 대부분의 경우 이러한 메모리 액세스가 발생하더라도 즉각적인 부작용이 나타나지 않을 수 있으며 명확한 경고도 없이 애플리케이션의 상태를 손상시킬 수 있습니다. 이 경우 오류 디버깅이 매우 어려워질 수 있습니다. Unity에서는 이 옵션을 활성화 상태로 유지하는 것이 좋습니다. |
활성화 |
| Divide by zero checks | 이 옵션을 활성화하면 IL2CPP가 생성하는 C++ 코드에는 정수 나눗셈에 대한 0으로 나누기 체크가 포함되며 필요에 따라 관리되는 DivideByZeroException 예외를 발생시킵니다. 이 옵션을 비활성화하면 IL2CPP는 생성된 C++ 코드의 정수 나눗셈에 대하여 0으로 나누기 체크를 포함시키지 않습니다. 이러한 체크는 런타임 시 성능에 영향을 미칩니다. 이 옵션은 0으로 나누기 체크를 실행해야 하는 경우에만 활성화해야 하며 그 외의 경우에는 비활성화 상태로 둬야 합니다. |
Disabled |
Il2CppSetOption 속성을 사용하는 방법은 다음과 같습니다.
Il2CppSetOption 속성을 사용하는 방법은 아래의 예제에 설명되어 있습니다.
[Il2CppSetOption(Option.NullChecks, false)]
public static string MethodWithNullChecksDisabled()
{
var tmp = new object();
return tmp.ToString();
}
어셈블리, 유형, 메서드, 프로퍼티에 Il2CppSetOption 속성을 적용할 수 있습니다. Unity는 가장 로컬 범위의 속성을 사용합니다.
[Il2CppSetOption(Option.NullChecks, false)]
public class TypeWithNullChecksDisabled
{
public static string AnyMethod()
{
// Unity doesn’t perform null checks in this method.
var tmp = new object();
return tmp.ToString();
}
[Il2CppSetOption(Option.NullChecks, true)]
public static string MethodWithNullChecksEnabled()
{
// Unity performs null checks in this method.
var tmp = new object();
return tmp.ToString();
}
}
public class SomeType
{
[Il2CppSetOption(Option.NullChecks, false)]
public string PropertyWithNullChecksDisabled
{
get
{
// Unity doesn’t perform null checks here.
var tmp = new object();
return tmp.ToString();
}
set
{
// Unity doesn’t perform null checks here.
value.ToString();
}
}
public string PropertyWithNullChecksDisabledOnGetterOnly
{
[Il2CppSetOption(Option.NullChecks, false)]
get
{
// Unity doesn’t perform null checks here.
var tmp = new object();
return tmp.ToString();
}
set
{
// Unity performs null checks here.
value.ToString();
}
}
}