Ruby Ractors를 활용한 실전 프로젝트 경험과 미래

Seong Heon Jung, "Using Ractors and Making Ractors Usable"

작성자
EuRuKo
발행일
2025년 01월 13일

핵심 요약

  • 1 Ractors는 Ruby에서 스레드의 한계를 극복하고 안전한 동시성 및 병렬성을 제공하기 위해 도입된 새로운 추상화 모델입니다.
  • 2 Ractors는 메모리 공유를 지양하고 메시지 전달 방식을 채택하여 데드락과 데이터 경쟁 같은 동시성 문제를 해결하는 데 중점을 둡니다.
  • 3 현재 Ractors는 불안정한 API와 잠재적 버그를 포함하고 있으나, Ruby가 현대 프로그래밍 언어로서 경쟁력을 확보할 핵심적인 기회로 평가됩니다.

도입

본 발표는 Ruby의 새로운 동시성 모델인 Ractors에 대한 실질적인 개발 경험을 공유하며, 기존 스레드 기반 동시성 프로그래밍의 한계와 Ractors가 제시하는 해결책을 탐구합니다. 스피커는 Ractors를 활용하여 실제 프로젝트를 구축하는 과정에서 겪었던 도전과제와 얻은 교훈을 통해, Ractors의 잠재력과 Ruby 커뮤니티가 나아가야 할 방향에 대한 심층적인 논의를 제안합니다.

스레드 기반 동시성의 문제점: 유아원 비유

발표자는 스레드 기반 동시성 프로그래밍의 어려움을 ‘유아원 아이들이 하나의 색칠 공부 책을 공유하는 상황’에 비유하여 설명합니다. 아이들(스레드)에게 명확한 규칙(락, 뮤텍스)을 주지 않으면 다음과 같은 문제가 발생합니다.

  • 비효율적인 대기: 한 아이가 그림을 그리다 잠들면, 다음 아이는 무한정 기다리게 됩니다. (스레드가 자원을 점유한 채 블로킹되는 상황)
  • 데드락: 두 아이가 서로 다른 자원을 기다리며 서로를 블로킹하는 상황이 발생합니다. (자원 교착 상태)

이러한 문제는 스레드가 메모리를 자유롭게 공유하고 언제든 잠들 수 있기 때문에 발생하며, 이는 프로그래머가 모든 예외 상황에 대한 명시적인 규칙을 설정해야 하는 복잡성을 야기합니다.

Ractors의 등장과 핵심 원칙

Ractors는 이러한 스레드의 문제점을 해결하기 위해 다음과 같은 세 가지 핵심 원칙을 기반으로 합니다.

  1. 메모리 공유 없음: 다른 Ractor의 데이터를 직접 건드리지 않습니다.
  2. 메시지 요청: 필요한 데이터는 해당 데이터를 가진 Ractor에게 메시지로 요청합니다.
  3. 메시지 응답: 요청받은 메시지에 대해 반드시 응답합니다.

이러한 제약은 동시성 추론을 훨씬 용이하게 만들며, 스레드 프로그래밍의 고질적인 문제들을 회피할 수 있도록 돕습니다.

Ractors를 활용한 실제 프로젝트

발표자는 Ractors의 실용성을 검증하기 위해 두 가지 프로젝트를 진행했습니다.

  1. RAW TCP/HTTP 서버: Sidekiq Enterprise의 헬스체크 서비스에 사용된 GServer를 Ractors 기반으로 재구현했습니다. 이는 비교적 간단한 구조로 Ractors의 spawnyield 기능을 활용하여 연결 풀을 관리하는 방식으로 구현되었습니다.
  2. Rack 호환 서버: Puma와 유사하게 비동기 I/O, HTTP 요청을 Rack 환경으로 변환, 워커 스케줄링을 처리하는 더 복잡한 서버를 구축하려 했습니다.

Ractors 개발 과정에서의 도전과제 및 한계

Rack 호환 서버 개발 과정에서 여러 난관에 봉착했습니다.

  • Gem 호환성 문제: async-http와 같이 스레드/파이버 안전하지만 Ractor 안전하지 않은 Gem이 존재했습니다. 특히, Ractor 간에 IO 객체를 전달할 수 없는 제약 때문에 Singleton 로거와 같은 문제를 해결하기 위해 원격 프로시저 호출(RPC) 개념을 도입하고 Ruby의 refinements 기능을 활용하여 로거 호출을 메시지 전달로 우회했습니다.
  • 스레드-Ractor 상호작용의 불명확성: 스레드 내 Ractor 작업(Ractor#take)이 파이버(Fiber) 깨우기 이벤트를 제대로 트리거하지 않는 버그가 발견되어, 워커 Ractor가 처리한 응답을 리시버 파이버로 다시 전달하는 데 어려움이 있었습니다.
  • 메모리 버그: Ractor 간 메시지 전달 시 객체 자동 동결 기능이 제대로 작동하지 않아 문자열 보간에서 메모리 손상(memory corruption)이 의심되는 현상이 발생했습니다. 이는 Ractors를 프로덕션 환경에 적용하기 매우 어렵게 만드는 치명적인 문제입니다.

Ruby의 미래와 Ractors의 역할

발표자는 Ruby 커뮤니티가 직면한 현실, 즉 Ruby가 과거만큼 ‘흥미로운’ 언어로 인식되지 않는다는 점을 지적합니다. Go, Elixir, Rust와 같은 빠르게 성장하는 언어들은 모두 강력한 동시성 및 병렬성 기능을 제공하며 개발자들의 관심을 끌고 있습니다. Ruby가 이러한 흐름에 발맞추어 스크립팅 언어로서 독보적인 위치를 차지하려면, Ractors와 같은 동시성 추상화가 핵심적인 돌파구가 될 수 있다고 강조합니다.

커뮤니티에 대한 요청

발표자는 Ractors가 아직 미완성이고 버그가 있지만, 충분히 실질적인 프로젝트를 구축할 수 있음을 보여주며 커뮤니티에 적극적인 참여를 요청합니다. 단순한 ‘장난감’ 프로젝트가 아닌, 실제 관심 있는 문제나 새로운 프레임워크 학습에 Ractors를 적용해보고, 그 과정에서 발견되는 문제점, 성공 사례, 예상치 못한 동작 등을 공유함으로써 Ractors의 발전과 Ruby의 혁신에 기여할 것을 독려합니다.

결론

Ractors는 Ruby의 동시성 및 병렬성 문제를 해결하고 언어의 미래 경쟁력을 확보할 중요한 기회를 제공합니다. 현재 불안정한 API와 버그가 존재하지만, 이는 커뮤니티의 적극적인 참여와 피드백을 통해 개선될 수 있습니다. 발표자는 개발자들이 Ractors를 두려워하지 않고 실제 프로젝트에 적용하며 경험을 공유함으로써, Ruby가 다른 스크립팅 언어와 차별화되는 강력한 동시성 기능을 갖춘 언어로 발전할 수 있기를 촉구합니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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