TECH 으로 돌아가기
TECH HACKER NEWS 오늘 9분 읽기 28 READS

Godot에 C++ 라이브러리를 붙이는 법: godot-cpp와 Conan으로 빌드 문제 풀기

Godot는 최근 몇 년 사이 가장 널리 쓰이는 게임 엔진 중 하나로 자리 잡았다. MIT 라이선스의 무료 오픈소스이고, 내려받아 몇 분 만에 쓰기 시작할 수 있을 만큼 가볍다는 점이 성장의 배경이다. 대부분의 Godot 게임은 엔진 자체 스크립트 언어인 GDScript로 작성된다. GDScript는 파이썬을 닮은 언어로, 컴파일 단계 없이 수정이 곧바로 반영되기 때문에 게임플레이 로직을 다루기에 편하다. 그러나 프로젝트가 커지면 이미 C나 C++ 라이브러리로 존재하는 기능, 예컨대 시뮬레이션 엔진, 데이터베이스, 네트워킹 프로토콜, 머신러닝 런타임 같은 것을 끌어와야 하는 순간이 온다. 문제는 GDScript가 네이티브 코드를 직접 호출하지 못한다는 데 있다.

GDExtension과 godot-cpp가 하는 일

Godot는 GDExtension이라는 구조를 통해 네이티브 코드를 로드한다. 엔진 자체가 C++로 작성되어 있고, 재컴파일 없이 C++로 만든 확장을 불러올 수 있다는 점이 C++ 개발자에게 흥미로운 대목이다. 이렇게 확장으로 들어온 클래스는 엔진의 일반 클래스와 똑같이 취급된다. 에디터에서 내장 노드 옆에 나타나고, 인스펙터에 속성이 노출되며, GDScript에서 여느 노드처럼 다룰 수 있다. C 인터페이스를 직접 쓰기는 번거롭기 때문에 Godot 팀은 godot-cpp라는 공식 바인딩을 관리한다. 이 라이브러리는 Node2D, Sprite2D, Input 같은 엔진 클래스마다 대응하는 C++ 클래스를 제공하며, 개발자는 그 클래스를 상속한 자신의 클래스를 작성하면 된다.

버전 관리도 정리됐다. godot-cpp 10.0부터는 단일 릴리스가 Godot 4.3 이상 어떤 버전과도 동작한다. api_version 빌드 옵션으로 기준 버전을 고르면 godot-cpp가 해당 API로부터 C++ 클래스를 생성한다. 4.3용으로 빌드한 확장은 더 새로운 버전에서도 동작하지만 이전 버전에서는 안 되므로, 보통 지원하려는 가장 오래된 버전을 고른다. 또한 godot-cpp는 에디터·디버그·릴리스라는 세 가지 타깃 중 하나로 컴파일되며, 런타임에 어떤 라이브러리를 로드할지는 기능 태그와 라이브러리 경로를 연결하는 작은 .gdextension 파일이 결정한다.

진짜 어려운 부분은 코드가 아니라 빌드

확장의 C++ 코드를 쓰는 일 자체는 어렵지 않다. 정작 까다로운 것은 빌드다. godot-cpp는 사용하는 Godot 버전과 맞아야 하고, 추가하는 모든 라이브러리는 출시하려는 플랫폼마다 컴파일해야 한다. Godot 공식 문서는 godot-cpp를 git 서브모듈로 저장소에 넣고 SCons로 함께 빌드하는 방식을 권한다. 첫 확장에는 무난하지만, 결국 모든 프로젝트가 타깃·플랫폼·아키텍처마다 자기만의 godot-cpp를 다시 컴파일하게 되고, 물리 엔진이나 머신러닝 런타임처럼 감싸려는 서드파티 라이브러리도 플랫폼마다 일치하는 플래그로 벤더링해 빌드해야 한다. 바로 이 반복이 패키지 매니저가 해결하려는 문제다.

ConanCenter에 올라온 godot-cpp 레시피를 쓰면 godot-cpp는 하나의 일반 패키지가 된다. 앞서 언급한 두 매개변수는 Conan 옵션으로 노출되고, 각 조합은 한 번만 빌드된 뒤 그것을 필요로 하는 모든 프로젝트에서 재사용된다. 확장을 만든다는 것은 의존성을 가진 평범한 C++ 프로젝트를 만드는 일이 되며, ConanCenter의 1,900개가 넘는 라이브러리나 직접 패키징한 레시피를 godot-cpp 옆에 나란히 붙일 수 있다. Conan은 목표 플랫폼마다 그것들을 일관되게 빌드한다.

