Rack 애플리케이션을 위한 코드 리로딩

Code Reloading for Rack Apps | Jared Norman

작성자
Awesome Ruby
발행일
2025년 07월 23일

핵심 요약

  • 1 Rails와 달리 Rack 기반 Ruby 애플리케이션은 기본적으로 코드 리로딩 기능을 제공하지 않습니다.
  • 2 이 글은 Zeitwerk, listen, concurrent-ruby 젬을 활용하여 Rack 앱에서 효율적인 코드 리로딩을 구현하는 방법을 설명합니다.
  • 3 제안된 솔루션은 개발 환경에서 서버 재시작 없이 코드 변경 사항을 즉시 반영하며, 스레드 안전성까지 고려합니다.

도입

Ruby on Rails는 Zeitwerk를 통해 강력한 코드 로딩 및 리로딩 기능을 기본으로 제공합니다. 그러나 Rails 프레임워크를 사용하지 않고 Rack 위에 직접 구축된 Ruby 애플리케이션은 이러한 편의 기능을 자체적으로 구현해야 합니다. 본 문서는 Rack 애플리케이션에서 개발 생산성을 높이기 위해 코드 리로딩 기능을 효과적으로 통합하는 방법을 심층적으로 다룹니다. 특히, Zeitwerk, listen 젬, 그리고 concurrent-ruby 라이브러리를 활용하여 Rails와 유사한 수준의 코드 리로딩 메커니즘을 Rack 앱에 적용하는 구체적인 방법을 제시합니다.

코드 리로딩 구현을 위해 몇 가지 핵심 젬(concurrent-ruby, listen, puma, rack, zeitwerk)이 필요하며, 이는 Gemfile에 명시되어야 합니다. 애플리케이션 구조는 config/environment.rb에서 환경을 로드하고, lib/my_app.rb에서 Rack 애플리케이션을 정의하며, config.ru를 통해 애플리케이션을 실행하는 형태로 구성됩니다.

첫 번째 유틸리티 클래스는 Once입니다. 이 클래스는 특정 코드 블록이 여러 스레드에서 호출되더라도 단 한 번만 실행되도록 보장하는 역할을 하며, 이는 서버 포크 이전에 리스너 스레드를 시작하지 않도록 하는 데 중요하게 사용됩니다.

핵심적인 구성 요소는 CodeLoader 클래스입니다. 이 클래스는 Zeitwerk 로더를 초기화하고, 지정된 경로의 코드를 로드합니다. 개발 환경에서는 코드 리로딩을 활성화하고, Listen 젬을 사용하여 파일 시스템 변경 사항을 감지합니다. 또한, Concurrent::ReadWriteLock을 사용하여 코드 리로딩 과정의 스레드 안전성을 확보합니다. reload! 메서드는 파일 변경이 감지될 때 실제 코드 리로딩을 수행하며, 이 과정에서 쓰기 잠금을 획득하여 다른 요청이 방해받지 않도록 합니다. 프로덕션 환경에서는 eager_load를 통해 코드를 즉시 로드하여 copy-on-write 성능 이점을 활용합니다.

CodeLoaderMiddleware는 Rack 미들웨어로 작동하며, 각 요청이 들어올 때마다 CodeLoaderreload! 메서드를 호출하여 코드 변경 여부를 확인하고 필요시 리로드합니다. 이 미들웨어는 또한 로더의 읽기 잠금을 사용하여 코드 리로딩 중에는 요청 처리를 지연시켜 스레드 안전한 환경을 유지합니다.

마지막으로, lib/my_app.rb에서 CodeLoaderMiddleware를 사용하도록 설정하고, 특히 개발 환경에서 코드 리로딩이 활성화된 경우 run 메서드를 Proc으로 래핑하여 매 요청마다 최신 버전의 애플리케이션 코드를 참조하도록 합니다. 이는 이전에 로드된 코드의 오래된 참조(stale reference)로 인해 코드 리로딩이 제대로 작동하지 않는 문제를 해결합니다.

결론

본 문서에서 제시된 `CodeLoader`와 `CodeLoaderMiddleware`의 조합은 Rack 애플리케이션에서 Rails와 유사한 수준의 강력하고 스레드 안전한 코드 리로딩 기능을 구현할 수 있도록 합니다. 이를 통해 개발자는 서버를 재시작할 필요 없이 코드 변경 사항을 즉시 확인할 수 있어 개발 효율성이 크게 향상됩니다. 이 접근 방식은 Rails 내부의 코드 리로딩 메커니즘과도 유사하며, Rack 기반 애플리케이션의 개발 경험을 크게 개선하는 데 기여합니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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