Unity 검색

Colorful CPU card
Colorful CPU card
공유

Is this article helpful for you?

Thank you for your feedback!

유니티는 최근 여러 해 동안 단계적으로 완성될 이니셔티브를 시작하여 크리에이터가 성능이 좋은 코드를 빠르게 작성하고 장기적인 안정성과 호환성을 제공할 수 있도록 지원하고 있습니다. 이번 포스팅에서는 스크립트를 뒷받침하는 기초적인 기술 스택을 업데이트하기 위해 유니티가 하고 있는 일들을 알아봅니다.

.NET 생태계는 다양한 방면으로 계속 진화를 거듭하고 있으며, 유니티는 새로운 개선 사항을 최대한 신속하게 전달하고자 노력하고 있습니다. 유니티 내부의 .NET Tech Group에서는 .NET 통합을 지속적으로 개선하고 있으며, 여기에는 최신 C# 기능 및 .NET Standard 2.1도 포함됩니다. 최근에는 사용자 피드백을 바탕으로 전체적인 개발자 경험을 대폭 개선하고 있습니다. 

이번 블로그 포스팅에서는 유니티가 현재 개발 중인 기능을 소개합니다. GDC 2022의 Unity 개발자 서밋(Unity Dev Summit)에서도 이 주제에 대해 논의한 바 있습니다. 여기에서 전체 세션을 보실 수 있습니다.

이 콘텐츠는 Targeting Cookies 카테고리를 수락해야만 동영상을 시청할 수 있도록 허용하는 타사 제공업체에서 호스팅합니다. 이러한 제공업체의 비디오를 보려면 쿠키 환경 설정에서 Targeting Cookies 카테고리를 수락하시기 바랍니다.

.NET과 Unity의 진화

이 이야기는 지금으로부터 17년 전, 유니티의 CTO가 C#과 Mono .NET 런타임을 동시에 활용하면서 시작됩니다. 유니티는 C# 코드를 상대적으로 효율성 높은 네이티브 코드로 변환하는 JIT(Just-In-Time) 컴파일러와 언어의 간결한 매력 때문에 C#을 선호했습니다. Unity 엔진에서 훨씬 더 큰 비중을 차지하는 나머지 부분은 성능의 적절한 균형과 제어를 위해 C++를 사용하여 개발되었습니다.

수년간 Unity는 Mono .NET 런타임 및 C# 언어(2.0)를 기반으로 실행되었고, 그 기간 동안 다른 플랫폼에 대한 지원도 추가되었습니다. 유니티는 iOS 및 일부 콘솔 플랫폼을 타겟팅할 수 있도록 자체 컴파일러이자 런타임인 IL2CPP도 개발했습니다.

그동안 전체 Microsoft .NET 생태계도 진화하여 새로운 라이선싱과 비 Windows 플랫폼 지원이 생겼습니다. 이러한 진화 덕분에 유니티는 2018년에 Unity .NET Mono 런타임을 업그레이드하고 더 현대적인 C# 언어 버전(7.0+)을 도입할 수 있었습니다. 같은 해에 Burst 컴파일러의 최초 버전도 릴리스하여 일부 C# 언어로 최적화된 네이티브 코드를 생성할 수 있게 되었습니다. 유니티는 당시 획기적인 발전을 거듭하며 C++가 아닌 C#을 사용하여 엔진의 다른 주요 기능을 개발할 수 있다는 가능성을 보게 되었고, 이는 DOTS 런타임 개발로 이어졌습니다.

Unity 2020 LTS와 Unity 2021 LTS에서는 새로운 버전의 C#과 .NET API(예: Span<T>)가 사용되었습니다. 이와 동시에 .NET 생태계에서는 엄청난 성능 개선이 이루어졌고, SDK 스타일의 csproj의 도입과 NuGet 생태계의 성장을 통해 보다 친근한 개발 환경이 구축되었습니다.

크리에이터 피드백

Unity 플랫폼은 오랜 진화의 결과로 Mono .NET 런타임에서 상속한 구체적 가정을 사용하여 .NET 오브젝트와 직접 상호 작용하는 대규모 C++ 코드베이스를 포함하게 되었습니다. 이는 .NET (Core) 런타임에는 더 이상 유효하지 않으며 효율이 떨어집니다. 

또한 Unity 에디터와 함께 사용하는 복잡한 컴파일 파이프라인은 MSBuild를 사용하지 않기 때문에 제공되는 모든 기본 기능을 활용할 수 없게 됩니다.

유니티는 지난 몇 년간 인터뷰와 Unity 포럼을 통해 많은 크리에이터와 소통하며 성공적인 게임을 개발하는 데 있어 어떤 측면을 개선할 수 있을지 파악했습니다. 그 결과 최신 C# 언어, .NET 런타임 기술, NuGet의 타사 C# 코드를 사용하고 싶다는 피드백을 받았습니다. Unity 플랫폼 사용에 관해서는 고품질 C# 테스트, 디버깅, 프로파일링 툴, 그리고 기본 .NET API와 Unity API 간의 적절한 통합을 통해 타겟 하드웨어를 최대한 활용하고 싶다는 의견이 많았습니다. C# Unity 프로그래머들은 업계 최고의 런타임 성능을 달성할 수 있도록 다른 툴박스와 원활히 연동되어 빠른 반복을 실현하는 Unity 툴을 원합니다.

