Ruby의 전통대로 핵심 개발팀이 2024년 12월 25일, Ruby 3.4를 정식 출시했습니다! Ruby를 사랑하는 개발자라면 이번 버전에서 무엇이 달라졌는지 궁금하실 텐데요. 이번 릴리스에는 대격변 같은 변화는 없지만, 놓치면 아까운 꽤 멋진 기능들이 여럿 포함되어 있습니다.
가장 먼저 언어 자체의 변화부터 살펴보겠습니다.
언어 변경 사항
언어 변경 사항은 대부분의 Ruby 개발자에게 가장 직접적으로 영향을 미치는 부분입니다. 하나씩 빠르게 짚어 보겠습니다.
기본 적용되는 문자열 리터럴 동결(Frozen String Literal)
Ruby를 조금만 다뤄본 분이라면 파일 맨 위에 이런 코드가 있는 것을 본 적이 있을 겁니다.
# frozen_string_literal: true
위 예제는 매직 코멘트(magic comment)로, Ruby 인터프리터에 실제 의미를 전달하는 특별한 주석입니다. 이 코멘트가 있으면 인터프리터는 해당 파일 내 모든 문자열에 freeze가 호출된 것처럼 취급합니다. 동결된 문자열을 수정하려고 하면 런타임 오류가 발생하죠.
Ruby 3.4부터는 문자열이 기본적으로 동결된 것처럼 동작합니다. 다만 문자열 변경 시도 시 즉시 오류 대신 폐기 예정(deprecation) 경고가 출력됩니다. 향후 버전에서는 기본 동결이 강제되어, 문자열을 변경하려고 하면 예외가 발생하게 됩니다. 이러한 과도기를 통해 Ruby 개발자들은 애플리케이션을 충분히 마이그레이션할 시간을 벌 수 있습니다.
블록 매개변수의 새 문법: it
Ruby 3.4는 짧은 코드 블록을 더 깔끔하게 작성할 수 있는 기본 블록 매개변수를 도입했습니다.
Ruby 2.7 이전에는 each 메서드로 배열의 각 요소를 출력하려면 다음과 같이 작성해야 했습니다.
[1, 2, 3].each { |item| puts item }
Ruby 2.7은 번호 매개변수(numbered parameters)를 도입해 매개변수 이름 지정을 생략할 수 있게 했습니다. 이후에는 같은 코드를 이렇게 줄여 쓸 수 있었죠.
[1, 2, 3].each { puts _1 }
다만 Ruby 2.7 방식은 더 간결하지만, 이 문법에 익숙하지 않은 개발자에게는 직관적이지 않다는 단점이 있었습니다. 그리고 Ruby 3.4는 이를 해결하는 더 나은 방식을 선보입니다.
[1, 2, 3].each { puts it }
블록 매개변수를 따로 선언하지 않아도 it으로 바로 참조할 수 있어, 가독성과 간결함을 모두 잡았습니다.
nil 키워드 스플랫(**)
Ruby 3.4 이전 버전에서는 더블 스플랫 연산자(**)를 nil에 사용하면 TypeError가 발생했습니다. nil은 암묵적으로 해시로 변환될 수 없기 때문인데, 나름 일관성 있는 동작이긴 했습니다.
Ruby 3.4에서는 이 동작이 단순해졌습니다. nil을 암묵적으로 빈 해시로 변환하기 때문에, nil에 **를 사용하는 것은 빈 해시에 사용하는 것과 동일하게 처리됩니다.
핵심 클래스 업데이트
핵심 클래스 업데이트는 언어 변경 사항만큼 즉각적으로 와닿지는 않지만, 알아두면 분명히 유용합니다!
Exception#set_backtrace
Ruby 이슈 트래커에는 Ruby 3.4 이전에 문자열 배열로 백트레이스를 설정하는 것이 "정보 손실(lossy)" 방식이라는 기능 요청이 있었습니다. 실제로 이전에는 #backtrace_locations가 nil을 반환하는 문제가 있었습니다.
Ruby 3.4에서는 Exception#set_backtrace가 Thread::Backtrace::Location 배열을 받을 수 있게 되어, Backtrace 인스턴스를 재구성하고 완전한 기능을 갖춘 Exception 객체를 만들 수 있습니다.
Range#size
Range#size도 Ruby 3.4에서 새로운 동작을 갖게 되었습니다. 반복(iteration)이 불가능한 범위에 size를 호출하면 이제 TypeError가 발생합니다. 극히 일부 범위 객체에서 size를 호출할 때만 체감되는 작은 변화입니다.
Ruby 3.4의 기타 변경 사항
Ruby 3.4에는 또 한 가지 사소한 변화가 있습니다. 블록을 전달받지만 실제로 사용하지 않는 메서드에 블록을 넘길 때, verbose 모드에서 경고가 출력됩니다.
또한 구현 재작성 덕분에 Array.each의 성능이 개선된 점도 반가운 소식입니다!
마지막으로 오류 메시지와 백트레이스 표시 방식도 개선되었습니다. 관련 상황에서는 백틱(`) 대신 작은따옴표(')를 사용하고, 메서드 이름 앞에 클래스 이름을 함께 표시해 디버깅 가독성을 높였습니다.
Ruby 3.4로 업그레이드하기
대부분의 프로젝트에서 Ruby 3.4 업그레이드는 크게 어렵지 않을 것입니다. 가장 손이 많이 가는 작업은 더 이상 필요 없는 frozen string 매직 코멘트를 제거하는 정도겠죠. Ruby 3.4의 새로운 기능들을 활용하려면 업그레이드에 투자하는 시간이 분명 결실로 돌아올 것입니다. 미루지 말고 지금 바로 시작해 보세요!
그리고 이런 유용한 Ruby 소식과 튜토리얼을 받아보고 싶다면 Honeybadger 뉴스레터 구독을 잊지 마세요!