기존 Sorbet 타입 주석 방식의 한계
2021년 Sorbet 실험은 기술적으로는 성공적이었으나, 소스 코드와 별도의 파일에 타입 주석을 관리하는 방식은 유지보수 측면에서 불편함이 있었습니다.
인라인 RBS 타입 주석 도입
2025년 초 Shopify가 Sorbet에서 RBS 스타일의 인라인 주석 지원을 발표하면서 새로운 가능성이 열렸습니다. 이 방식은 런타임 의존성 없이 코드 내부에 직접 타입 주석을 작성할 수 있게 합니다. 발표된 예시는 다음과 같습니다:
ruby
#: (Array[String]) -> String
def greet(names)
"Hello, #{names.join(", ")}!"
end
class User
#: String?
attr_reader :nickname
#: (String, String?) -> void
def initialize(name, nickname = nil)
@name = name #: String
@nickname = nickname #: String?
end
end
pdf-reader 젬 적용 결과
저자는 이 인라인 RBS 방식을 pdf-reader 젬에 적용하여 성공적인 결과를 얻었습니다. v2.15.0부터 pdf-reader는 다음 특징을 가집니다:
-
RBS 주석을 사용하여 타입 어노테이션이 코드 내부에 인라인으로 정의됩니다.
-
더 이상 RBI 파일을 저장소에 커밋하지 않습니다.
-
spoom도구를 사용하여 CI에서 동적으로 RBI 파일을 생성하고, 이를 rubygems.org에 게시되는 젬에 포함하여 다운스트림 사용자들이 Sorbet 타입 주석을 활용할 수 있도록 합니다. (명령어:spoom srb sigs export) -
모든 빌드에서 CI 중 Sorbet을 통한 타입 검사는 계속 유지됩니다.
개발자 경험 개선 및 보너스 이점
인라인 RBS 타입 주석은 루비 젬 코드베이스의 타입 어노테이션을 위한 훨씬 나은 경험을 제공했습니다. 특히, 이전에는 외부 RBI 파일 방식에서 Sorbet이 클래스 상수를 주석 처리하는 데 어려움을 겪었으나, 인라인 RBS 주석을 통해 다음과 같이 상수에 쉽게 타입 힌트를 추가할 수 있게 되었습니다:
ruby
class Buffer
TOKEN_WHITESPACE=[0x00, 0x09, 0x0A, 0x0C, 0x0D, 0x20] #: Array[Integer]
TOKEN_DELIMITER=[0x25, 0x3C, 0x3E, 0x28, 0x5B, 0x7B, 0x29, 0x5D, 0x7D] #: Array[Integer]
end
로컬 개발 환경(Helix) 및 CI에서 타입 오류가 명확하게 표시되어 개발 효율성이 향상되었습니다.
두 가지 타입 힌팅 생태계 활용
Sorbet과 RBS 두 가지 타입 힌팅 생태계를 동시에 사용하는 것이 이상하게 보일 수 있으나, pdf-reader의 특정 사용 사례에서는 모든 면에서 이점이 많았습니다. Sorbet 문서에 RBS 인라인 주석 사용 시 주의사항이 명시되어 있으나, pdf-reader의 요구사항이 크지 않아 현재까지는 문제가 발생하지 않았습니다.