조나단은 전통적인 게임 엔진(Unreal, Godot, Unity)이 실시간 고속 처리에 강점을 보이지만, 배우고 활용하기에 시간 제약이 있음을 지적합니다. 반면 Rails는 사용자 입력을 받아 게임 상태를 변경하고, 이를 사용자에게 렌더링하며, 백그라운드 작업을 처리하는 등 게임 엔진의 핵심 기능과 유사한 동작 방식을 가집니다. 특히 HTTP의 본질적인 지연 시간 때문에 1인칭 슈팅 게임과 같은 실시간 반응형 게임에는 부적합하지만, 카드 게임이나 턴 기반 전략 게임처럼 사용자 입력이 게임 상태 변화의 주요 동인인 경우 Rails는 매우 효과적입니다. 사용자 인식이 사실적 정확성보다 중요한 게임의 특성을 고려할 때, Rails는 다음과 같은 장점을 제공합니다.
Rails를 게임 엔진으로 활용 시의 장점
-
지속적인 업데이트: 페이지 새로고침마다 새로운 클라이언트 코드를 배포할 수 있어 별도의 업데이트 다운로드가 필요 없습니다.
-
기본 멀티플레이어 지원: Devise와 같은 로그인 시스템을 통해 기본적으로 멀티플레이어 환경을 구축할 수 있습니다.
-
개방형 플랫폼: Apple 또는 Steam과 같은 플랫폼 수수료 없이 직접 서비스를 제공할 수 있습니다.
Galactic Impact 구현 사례
조나단은 2020년, 10년 이상의 Rails 개발 및 게임 디자인 경험을 바탕으로 ‘Galactic Impact’를 재구축했습니다. 이 게임은 90년대 4X 게임에 대한 오마주이면서도 식민주의적 요소를 배제하고, 사용자 경험을 존중하며(도박, 현질 유도 없음), 영구적으로 변화하는 공유 은하계를 특징으로 합니다.
-
데이터 모델링:
User,Empire,Star,World,Ship등 게임 내 엔티티들은 Active Record를 통해 효과적으로 관리됩니다.Unit모델 Concern을 사용하여World와Ship이Order큐를 가질 수 있도록 구현했습니다. -
게임 시뮬레이션: 게임은 3시간마다 업데이트되는 턴 기반 방식으로 운영됩니다. Sidekiq 배치 작업을 활용하여 수천 개의 레코드에 대한 복잡한 시뮬레이션을 처리합니다.
-
입력 차단: 게임 업데이트 중에는 사용자가 이상한 상태를 보거나 타이밍 해킹을 시도하는 것을 막기 위해, 해당 사용자를 임시 대기 페이지로 리디렉션하는
before_filter를ApplicationController에 구현했습니다. -
실시간 UI 업데이트: Turbo Stream을 HTML 태그로 활용하여 서버 응답 시 애플리케이션 전반에 걸쳐 여러 UI 요소를 동시에 업데이트합니다. 예를 들어, 건물 건설 시 자원 미터와 크레딧이 즉시 반영됩니다.
-
지연 로딩 UI:
<details>와<summary>태그 내에 Turbo Frame을 사용하여 로스터(Roster)와 같은 복잡한 UI 섹션을 필요할 때만 지연 로딩하여 성능을 최적화했습니다. -
지리 공간 데이터: PostGIS 확장 기능과
active_record_postgis_adapterGem을 활용하여 별의 위치(geometry타입)를 저장하고,within_radius_of와 같은 스코프를 통해 거리 기반 쿼리를 효율적으로 수행합니다. 또한 RGeo를 사용하여 Empire의 영토에 대한 볼록 껍질(convex hull)을 계산하여 새로운 플레이어의 시작 위치를 결정하는 데 활용합니다. -
과거 상태 기록 및 전투 로그: 전투 결과를 기록하기 위해
InteractionParticipant모델에before와after필드를 두어 전투 전후 유닛의 상태를 YAML로 직렬화하여 저장합니다. 이를 통해 과거 전투 로그를 조회할 때 Rails의 더티 트래킹(changes배열) 기능을 활용하여 어떤 변화가 있었는지 직관적으로 보여줍니다. -
동적 지도 상호작용:
document.elementsFromPointJavaScript API와 Stimulus 컨트롤러, SVG를 활용하여 2D 지도 상에 겹쳐진 유닛들을 커서 위치에서 정확하게 식별하고 상호작용할 수 있는 기능을 구현했습니다.