.NET Native AOT를 활용, 라이브 게임을 오프라인으로 전환하는 기술적 여정 공개

by DD
3개월 전
조회수 12

라이브 서비스 게임(Live Service Game)을 오프라인으로 전환하기 위해 .NET Native AOT를 활용하여 기존 C# 코드를 게임 클라이언트에 통합

서버리스 서비스(Serverless Service) 아키텍처를 구축, HTTP 요청을 가로채어 AOT DLL로 라우팅하여 기존 API를 재사용

코드 생성(Code Generation)을 통해 API 엔드포인트(API Endpoint)를 등록하고, C++와 C# 간의 데이터 구조 정렬을 통해 상호 운용성 확보

의존성 주입(Dependency Injection)을 활용하여 오프라인 환경에 필요한 구체적인 구현을 주입, 코드 재사용 및 유지보수 용이성 확보

.NET Native AOT를 활용한 오프라인 전환의 기술적 도전

저자는 라이브 게임을 오프라인으로 전환하기 위해 .NET Native AOT를 선택한 배경을 설명한다. 기존 C# 코드를 Unreal Engine 게임 클라이언트에서 실행하기 위해, 플랫폼 종속적인 문제를 해결해야 했다. 특히, Native AOT는 Windows와 Linux에서만 공식 지원되므로, Xbox 및 PS5 지원을 위해 FNA 프로젝트의 Native AOT 포트를 활용했다. 이러한 기술적 도전은 게임의 오프라인 지원을 위한 핵심적인 단계였다.

서버리스 서비스(Serverless Service) 아키텍처 설계

저자는 기존의 C# 백엔드 코드를 재사용하기 위해 서버리스 서비스(Serverless Service) 아키텍처를 구축했다. 이 아키텍처는 Unreal Engine 클라이언트에서 발생하는 HTTP 요청을 가로채어, Native AOT로 컴파일된 DLL로 라우팅한다. ProcessHttpRequest 함수를 통해 모든 요청을 처리하며, 코드 생성을 통해 API 엔드포인트를 등록하고, C++와 C# 간의 데이터 구조를 정렬하여 상호 운용성을 확보했다.

코드 생성(Code Generation)을 통한 API 통합

수백 개의 API를 지원하기 위해, 저자는 OpenAPI Swagger 엔드포인트를 활용한 코드 생성(Code Generation) 방식을 채택했다. Swagger API 명세를 기반으로 C# 코드를 생성하여, API 엔드포인트 등록 및 연결에 필요한 보일러플레이트 코드를 줄였다. 이러한 접근 방식은 API 통합의 효율성을 높이고, 유지보수성을 향상시키는 데 기여했다.

의존성 주입(Dependency Injection)을 활용한 환경 구성

저자는 의존성 주입(Dependency Injection)을 활용하여 오프라인 환경에 필요한 구체적인 구현을 주입했다. 기존의 .NET 웹 애플리케이션의 IoC 컨테이너를 활용하여, 오프라인 플레이에 필요한 구체적인 구현을 주입함으로써 코드 재사용성을 높였다. 예를 들어, 텔레메트리 클라이언트에 대해 no-op 구현을 주입하여, 오프라인 환경에서도 기존 코드를 최대한 활용할 수 있도록 했다.

데이터 구조 정렬 및 상호 운용성 확보

Unreal Engine C++ 코드와 C# DLL 간의 상호 운용성을 위해, 저자는 데이터 구조의 정확한 정렬에 특히 주의를 기울였다. UnmanagedProcessRequestFProcessHttpRequestRequest 구조체의 바이트 단위 호환성을 유지함으로써, 데이터 교환 과정에서 발생할 수 있는 문제를 방지했다. 이러한 세심한 설계는 안정적인 오프라인 게임 플레이를 위한 핵심 요소였다.

Offlining a Live Game With .NET Native AOT