라이브 서비스 게임(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를 선택한 배경을 설명한다. 기존 C# 코드를 Unreal Engine 게임 클라이언트에서 실행하기 위해, 플랫폼 종속적인 문제를 해결해야 했다. 특히, Native AOT는 Windows와 Linux에서만 공식 지원되므로, Xbox 및 PS5 지원을 위해 FNA 프로젝트의 Native AOT 포트를 활용했다. 이러한 기술적 도전은 게임의 오프라인 지원을 위한 핵심적인 단계였다.
저자는 기존의 C# 백엔드 코드를 재사용하기 위해 서버리스 서비스(Serverless Service) 아키텍처를 구축했다. 이 아키텍처는 Unreal Engine 클라이언트에서 발생하는 HTTP 요청을 가로채어, Native AOT로 컴파일된 DLL로 라우팅한다. ProcessHttpRequest 함수를 통해 모든 요청을 처리하며, 코드 생성을 통해 API 엔드포인트를 등록하고, C++와 C# 간의 데이터 구조를 정렬하여 상호 운용성을 확보했다.
수백 개의 API를 지원하기 위해, 저자는 OpenAPI Swagger 엔드포인트를 활용한 코드 생성(Code Generation) 방식을 채택했다. Swagger API 명세를 기반으로 C# 코드를 생성하여, API 엔드포인트 등록 및 연결에 필요한 보일러플레이트 코드를 줄였다. 이러한 접근 방식은 API 통합의 효율성을 높이고, 유지보수성을 향상시키는 데 기여했다.
저자는 의존성 주입(Dependency Injection)을 활용하여 오프라인 환경에 필요한 구체적인 구현을 주입했다. 기존의 .NET 웹 애플리케이션의 IoC 컨테이너를 활용하여, 오프라인 플레이에 필요한 구체적인 구현을 주입함으로써 코드 재사용성을 높였다. 예를 들어, 텔레메트리 클라이언트에 대해 no-op 구현을 주입하여, 오프라인 환경에서도 기존 코드를 최대한 활용할 수 있도록 했다.
Unreal Engine C++ 코드와 C# DLL 간의 상호 운용성을 위해, 저자는 데이터 구조의 정확한 정렬에 특히 주의를 기울였다. UnmanagedProcessRequest 및 FProcessHttpRequestRequest 구조체의 바이트 단위 호환성을 유지함으로써, 데이터 교환 과정에서 발생할 수 있는 문제를 방지했다. 이러한 세심한 설계는 안정적인 오프라인 게임 플레이를 위한 핵심 요소였다.