Zeitwerk는 Ruby 프로젝트에서 require
문 없이 코드를 사용할 수 있게 하는 자동 로딩(Autoloading), 코드를 미리 로드하는 즉시 로딩(Eager Loading), 그리고 코드 변경 시 자동으로 리프레시하는 리로딩(Reloading) 기능을 제공하는 필수적인 Ruby Gem입니다. 특히 Ruby on Rails 프레임워크에서 이 핵심 기능들을 담당하고 있습니다. 기존 Rails의 const_missing
기반 자동 로더는 컨텍스트 정보 부족으로 인한 문제와 require
의 전역적 부작용으로 인한 의존성 관리의 어려움을 겪었습니다. Zeitwerk는 이러한 근본적인 한계들을 해결하여 개발자가 require
관련 문제에 대한 고민 없이 효율적으로 코드를 작성하고 관리할 수 있도록 자동화된 솔루션을 제공합니다.
2019년 첫 안정 버전 출시 이후, Zeitwerk는 Shopify와 GitHub와 같은 세계 최대 규모의 Rails 애플리케이션에 성공적으로 도입되며 그 견고함과 효율성을 입증했습니다. 초기 Rails 6.0 및 6.1 버전에서는 기존 로더와 함께 제공되어 사용자들의 원활한 마이그레이션을 지원했으며, 현재는 약 600개 이상의 Gem에서 사용되고, 하루 약 50만 건의 다운로드를 기록하는 등 Ruby 생태계에 광범위하게 기여하고 있습니다. Zeitwerk의 핵심 설계 목표 중 하나는 ‘투명성’으로, 사용자 코드가 Zeitwerk의 존재를 인지할 필요 없이 일반적인 Ruby 프로젝트처럼 보이도록 설계되었습니다.
발표자는 Zeitwerk의 API 디자인 철학으로 네 가지 핵심 원칙을 강조합니다. 첫째, ‘사용성’을 최우선으로 하여 클라이언트 코드가 직관적이고 ‘옳게 보이도록’ 설계합니다. 둘째, ‘좋은 인터페이스는 사용자 실수를 디자인으로 방지’합니다. 예를 들어, Inflector API는 불필요한 정보(파일 확장자)를 제거하고 이미 알고 있는 컨텍스트(부모 디렉토리의 네임스페이스)를 활용하여 사용자에게 더 간결하고 실수할 여지가 적은 인터페이스를 제공합니다. 셋째, ‘좋은 인터페이스는 최적의 관행으로 유도’합니다. 일관된 명명 규칙(예: ‘API’의 대소문자 통일)을 따르도록 유도하는 간결한 API를 제공합니다. 넷째, ‘좋은 인터페이스는 지식 비대칭성(Knowledge Asymmetries)을 반영’합니다. 모든 사용 사례가 대칭적이지 않으므로, 일반적인 사용 사례에 대해서는 간결하고 특화된 API를 제공하여 편의성을 높입니다(예: 디버깅을 위한 loader.log!
).
또한, 발표자는 Ruby에서 ‘공개 인터페이스’의 정의가 단순히 public
가시성을 가진 메서드를 넘어선다는 점을 강조합니다. 라이브러리 내부적으로는 public
이어야 하지만 외부 사용을 의도하지 않는 메서드들이 존재하며, Zeitwerk는 internal
매크로를 통해 이러한 내부 메서드를 명확히 표시하여 사용자들이 의도치 않게 프라이빗 API를 사용하는 것을 방지합니다. 더 나아가, 소프트웨어 오류가 불가피한 것이 아니라는 메시지를 전달하며, TeX나 Elixir처럼 버그가 적거나 없는 소프트웨어가 존재함을 예시로 들고, Zeitwerk 또한 버그 보고가 거의 없음을 강조합니다. 개발자들에게 버그를 당연하게 여기지 말고, 높은 수준의 품질과 탁월함을 추구하도록 독려합니다.
Zeitwerk의 향후 주요 목표는 Ruby의 상수 해석 방식과 100% 일치하는 자동 로딩을 완벽하게 제공하는 것입니다. 현재 Zeitwerk는 TracePoint
를 활용하여 ‘명시적 네임스페이스’의 순환 참조 문제를 해결하고 있지만, Class.new
와 같은 일부 엣지 케이스에서는 여전히 한계가 있습니다. Ruby 3.2에 도입된 Module#const_added
API를 활용하면 이 마지막 엣지 케이스까지 해결하여 완벽한 자동 로더를 구현할 수 있을 것으로 예상되며, 이는 Zeitwerk 3의 핵심 목표가 될 것입니다.