이러한 요청을 모두 현실화하려면 수 년이 걸릴 것으로 예상합니다. 유니티는 개발 과정에서 직면하는 기술적인 문제에 관해 블로그와 포럼을 수시로 업데이트하여 상황을 계속 공유할 예정입니다.

.NET 이니셔티브

이번 이니셔티브의 첫 단계에서는 C# 및 .NET에 열의를 가진 내부 직원을 모두 한 데 모아 C#/.NET Tech Group을 구성하였습니다. 

커스텀 솔루션이 아닌 .NET 생태계를 기반으로 빌드하고자 했으며, 최신 .NET SDK/Runtime 및 MSBuild의 성능과 생산성 개선을 활용할 수 있도록 Mono .NET 런타임에서 현대적인 .NET (Core) 런타임인 CoreCLR로 마이그레이션할 계획을 세웠습니다.

또한 이 이니셔티브는 C# 스크립트에서 더 빠른 .NET 반복 작업이 가능하도록 기존의 .NET 생태계를 넘어서는 혁신을 제공합니다. 유니티는 JIT 및 AOT(Ahead-Of-Time) 솔루션, 즉 IL2CPP 및 Burst의 융합을 통해 컴파일 소요 시간과 코드 생성 품질 간에 최적의 균형을 제공하려고 합니다. 

외부적으로는 Unity 크리에이터가 최신 .NET 기술을 사용할 수 있도록 Microsoft, JetBrains 등의 업계 파트너와 협력하면서 오픈 소스 커뮤니티에서도 참여도를 높일 예정입니다. 이 모든 활동은 여러 세분화된 단계로 진행됩니다. 그럼 향후 계획을 살펴보겠습니다.

2022년 유니티의 계획

유니티 팀은 올해에 다음 사항에 집중할 예정입니다.

An infographic of the pillars of Unity Developer Experience

C# 개발 워크플로

최대한 시간을 활용할 수 있도록 반복 작업 시간 단축을 여전히 최고 우선 순위로 고려합니다. 다음은 반복 작업 시간을 개선하기 위한 방안의 일부입니다.

  • 컴파일 파이프라인에서 C# 컴파일 후에 컴파일된 .NET 어셈블리의 수정을 담당하는 IL Post Processing에 의해 소모되는 시간을 개선하고 있습니다. 이제 컴파일 단계 이후 영속적인 프로세스를 사용하여 IL Post Processing을 실행하며 이를 통해 수백 밀리초를 단축할 수 있습니다.
  • Burst 컴파일러가 더 빈번하게 사용되고 있으므로 추이적 해싱(transitive hashing) 알고리즘을 사용하여 코드 변경을 더 세밀하게 검출할 수 있도록 개선하고 있습니다. 이에 따라 컴파일이 필요한 버스트 가능 코드를 더 빨리 식별할 수 있습니다. 유니티는 Burst 컴파일러가 프로세스를 벗어나 별도 .NET 6.0 실행 파일에서 실행됨으로써 코드를 더 빠르게 컴파일할 수 있도록 하고 있습니다.
  • 또한 TypeCache가 사용될 때마다 백그라운드에서 빌드되는 반사 데이터를 개선하여 도메인 리로드의 기능을 향상하고 있습니다.
  • 패키지 및 프로젝트 템플릿의 반복 작업 시간을 더 면밀히 추적하기 위해 테스트와 검증이 추가됩니다.

MSBuild로 마이그레이션하기 위한 첫 단계는 Unity 에디터에서 컴파일 파이프라인을 분리하여 별도 프로세스로 옮기는 것이었습니다. 몇 년간 축적된 수천 줄의 C++, C# 레거시 코드를 분리해내는 동시에 하위 호환성도 유지해야 하기 때문에 이는 복잡한 작업입니다. 외부적인 변화는 없지만 이 작업을 통해 MSBuild로 이전하기 위한 기반을 마련하고 유지 관리를 간소화할 수 있습니다.

또한 Burst에서 C# IDE 디버깅 경험도 개선할 예정입니다. Burst를 통해 실행되는 코드 경로에 중단점이 설정되어 있을 때 디버거가 관리되는 디버깅으로 자동 전환하는 모드가 도입됩니다. 이렇게 하면 디버깅되는 코드 경로에서 [BurstCompile] 속성을 수동으로 제거하지 않아도 됩니다.

.NET 런타임 현대화

.NET CoreCLR 런타임으로 마이그레이션하기 위한 작업은 이미 시작되었으며 이는 아주 까다로운 과제입니다. 이 마이그레이션을 완수하기 위해 유니티는 문제를 점진적으로 해결하면서 기존 Unity 프로젝트의 안정성을 유지하는 방향으로 결과물을 전달하려 합니다.

