시뮬레이터 개발 과정은 초기 시각화에 대한 매니저의 불만족스러운 반응(“생물학 농담인가? 차는 어디에?”)에서 시작하여, 점차 실제 차량 흐름과 재무 데이터를 포함하는 형태로 발전했습니다. 시뮬레이션의 핵심 개념은 YAML 파일을 통해 다양한 시나리오를 정의하고, 이를 시뮬레이션 러너가 실행하며, 로거, 타이머, 글로벌 리포트 등의 컴포넌트가 유기적으로 작동하는 것입니다.
주요 기술적 구현으로는 맞춤형 타이머가 눈에 띕니다. 시스템 시간 대신 Thread.sleep
과 tick
메커니즘을 사용하여 시뮬레이션 속도를 제어했으며, JRuby와 MRI(Ruby의 GIL) 환경에서의 스레드 동작 차이를 직접 경험하며 MRI가 시뮬레이션 동시성에 더 적합하다고 설명했습니다. 차량 생성기(Car Spawner)는 지연 열거자(lazy enumerator) 패턴을 사용하여 모든 차량을 미리 메모리에 로드하거나 각 차량에 개별 스레드를 할당하는 비효율을 피했습니다. 이는 대규모 시뮬레이션에서도 CPU 부하를 낮게 유지하는 데 기여합니다.
가장 중요한 동시성 제어 부분에서는 루비의 Mutex
와 ConditionVariable
을 활용한 생산자-소비자(Producer-Consumer) 패턴이 적용되었습니다. 차량 생성기가 Mutex
로 보호되는 큐에 차량을 추가(생산자)하고, 주유 펌프(소비자)는 큐에서 차량을 가져와 처리합니다. 이때 ConditionVariable
의 wait
, signal
, broadcast
메서드를 사용하여 큐가 비어 있을 때 펌프 스레드를 대기시키고, 새로운 차량이 들어오면 깨우는 방식으로 효율적인 동시성 처리를 구현했습니다. 시각적인 요소는 ASCII 아트를 사용하여 콘솔에서 주유소의 움직임을 표현했습니다.
프로젝트를 통해 얻은 교훈으로는 초기 단계부터 의존성 주입(Dependency Injection)을 고려하는 것이 중요하며, 시스템 시간 대신 자체 카운터를 사용하는 것이 더 정밀한 제어를 가능하게 한다는 점이 강조되었습니다. 또한, 루비 MRI의 GIL(Global Interpreter Lock)이 동시성 코드의 동작에 미치는 영향을 이해하고, 프로토타입 개발 시에는 테스트보다는 빠른 실험에 집중하는 것이 효율적이라는 실용적인 조언도 포함되었습니다. 취미 프로젝트가 실제 업무 코드 품질 향상에 기여한다는 점 또한 역설했습니다.