콘텐츠로 건너뛰기
Codex

Godot에서 Tauri로 3일 만에 엔진을 갈아탄 이유

Godot에서 Tauri로 3일 만에 엔진을 갈아탄 이유

TECH NOTE · DESKTOP AI PET

Godot .NET로 만든 데스크톱 펫이 208M이 나와 Tauri로 옮긴 과정입니다. 무엇이 무거웠는지, 실제로 몇 M이 됐는지 실측으로 정리했습니다.

208M짜리 앱을 보고 엔진을 갈아탔다

데스크톱 펫을 Godot .NET으로 만들다가 Tauri로 옮겼다. 계기는 빌드 결과였다. macOS로 export한 앱이 208M이었다. 화면 한쪽에 캐릭터 하나 띄우는 프로그램 치고는 설명하기 어려운 크기다.

기능이 모자라서 바꾼 게 아니다. Godot 쪽은 이미 돌아가고 있었다. 그래서 옮기기 전에 숫자부터 재고, 그 숫자를 문서에 남긴 뒤에 움직였다.

208M이 어디서 나왔나

무엇이 무거운지부터 갈랐다. export한 앱을 뜯어보면 이렇다.

구성 크기
전체 PetDesktop.app 208M
Godot executable/runtime 79M
.NET arm64 runtime 82M
Pet.pck (게임 리소스) 23M
character-packs 24M
Godot .NET 208M과 Tauri 20M의 구성 비교
Godot .NET 208M과 Tauri 20M의 구성 비교

내가 만든 건 아래 두 줄, 47M이다. 나머지 161M은 런타임이다. Godot 런타임과 .NET 런타임을 둘 다 안고 배포하는 구조였다.

여기서 선택지가 갈렸다. .NET만 걷어내면 120~150M쯤 될 것 같았는데, 그러려면 GDScript나 Rust GDExtension으로 이식해야 했다. 절반만 줄이자고 거의 다시 쓰는 셈이라 이득이 애매했다.

옮기기 전에 먼저 재봤다

결정하기 전에 Tauri로 같은 것을 만들어 봤다. 비슷한 구조의 공개 저장소를 빌드해 실측한 값이 8.9M이었고, 여기에 Hermes 캐릭터를 얹은 스파이크가 23M이었다.

작은 이유는 단순하다. Godot 런타임이 없고, .NET 런타임이 없고, 화면은 OS에 이미 있는 WebView를 쓴다. Rust 릴리스 설정도 한몫한다.

[profile.release]
strip = true
lto = true
codegen-units = 1

세 선택지를 한 줄로 놓으면 이렇게 됐다.

선택지 크기 전환 비용 판단
Godot .NET 유지 208M (실측) 낮음 지금 구현을 이어가기엔 유리
Godot에서 .NET만 제거 120~150M (예상) 높음 이득 대비 복잡도가 애매
Tauri 2 + Rust + TS 23M (스파이크 실측) 높음 데스크톱 펫에는 가장 적합

실제로 나온 건 20M이었다

지금 배포하는 앱을 du -sh로 재보면 20M이다. 스파이크 때 예상한 것보다도 작다. 내부를 보면 실행 파일이 20M이고 리소스는 524K다.

여기서 갈린 게 하나 있는데, 크기 숫자보다 이쪽이 구조적으로 중요하다. 추가 캐릭터 팩이 앱 안에 없다. Godot 때는 Pet.pck 23M과 character-packs 24M이 앱 번들 안에 들어갔다. 지금은 팩이 앱 밖에 있고 사용자 폴더에 설치된다.

기본 캐릭터는 예외다. 처음 실행했을 때 화면에 뭐라도 있어야 하니, 기본 캐릭터 한 마리의 스프라이트 시트는 프론트엔드 에셋으로 실행 파일 안에 들어간다. 20M 중 10M이 그것이다. 앱이 가벼워진 건 캐릭터를 빼서가 아니라 런타임을 뺐기 때문이다.

