Ruby는 매년 크리스마스에 새 버전을 출시하는 전통이 있습니다.
이번 글에서는 Ruby 2.4에서 가장 흥미로운 변경 사항들을 소개해 드리겠습니다. 최신 소식을 놓치지 마세요! 🙂
1. 키워드 인수를 지원하는 Float#round
애플리케이션에서 부동소수점(float)을 다룬다면 반올림 시 floor나 ceil을 사용하고 계셨기를 바랍니다. Ruby 2.4에서 Float#round 메서드의 기본 동작이 변경되었기 때문입니다.
예시:
# Ruby 2.3 (2.5).round 3 # Ruby 2.4 (2.5).round 2
새 기본 동작은 "가장 가까운 짝수로 반올림(round-to-nearest-even)" 방식입니다.
업데이트: 이 글 발행 이후 Matz의 결정에 따라, Ruby 2.4 정식 버전에서는
Float#round의 기본 동작이 다시 "올림 반올림"으로 되돌아갔습니다.
또한 Float#round는 이제 인수를 받아 원하는 반올림 방식을 지정할 수 있습니다.
사용 가능한 옵션은 다음과 같습니다:
- :even (짝수 방향)
- :up (올림)
- :down (내림)
예시:
(4.5).round(half: :up) 5
그리고 Float#floor, Float#ceil, Float#truncate도 이제 선택적 인수를 받아 소수점 자릿수(precision)를 지정할 수 있게 되었습니다.
2. IO 메서드의 chomp 플래그
gets나 each_line 같은 메서드를 사용해 본 적이 있다면, 성가신 개행 문자를 처리해야 했던 경험이 있으실 겁니다.
바로 \n처럼 생긴 그 문자들 말입니다.
초보자들이 늘 어려워하는 부분인데, 이번 새 기능이 도움이 될 수 있습니다!
다음 예시를 보세요:
input = gets.chomp # "abc\n"
Ruby 2.4부터는 chomp 키워드 인수를 설정하면 gets가 자동으로 개행 문자를 제거해 줍니다.
예시:
input = gets(chomp: true) # "abc"
Ruby에서 유일한 "거짓(falsy)" 값인 false와 nil이 아닌 모든 값에 대해 작동합니다.
따라서 아래 코드도 동작합니다 (다만 혼란을 줄 수 있어 권장하지 않습니다):
input = gets(chomp: 1234) # "abc"
대단한 기능은 아니지만, 메서드 호출 한 번을 절약해 준다는 점에서 유용합니다 🙂
3. Pathname#empty?
Ruby 2.4에는 Dir#empty?와 File#empty?가 구현되었습니다. 디렉터리나 파일이 비어 있는지 확인할 수 있는 메서드입니다 (당연한 설명이죠?).
그런데 최근에는 Pathname#empty?도 추가되었습니다.
Pathname을 처음 들어보셨다면 간단히 설명하자면, Dir 클래스와 File 클래스의 기능을 하나로 통합한 클래스입니다.
게다가 문자열 대신 Pathname 객체를 반환하기 때문에 더 "객체지향적(OO)"이라고 할 수 있습니다.
예시:
Pathname.empty?("file or directory name")
커밋: https://github.com/ruby/ruby/commit/9373c5efb993dd8cae0526118805449b19af2c22
4. Set의 compare_by_identity
Set은 표준 라이브러리에서 제공되는 자료구조로, 고유한 요소들의 컬렉션을 관리하는 데 유용합니다.
기본적으로 객체들은 값(value)을 기준으로 비교됩니다. 더 정확히는 해시(hash) 값을 기준으로 비교됩니다.
하지만 Ruby 2.4부터는 객체 ID(object id)를 기준으로 고유한 객체 집합을 만들 수도 있습니다.
예시:
require 'set' # 일반 Set set = Set.new set << 123 << 123 << "abc" << "abc" # [123, "abc"] # Identity Set set = Set.new().compare_by_identity set << 123 << 123 << "abc" << "abc" # [123, "abc", "abc"]
이 기능의 재미있는 활용 사례를 알고 계시다면 댓글로 공유해 주세요 🙂
커밋: https://github.com/ruby/ruby/commit/76977611dd68e384fdce8c546efda5e1931e67a6
5. Kernel#send, BasicObject#__send__, Symbol#to_proc에서 사용 가능한 Refinements
여기서 리파인먼트(refinements)를 자세히 다루지는 않겠지만, 기본 개념은 String 같은 클래스에 메서드를 추가하면서도 그 변경을 특정 파일이나 클래스 범위로 "국소화(localized)"할 수 있다는 것입니다.
Ruby 2.4부터는 리파인먼트로 정의된 메서드를 Kernel#send나 Symbol#to_proc 같은 메서드를 통해 호출할 때도 사용할 수 있게 되었습니다.
예시:
module TenTimes
refine String do
def ten_times
puts self * 10
end
end
end
class Thing
using TenTimes
"abc".send(:ten_times)
end
Ruby 2.3 이하 버전에서 실행하면 'undefined method' 오류가 발생합니다.
커밋: https://github.com/ruby/ruby/commit/35a29390197750abf97ef16fa0740e377764daef
6. Hash#transform_values
Rails에서 추출되어 Ruby 본체에 직접 편입된 또 하나의 메서드입니다. 바로 Hash#transform_values인데, Array#map과 유사하게 동작합니다.
예시:
h = {a: 1, b: 2, c: 3}
h.transform_values { |v| v * 10 }
# {a: 10, b: 20, c: 30}
원본 해시를 직접 변경(in-place mutation)해야 한다면 Hash#transform_values!도 사용할 수 있습니다.
7. 키워드 인수를 지원하는 Kernel#clone
Ruby 객체의 복사본을 만들 수 있다는 것은 잘 알고 계실 겁니다. 대부분의 Ruby 객체는 변경 가능(mutable)하기 때문에, 원본 객체를 보존하고 싶을 때 유용합니다.
객체 복사를 위한 메서드는 두 가지입니다:
- clone
- dup
clone과 dup 사이에는 몇 가지 미세한 차이가 있는데, 이 글에서는 clone은 원본 객체의 "frozen(동결)" 상태를 유지하지만 dup은 그렇지 않다는 점만 언급하겠습니다.
2.4의 새로운 기능은 clone 호출 시 "freeze" 플래그를 지정할 수 있다는 점입니다.
예시:
foo = "test".freeze boo = foo.clone(freeze: false) boo.frozen? # false
이것이 실제로 어느 정도 유용할지는 확실치 않지만, 선택지가 많으면 나쁠 건 없겠죠 🙂
커밋: https://github.com/ruby/ruby/commit/320ae01c5fb091eab0926c186f304a9caeda1ace
8. Thread.report_on_exception
2.4에 추가된 또 다른 기능은 Thread.report_on_exception입니다. 스레드(Thread)의 예외는 기본적으로 조용히 무시되기 때문에 코드의 문제를 숨길 수 있다는 점이 문제 제기되었습니다.
기본값은 false이지만, 애플리케이션에서 스레드를 사용한다면 Ruby 2.4로 업그레이드할 때 이 옵션을 활성화해 보는 것이 좋습니다.
예시:
Thread.report_on_exception = true t1 = Thread.new do puts "In new thread" raise "Exception from thread" end sleep(1) puts "In the main thread"
이렇게 하면 예외가 출력되지만 프로그램이 중단되지는 않습니다. 프로그램을 강제 종료시키고 싶다면, 예전부터 제공되던 Thread.abort_on_exception을 사용하면 됩니다.
참고로 이 메서드에는 인스턴스 버전도 있어서, 모든 스레드가 아닌 특정 스레드에만 개별적으로 옵션을 설정할 수도 있습니다.
9. Binding#irb
디버깅할 때 binding.pry를 즐겨 사용하시나요? 이제 비슷한 방식으로 동작하는 binding.irb도 사용할 수 있습니다.
다만 irb 기반이기 때문에 pry가 제공하는 문법 강조(syntax highlighting) 같은 편리한 기능은 여전히 사용할 수 없습니다.
어떤 이유로든 pry를 사용할 수 없는 상황이라면, 없는 것보다는 낫겠죠 🙂
커밋: https://github.com/ruby/ruby/commit/493e48897421d176a8faf0f0820323d79ecdf94a
마무리
이번 Ruby 2.4는 흥미로운 기능들을 많이 담고 있습니다. 출시되면 꼭 확인해 보시기 바랍니다.
더 많은 사람들이 Ruby 2.4의 새로운 기능을 배울 수 있도록 이 글을 공유해 주시는 것도 잊지 마세요!