다음과 같이 여러 단계로 이 마이그레이션을 완수할 계획입니다.

  • 첫 단계에서는 데스크톱 플랫폼의 스탠드얼론 플레이어를 위한 .NET CoreCLR 지원을 제공합니다. 크리에이터는 기존 Mono 및 IL2CPP 백엔드와 함께 플레이어 설정에서 이 런타임을 선택할 수 있게 됩니다. 이 단계를 통해 에디터 부분보다 훨씬 더 작은 규모인 Unity 엔진의 핵심 부분을 마이그레이션할 수 있으며, 마이그레이션에 수반되는 여러 가지 기술적인 문제도 해결할 수 있기를 바랍니다. 이전과 마찬가지로 .NET Standard 2.1 API를 통해 .NET 런타임에 액세스할 수 있으며, 유니티는 2023년 중으로 새로운 런타임을 릴리스하는 것을 목표로 하고 있습니다.  
  • 두 번째 단계는 Unity 에디터를 .NET CoreCLR로 포팅하는 동시에 .NET Mono 런타임에 대한 지원을 중단합니다. 이 단계에서는 AppDomains를 사용하지 않고 에디터에서 스크립트를 리로드하고 .NET CoreCLR로의 전환을 완료할 수 있는지가 관건입니다. dotnet/runtime 저장소에서 기본 클래스 라이브러리를 지원하기 위해 IL2CPP도 업그레이드해야 합니다. 최종적으로 전체 .NET 7.x 또는 8.0 API에 액세스할 수 있게 됩니다. 2024년 중으로 이 기능을 갖춘 새로운 에디터를 릴리스할 수 있기를 바랍니다. 

Unity 런타임 현대화

Unity 2021 LTS.NET Standard 2.1 지원을 통해 다양한 방식으로 Unity 런타임을 현대화할 수 있게 되었습니다. 유니티는 현재 아래와 같은 두 가지 측면을 개선하고 있습니다.

async/await 프로그래밍 모델을 개선합니다. async/await는 기초적인 프로그래밍 접근 방식으로, 엔진의 메인루프 차단 없이 비동기 연산이 완료될 때까지 대기해야 하는 게임플레이 코드를 작성합니다. 

2011년, async/await가 .NET에서 대중화되기 전에 유니티는 반복자(interator) 기반의 코루틴을 통해 비동기 연산을 도입했으나 이 접근 방식은 async/await와 호환되지 않으며 효율성이 저하될 가능성이 있습니다. 그동안 .NET Standard 2.1은 ValueTask를 통해 더 효율적인 async/await 연산 처리를 도입하고, AsyncMethodBuilder를 통해 작업 기반의 자체 시스템을 허용함으로써 C# 및 .NET에서 async/await 지원을 개선했습니다. 

이제 이러한 개선 사항을 활용할 수 있으며 Unity의 기존 비동기 연산을 통해 async/await 연산을 사용할 수 있도록 수정하고 있습니다(다음 프레임 대기 또는 UnityWebRequest 완료 대기 등). 첫 단계에서는 MonoBehavior가 제거되고 있거나 취소 토큰을 사용하여 플레이 모드를 종료할 때 대기 중인 비동기 작업을 취소할 수 있도록 개선합니다. 유니티는 UniTask의 작성자와 같이 커뮤니티에 적극적으로 기여하는 사용자들과 긴밀히 협력하여 이와 같은 신기능을 활용할 수 있도록 지원하고 있습니다.

Span<T>를 활용하여 메모리 할당과 사본을 줄입니다. Unity는 C# 스크립팅 레이어가 있는 C++ 엔진이기 때문에 둘 사이에 많은 데이터가 교환됩니다. 데이터를 상호 복사하거나, 관리되는 오브젝트를 새로 할당해야 하는 경우가 종종 있으므로 이는 비효율적일 수 있습니다. 

Span<T>는 이 과정을 개선하기 위해 C# 7.2에 도입되었으며 .NET Standard 2.1에서 기본적으로 사용 가능합니다. 최근 몇 년간 Span<T> 덕분에 .NET 런타임의 성능이 여러 면에서 크게 개선되었다는 소식을 아마 접하셨을 겁니다(.NET Core 2.1, .NET Core 3.0, .NET 5, .NET 6의 자세한 개선 사항 참조). Unity에서는 Span<T>를 활용하여 할당과 가비지 컬렉션의 멈춤 현상을 줄이고 API 다수의 전반적인 성능을 개선할 계획입니다.

유니티의 여정에 동참하세요

이번 포스팅에서 소개한 변경 사항과 기능에 큰 기대를 가져주셨으면 합니다. 

유니티의 계획에 대한 의견은 포럼에서 공유해 주세요. Unity 플랫폼 로드맵엔지니어링 섹션도 정기적으로 업데이트됩니다. 로드맵을 통해 새로운 기능을 요청하고 프로젝트 우선 순위를 제안하세요.

Is this article helpful for you?

Thank you for your feedback!