구성 Godot .NET Tauri
앱 번들 208M 20M
기본 캐릭터 앱 안에 포함 앱 안에 포함 (10M)
추가 캐릭터 팩 앱 안에 포함 앱 밖, 사용자 폴더에 설치

캐릭터를 추가하려고 앱을 다시 빌드할 필요가 없어졌다는 뜻이다. 크기를 줄이려다 얻은 부수 효과였다.

크기만 보고 정한 건 아니다

숫자가 결정적이긴 했지만 그것만으로 엔진을 바꾸지는 않았다. 데스크톱 펫은 화면 위에 얹혀 사는 프로그램이라 OS 창 동작을 많이 건드린다. 투명 배경, 항상 위, 작업표시줄 숨김, 그림자 제거 같은 것들이다.

Tauri에서는 창 설정 몇 줄이다. 실제로 쓰는 값이다.

{
  "transparent": true,
  "decorations": false,
  "alwaysOnTop": true,
  "skipTaskbar": true,
  "shadow": false,
  "resizable": false,
  "acceptFirstMouse": true
}

게임 엔진은 게임 창을 띄우는 데 맞춰져 있다. 창을 데스크톱의 일부처럼 굴리는 일은 엔진 바깥에서 손대야 하는 경우가 많다. 만들려던 게 게임이 아니라 화면에 상주하는 캐릭터였으니, 손이 덜 가는 쪽이 맞았다.

옛 엔진은 조건을 정하고 지웠다

전환 자체는 빨랐다. 07-09 오후에 목표 아키텍처 문서를 쓰고, 같은 날 저녁까지 기반 구현과 팩 로더, 자율 행동 틱, 설정 저장까지 커밋이 이어졌다.

Godot 런타임을 지운 건 그다음 날이다. 순서를 이렇게 뒀다.

  1. 무엇이 같아야 지울 수 있는지 먼저 정했다 — Define the safety contract for retiring the Godot runtime (07-10 09:28)
  2. 그 조건을 통과한 뒤에 지웠다 — chore: retire the Godot runtime after the parity gate (07-10 12:39)

두 커밋 사이는 세 시간이다. 목표 아키텍처 문서부터 세면 하루가 조금 안 된다. 짧지만 순서가 뒤집혔으면 곤란했을 것이다. 새 구현이 도는 걸 보고 바로 옛 코드를 지우면, 나중에 빠진 기능이 나왔을 때 비교할 대상이 없어진다.

같이 나오는 질문

처음부터 Tauri로 시작했으면 되지 않았나

그랬으면 좋았겠지만 처음에는 크기가 문제될 줄 몰랐다. 208M을 보기 전까지 Godot .NET은 합리적인 선택이었다. 빌드해서 재보기 전에는 알기 어려운 종류의 문제다.

게임 엔진이 데스크톱 앱에 안 맞는다는 뜻인가

그런 뜻은 아니다. 만들려는 게 게임이면 반대 결론이 나온다. 여기서 갈린 조건은 “화면에 상주하면서 OS 창 동작을 많이 건드리는 프로그램”이었다.

전환 비용은 어떻게 감수했나

코드 재사용은 사실상 포기했다. 대신 캐릭터 팩 포맷과 설계 문서는 엔진과 무관하게 정의해 둔 상태였고 그대로 넘어갔다. 엔진에 묶이는 것과 아닌 것을 나눠 뒀던 게 이때 도움이 됐다.

다음에 볼 건 Tauri에서 투명·항상 위·클릭 통과 창을 실제로 어떻게 만드는지다. 설정 한 줄로 끝나는 것과 직접 구현해야 하는 것이 갈린다.

이 블로그 더 보기

이 블로그는 실제 프로젝트를 AI와 함께 굴리면서 남긴 기록입니다.

  • 새 글은 RSS로 받아볼 수 있습니다.
  • 시리즈 전체는 여기에 정리해 두었습니다.

“Godot에서 Tauri로 3일 만에 엔진을 갈아탄 이유”의 1개의 댓글

  1. 핑백: 번들 크기를 실측하는 방법 - Bluecafe Blog

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다