flecs로 입자 10만 개를 돌리는 예제

글에서 소개한 예제는 Swarm이라는 새 노드를 등록하는 GDExtension이다. 마우스 커서를 피해 달아나고 창 가장자리에서 튕기는 입자 10만 개를 시뮬레이션해 장면에 그린다. 시뮬레이션은 C·C++용 엔티티 컴포넌트 시스템(ECS) 라이브러리인 flecs로 돌아간다. ECS에서 엔티티는 단순한 id, 컴포넌트는 그에 붙는 데이터 구조체, 시스템은 특정 컴포넌트 집합을 가진 모든 엔티티에 대해 도는 함수다. 같은 타입의 컴포넌트를 메모리에 함께 저장하기 때문에 대량의 엔티티를 순회하는 속도가 빠르고, 그래서 시뮬레이션이나 군중, 탄막 게임에 즐겨 쓰인다. 매 프레임 이만큼의 엔티티를 갱신하는 일은 GDScript보다 C++에서 훨씬 빠르므로, 네이티브 코드의 이점이 드러나는 작업이기도 하다.

구조를 보면 conanfile.py가 ConanCenter에서 godot-cpp와 flecs를 요구하고, generate() 단계에서 godot-cpp 의존성의 target 옵션을 읽어 CMake에 넘겨 라이브러리 이름이 링크된 바이너리와 항상 일치하도록 한다. 확장은 godot-cpp와 flecs를 정적으로 링크하는 공유 라이브러리이므로 배포할 파일은 하나뿐이며, 곧바로 demo/bin에 쓰여 Godot가 추가 복사 없이 찾는다. Swarm 클래스는 Node2D를 상속해 flecs 월드를 소유하고, GDCLASS 매크로가 클래스 시스템에 필요한 상용구를, _bind_methods()가 count와 flee_radius 속성을 선언한다. 이 속성들은 등록 뒤 인스펙터에 나타나고 GDScript에서 쓸 수 있다. _ready()는 입자마다 flecs 엔티티와 갱신 시스템을 만들고, 한 번의 드로우 콜로 같은 메시를 여러 번 그리는 MultiMesh를 설정한다. 입자 하나당 노드 하나를 두면 10만 개에는 너무 무겁기 때문이다. 매 프레임 _process()는 마우스 위치를 flecs에 넘기고 world.progress()로 시스템을 돌린 뒤 결과 위치를 MultiMesh로 복사한다.

한 가지 눈여겨볼 점은 클래스 등록에 GDREGISTER_RUNTIME_CLASS를 쓴다는 것이다. 기본적으로 GDExtension 클래스의 코드는 에디터 안에서도 실행되므로, 그대로 두면 장면을 편집하는 동안 _ready()와 _process()가 시뮬레이션을 시작해버린다. 런타임 클래스로 등록하면 에디터에서는 장면에 추가하고 속성을 설정할 수 있는 자리표시자에 그치고, 실제 코드는 게임이 실행될 때만 돈다. 빌드는 conan 명령 한 번으로 끝나며, godot-cpp는 C++17을 요구하므로 기본 프로파일 표준이 낮은 MSVC 등에서는 -s compiler.cppstd=17을 덧붙이면 된다.

결국 이 조합의 실무적 가치는 배포 시점에 드러난다. GDExtension과 godot-cpp가 C++로 엔진 클래스를 작성하게 해주고, Conan이 godot-cpp와 그 밖에 필요한 C++ 라이브러리의 빌드를 대신 맡는다. 여러 플랫폼용으로 확장을 만드는 일이 빌드 설정만 바꾸는 문제로 줄어든다는 뜻이다. 다만 이 글은 개념과 골격만 보여주는 단순화된 예시이며, 전체 코드는 Conan examples2 저장소에 있으니 실제 적용 전에는 라이브러리별 링크 플래그와 지원 대상 버전 정책을 직접 확인하는 편이 안전하다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://blog.conan.io/cpp/conan/gamedev/godot/cmake/2026/09/...
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...