Ruck: Ruby를 위한 강력한 타이밍 및 가상 시간 라이브러리

[29S07] Now you're thinking with virtual clocks

작성자
RubyKaigi
발행일
2025년 10월 05일

핵심 요약

  • 1 Ruck은 Chuck 프로그래밍 언어에서 영감을 받은 Ruby 라이브러리로, 강력한 타이밍과 가상 시간 개념을 활용하여 라이브 코딩 및 시간 제어 애플리케이션 개발을 지원합니다.
  • 2 이 라이브러리는 'shred'(스레드), 'shredular'(스케줄러), 'spork'(포크)와 같은 고유한 용어를 사용하여 Ruby 환경 내에서 동시성 및 시간 기반 이벤트를 정밀하게 관리합니다.
  • 3 Shredular를 통해 실제 시간, MIDI 틱, 오디오 스트림 등 다양한 시간 단위에 가상 시간을 유연하게 매핑할 수 있으며, 이를 통해 게임의 프레임 속도 독립성 및 음악 시퀀싱의 정확성을 확보합니다.

도입

본 발표는 Ruby 개발자를 위한 'Ruck'이라는 라이브러리를 소개합니다. Ruck은 실시간으로 코드를 작성하고 실행하는 '라이브 코딩' 퍼포먼스를 위해 설계된 'Chuck'이라는 오디오 프로그래밍 언어에서 영감을 받았습니다. Chuck의 핵심 개념인 '강한 타이밍(strong timing)'과 '가상 시간(virtual time)'을 Ruby 환경으로 가져와, 개발자가 시간의 흐름을 정밀하게 제어하고 예측 가능한 방식으로 동시성 작업을 관리할 수 있도록 돕는 것이 Ruck의 목적입니다. 이를 통해 복잡한 시간 기반 로직을 단순화하고, 다양한 시간 매핑 시나리오에 유연하게 대응할 수 있는 프레임워크를 제공합니다.

Ruck 라이브러리는 Chuck 언어의 강력한 시간 제어 개념을 Ruby에 도입합니다. 이는 특히 라이브 코딩 퍼포먼스나 시간 의존적인 애플리케이션 개발에 유용합니다. 모든 코드는 즉각적으로 실행되며, 시간은 명시적으로 ‘허용’될 때만 흐른다는 가상 시간 모델을 따릅니다. 이는 여러 동시성 작업 간의 일관성과 예측 가능성을 보장합니다.Ruck은 Ruby의 스레드와 스케줄러 개념을 확장하기 위해 다음과 같은 고유한 용어를 사용합니다.

Ruck의 핵심 개념

  • Shred: Ruby의 스레드와 유사하지만, Ruck의 스케줄러에 의해 관리되는 실행 단위입니다.
  • Shredular: Ruby의 스케줄러와 유사하지만, Shred들을 관리하고 가상 시간의 흐름을 조율하는 객체입니다.
  • Spork: Ruby의 fork와 유사하지만, 프로세스 대신 Shred를 생성합니다.Shred는 shred.yield를 호출하여 가상 시간 단위로 시간을 양보하며, 이는 Ruby의 sleep과 달리 가상 시간 위에서 동작합니다. Shredular는 이 Shred들을 정확한 가상 시간에 깨워 타임라인의 일관성을 유지합니다.

Shredular의 역할과 사용자 정의Shredular는 가상 시간과 실제 시간 또는 다른 시간 단위(예: MIDI 틱, 오디오 스트림) 사이의 매핑을 담당합니다. 기본 Shredular는 가상 시간 진행 시 아무 작업도 수행하지 않으므로, 개발자는 Shredular를 서브클래싱하고 fast_forward 메서드를 오버라이딩하여 원하는 시간 매핑 로직을 구현할 수 있습니다. 예를 들어, fast_forward 내부에 sleep 명령어를 넣어 실제 시간과 연동하거나, 오디오 샘플을 생성하는 로직을 추가할 수 있습니다.

Ruck의 활용 사례

MIDI 시퀀싱발표자는 Ruck을 사용하여 임의의 코드를 생성하고 멜로디를 오버레이하는 MIDI 시퀀싱 스크립트를 시연했습니다. Shredular의 fast_forward 메서드를 오버라이딩하여 MIDI 이벤트를 파일로 저장하거나 실시간으로 재생하도록 설정할 수 있습니다. 동일한 코드 기반 위에서 Shredular의 설정 변경만으로 재생 속도를 두 배로 늘리거나 절반으로 줄이는 등 유연한 시간 제어가 가능합니다.

게임 개발 (프레임 속도 독립성)Ruck은 게임 개발에서도 강력한 이점을 제공합니다. Chipmunk 물리 엔진 데모 게임을 Ruck 기반으로 재구성한 사례에서, 물리 시뮬레이션, 별 애니메이션, 프레임 속도 계산, 심지어 드로잉 코드까지 모두 Ruck에 의해 스케줄링됩니다. 이로 인해 게임은 프레임 속도에 독립적으로 동작합니다. 렌더링 콜백 내에서 지연이 발생하더라도, 애니메이션이나 물리 시뮬레이션은 정확한 가상 시간 흐름에 따라 실행되어 ‘느려지는’ 현상이 발생해도 내부 로직은 정확성을 유지합니다.이는 전통적인 게임 루프에서 흔히 볼 수 있는 복잡한 시간 계산 로직(current_time, last_update_time 등)을 Shredular 내부로 집중시킴으로써 개발자가 ‘언제’ 특정 이벤트가 발생해야 하는지에만 집중할 수 있게 합니다. 그래픽 콜백은 단순히 Shredular의 run_until 함수를 호출하여 현재 가상 시간까지 모든 Shred를 실행시키는 역할만 수행합니다. 또한, Ruck은 계층적 클록(subclock) 기능을 제공하여, 서로 다른 비율로 실행되는 시간 흐름을 생성하고 제어할 수 있어, 음악에 스윙을 추가하거나 특정 이벤트 그룹을 일시 정지하는 등의 고급 시간 조작이 가능합니다.

결론

Ruck 라이브러리는 Ruby 개발자에게 Chuck 언어의 '강한 타이밍'과 '가상 시간'이라는 강력한 개념을 제공합니다. 이를 통해 개발자는 시간의 흐름을 완벽하게 제어하고, 동시성 작업을 예측 가능하며 일관된 방식으로 관리할 수 있습니다. Shredular의 유연한 시간 매핑 기능은 MIDI 시퀀싱, 게임 개발과 같은 다양한 시간 의존적 애플리케이션에서 프레임 속도 독립성, 정확한 이벤트 타이밍, 그리고 코드의 모듈성을 크게 향상시킵니다. Ruck은 복잡한 시간 관련 로직을 단순화하고, 라이브 코딩 퍼포먼스 및 정밀한 시간 제어가 필요한 프로젝트에서 Ruby의 잠재력을 확장하는 중요한 도구로 자리매김할 것입니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!