Sorbet에 RBS 지원 추가

Inline RBS comments support for Sorbet

작성자
발행일
2025년 04월 23일

핵심 요약

  • 1 Shopify는 Sorbet의 강력한 타입 체크 기능을 유지하면서 가독성을 높이기 위해 RBS(Ruby Type Signature) 인라인 주석 지원을 Sorbet에 통합했습니다.
  • 2 이 통합은 기존 Sorbet의 장황한 타입 구문 문제를 해결하고, 더 간결하고 직접적인 타입 주석 방식을 제공하여 Ruby 개발 경험을 개선합니다.
  • 3 RBS 주석은 런타임 의존성 없이 메서드, 속성, 변수 및 타입 캐스팅 등 다양한 타입 정의를 지원하며, 기존 코드를 점진적으로 새로운 구문으로 마이그레이션할 수 있도록 돕는 자동화 도구도 제공됩니다.

도입

Shopify는 코드의 가독성, 이해도, 그리고 유지보수성을 크게 향상시키는 데 Sorbet을 적극적으로 활용해왔습니다. Sorbet은 Ruby 개발자들이 점진적으로 정적 타입 어노테이션을 추가할 수 있도록 지원하여, 오류를 조기에 감지하고 리팩토링을 용이하게 함으로써 코드 안정성과 신뢰성을 높이는 핵심 도구입니다. 그러나 Sorbet의 기존 타입 구문은 때때로 장황하고 코드베이스를 복잡하게 만드는 경향이 있었습니다. 이러한 문제를 해결하고 Ruby 개발 경험을 더욱 원활하고 즐겁게 만들기 위해, Shopify는 Sorbet의 강력한 타입 안전성 및 타입 체크 속도를 유지하면서 RBS(Ruby Type Signature)의 더 깔끔한 구문을 채택하여 Sorbet에 인라인 RBS 주석 지원을 추가했습니다.

Shopify는 현재 75,000개 파일 중 99%를 Sorbet으로 검사하고 있으며, 150만 메서드의 71%에 타입 시그니처를 적용하여 생산 환경에서의 오류를 크게 줄이고 있습니다. 그럼에도 불구하고 개발자 설문조사 결과, 80%의 개발자가 더 많은 코드에 타입이 지정되기를 원하고 71%가 Sorbet 기능 활용을 위해 코드베이스의 타입 지정을 지지했지만, 거의 75%의 개발자가 기존 워크플로우에 원활하게 통합될 수 있는 더 사용자 친화적이고 읽기 쉬운 구문을 요구했습니다. 기존 Sorbet은 Ruby를 DSL로 사용하여 타입 표현이 장황하고 sorbet-runtime gem으로 인한 성능 오버헤드가 있어 프로덕션 환경에서는 런타임 타입 체크를 비활성화해야 했습니다.

이러한 요구에 부응하여 Ruby 3.0에 도입된 타입 정의 언어인 RBS에 주목했습니다. RBS는 .rbs 파일을 통해 코드와 타입 정의를 분리하여 더 명확하고 간결하게 타입을 기술할 수 있습니다. 하지만 .rbs 파일의 중복 관리 문제, 로컬 변수 타입 지원 부족, 대규모 코드베이스를 위한 확장 가능한 타입 체커 부재 등의 한계가 있었습니다. 그럼에도 불구하고 Sorbet의 많은 기능이 RBS와 잘 부합했기에, 두 방식의 강점을 활용하기 위한 통합은 자연스러운 진전이었습니다.

Shopify의 목표는 Ruby 파일 내에 직접 간결한 타입 주석을 추가하는 것이었습니다. 이를 위해 Sorbet의 타입 체크 파이프라인에 새로운 단계를 도입했습니다. 이 단계에서는 RBS 주석을 찾아 관련 AST(Abstract Syntax Tree) 노드와 연결한 후, RBS 내용을 파싱하여 마치 처음부터 Ruby 파일에 작성된 것처럼 동등한 Sorbet의 sigT.let 구문을 AST 내에 직접 생성합니다. 이 과정은 Sorbet 파이프라인의 나머지 부분이 원활하게 작동하도록 보장합니다.

현재 Sorbet은 인스턴스 및 싱글톤 메서드에 대한 RBS 시그니처 주석(#:), 여러 줄에 걸쳐 작성 가능한 시그니처(#|:), 속성(attr_reader :nickname #: String?), 로컬/전역/인스턴스/클래스 변수 및 상수(local = ARGV.first #: String?)에 대한 타입 지정을 지원합니다. 이는 T.let과 동등합니다. 또한 #: as를 사용한 타입 캐스팅(name = ARGV.first #: as String)은 T.cast와, #: as !nil을 사용한 널 불가능 타입 캐스팅(name = ARGV.first #: as !nil)은 T.must와 동등합니다. 표현식 중간이나 호출 수신자에 대한 타입 단언도 가능하여 유연성을 더합니다.

결론

Sorbet의 RBS 지원은 현재 실험 단계이며, `--enable-experimental-rbs-signatures` 및 `--enable-experimental-rbs-assertions` 옵션을 통해 활성화할 수 있습니다. 대규모 코드베이스의 RBS 마이그레이션 부담을 줄이기 위해, Shopify는 기존 Sorbet 시그니처와 단언을 RBS 구문으로 쉽게 번역할 수 있는 자동화 도구(`spoom srb sigs translate`, `spoom srb assertions translate`)를 Spoom에 구축했습니다. Sorbet은 RBS 주석과 기존 `sig {}` 구문을 모두 지원하여 개발자들이 새로운 구문으로 점진적으로 마이그레이션할 수 있도록 합니다. 이 통합은 Ruby 개발자들이 더욱 효율적이고 즐겁게 코딩할 수 있도록 돕는 중요한 진전이며, Shopify의 Ruby 개발 경험 향상을 위한 지속적인 노력의 일환입니다.

댓글 0

댓글 작성

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

아직 댓글이 없습니다

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