오랜 시간이 지난 뒤에도 Ruby가 여전히 집처럼 느껴지는 이유
1 week ago
5
- Ruby는 가장 빠르거나 유행하는 언어는 아니지만, 15년 넘게 여러 언어를 거친 뒤에도 일을 즐기고 싶을 때 다시 선택되는 언어로 남아 있음
- refinements, Forwardable, SimpleDelegator, Object#then, Kernel#tap, 번호 매개변수는 작은 문법 편의와 읽기 쉬운 흐름을 제공함
- 표준 라이브러리의 Thread::Queue, json, csv와 RuboCop, Ruby LSP는 작은 gem과 복잡한 설정 없이도 실용적인 개발 환경을 유지하게 해 줌
- Ruby 3.x의 YJIT와 4.x의 ZJIT는 CPU 집약 작업 격차를 줄이고 있으며, 간단한 Fibonacci 비교에서 Ruby with ZJIT가 Go의 2~3배 이내였음
- Rust·Go·Python이 더 적합한 영역도 있지만, 웹 앱·백그라운드 처리·내부 도구에서는 개발자 행복과 빠른 반복 속도가 Ruby의 강점으로 남아 있음
Ruby가 편하게 느껴지는 언어적 이유
- Ruby는 가장 빠르거나 가장 유행하는 언어는 아니지만, 15년 넘게 여러 언어를 오간 뒤에도 실제로 일을 즐기고 싶을 때 다시 선택하게 되는 언어로 남아 있음
- refinements는 제한된 범위에서만 클래스를 열 수 있게 해, 전체 네임스페이스를 오염시키지 않고 파일이나 블록 안에 작은 문법 편의를 추가할 수 있음
- 테스트 헬퍼나 큰 코드베이스의 내부 DSL에 잘 맞음
- using QuotingRefinement를 호출한 위치에서만 "hello".quote 같은 메서드를 사용할 수 있음
- 표준 라이브러리의 Forwardable과 SimpleDelegator는 래퍼 메서드를 직접 쓰거나 추가 gem을 끌어오지 않고도 깔끔한 위임을 가능하게 해 줌
- Rails를 이미 쓰는 경우 Active Support의 delegate가 더 편할 수 있지만, 핵심 Ruby 버전은 일반 스크립트를 가볍게 유지해 줌
- Object#then과 Kernel#tap은 중간 변수를 만들지 않고도 작업을 위에서 아래로 읽히는 체인으로 연결하게 해 줌
- User.new(params).tap { ... }.then { ... }.save처럼 생성, 로깅, 정규화, 저장 흐름을 이어 쓸 수 있음
- Ruby 2.7 이후의 번호 매개변수는 짧은 콜백에서 잡음을 줄여 줌
- items.map { _1.price * 1.1 }처럼 블록 인자를 명시하지 않아도 됨
- fiber scheduler는 이벤트 루프를 연결했을 때 순차 코드처럼 보이는 동시성 코드를 작성할 수 있게 해 줌
- Fiber.schedule do ... end 형태로 다른 fiber와 협력하는 코드를 표현함
도구, 성능, 생태계의 현재 모습
- Shopify의 Ruby LSP는 최소 설정으로 에디터 통합을 제공하며, 점진적 타입 적용을 위한 Steep이나 RBS와 함께 잘 동작함
- RuboCop은 다른 생태계에서 보이는 의식적인 절차 없이도 스타일을 일관되게 유지하게 해 줌
- 표준 라이브러리는 흔한 작업을 위해 여러 작은 gem을 추가하지 않아도 되는 조용한 강점으로 남아 있음
- 큐가 필요하면 Thread::Queue를 사용할 수 있음
- JSON이나 CSV 파싱은 json과 csv 라이브러리가 대부분의 실제 사용 사례를 큰 절차 없이 처리해 줌
- Ruby 3.x의 YJIT에 이어 4.x 시리즈에는 ZJIT가 들어오고 있음
- ZJIT는 같은 기반 위에서 더 공격적으로 동작하는 JIT이며, 더 뜨거운 실행 경로를 효과적으로 컴파일함
- 초기 수치상 CPU 집약 작업에서 Ruby와 큰 격차를 보이던 언어들과의 차이가 의미 있게 줄어듦
- CRuby ZJIT는 Ruby 메인 저장소에서 개발되고 있음
- 같은 머신에서 재귀 Fibonacci 구현을 비교한 간단한 벤치마크에서는 Ruby with ZJIT가 Go의 2~3배 이내였고, 해당 사례에서 최적화된 Rust와도 크게 떨어지지 않았으며, Python with pypy는 뒤처졌음
- 마이크로벤치마크에는 한계가 있지만, JIT가 최적화할 시간이 생긴 따뜻한 코드 경로에서는 실제 애플리케이션도 더 큰 이득을 볼 수 있음
- Rust와 비교하면 Ruby는 비즈니스 로직의 반복 속도에서 강점이 있음
- Rust에서는 런타임에는 명확한 일에도 borrow checker와 씨름하는 시간이 생길 수 있음
- Go는 동시성 기본 요소가 뛰어나지만, 최근까지 generics가 없었고 다소 경직된 오류 처리 때문에 간단한 스크립트가 필요 이상으로 무거워질 수 있음
- Python은 가장 가까운 정신적 사촌이지만, 특히 클래스와 데코레이터 주변에서 같은 고수준 아이디어를 표현하는 데 더 많은 보일러플레이트가 필요함
- 모델에 코드를 넣을 때 토큰 효율성도 Ruby의 실제 장점으로 작동함
- do/end나 중괄호로 블록을 표현하고, 가독성이 허용되면 메서드 호출에 괄호가 거의 필요 없음
- 해시와 키워드 인자가 일급 기능이며 간결해, 구조적 잡음이 많은 언어보다 같은 컨텍스트 창에 더 많은 실제 로직을 넣을 수 있음
- Ruby의 메타프로그래밍 유틸리티는 작고 읽기 쉬운 API를 만들기 좋음
- define_method, class_eval, missing method 가로채기 같은 기능으로 코드 생성 단계 없이 표현력 있는 API를 만들 수 있음
- dry-rb나 aasm 같은 라이브러리는 이 기능을 절제해서 사용해 깔끔한 상태 머신과 검증 계층을 제공함
- 커뮤니티 도구와 배포 흐름도 성숙해졌음
- byebug와 pry는 다른 곳에서 써 본 많은 디버거보다 더 유연하게 느껴짐
- 백그라운드 작업에서는 solid_queue와 good_job이 단순해, 구현 전체를 한 오후에 이해할 수 있을 정도로 접근 가능함
- Kamal은 많은 사람에게 오래된 capistrano식 절차를 대체했으며, 실제로 작은 팀을 운영하는 사람들이 만든 도구처럼 느껴짐
- Ruby가 모든 작업에서 Rust나 Go를 이긴다는 뜻은 아니며, Rust나 Go가 더 적합한 영역도 있음
- 웹 애플리케이션, 백그라운드 처리, 내부 도구라는 넓은 중간 영역에서는 Ruby가 과도한 의식이나 잦은 컨텍스트 전환 없이 개발자 행복을 계속 제공함
- 작은 편의와 언어의 전체적인 감각은 10년이 넘은 뒤에도 먼저 손이 가게 만드는 요소로 남아 있으며, 새로운 JIT 작업과 꾸준한 언어 개선이 그 이유를 더 강화함
-
Homepage
-
개발자
- 오랜 시간이 지난 뒤에도 Ruby가 여전히 집처럼 느껴지는 이유