Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Ruby 2.6의 9가지 새로운 기능 총정리

새로운 기능과 성능 개선을 담은 Ruby의 새 버전이 곧 출시됩니다.

이번 변화들을 미리 파악해 두면 좋겠죠?

지금부터 하나씩 살펴보겠습니다!

무한 범위(Endless Range)

Ruby 2.5 이하 버전에서도 Float::INFINITY를 활용하면 일종의 무한 범위를 표현할 수 있었지만, Ruby 2.6에서는 이를 한 단계 발전시킨 새로운 문법이 도입되었습니다.

새로운 무한 범위는 다음과 같이 작성합니다:

(1..)

(1..10)처럼 끝값을 갖는 일반적인 범위와 달리, 이 표현식에는 종료 값이 없다는 점이 특징입니다.

활용 예시:

["a", "b", "c"].zip(1..)
# [["a", 1], ["b", 2], ["c", 3]]

[1,2,3,4,5][1..]
# [2, 3, 4, 5]

(1..).step(5).take(100)
# [1, 6, 11, 16, 21, 26, 31, 36, 41, 46]

여러분이라면 어떤 상황에서 활용할 수 있을까요?

ArithmeticSequence

Ruby 2.6에서는 새로운 종류의 Enumerable 객체가 도입되었습니다.

바로 Enumerator::ArithmeticSequence입니다.

현재 ArithmeticSequence를 반환하는 메서드는 두 가지입니다:

  • Range#step
  • Numeric#step

그렇다면 이 객체의 특별한 점은 무엇일까요?

ArithmeticSequence는 요소의 개수와 첫 번째 요소, 마지막 요소를 스스로 알고 있습니다.

예시:

(1..10).step(2).first
# 1

(1..10).step(2).last
# 9

이러한 first, last 메서드는 Ruby 2.6 이전에는 사용할 수 없었습니다. 그래서 ArithmeticSequence가 새롭게 등장한 것입니다!

또 다른 차이점도 있습니다:

(1..10).step(2) == (1..10).step(2)
# false - Ruby 2.5 (및 이전 버전)

(1..10).step(2) == (1..10).step(2)
# true - Ruby 2.6

Ruby 2.6에서는 산술 시퀀스끼리 서로 비교할 수 있게 되었습니다.

여러 인수로 해시 병합하기

여러 개의 해시를 하나로 합치고 싶을 때가 있습니다.

기존에는 이렇게 작성해야 했습니다:

a = { a: 1 }
b = { b: 2 }
c = { c: 3 }

a.merge(b).merge(c)
# {:a=>1, :b=>2, :c=>3}

Ruby 2.6에서는 새로운 방식이 추가되었습니다:

a.merge(b, c)
# {:a=>1, :b=>2, :c=>3}

결과는 동일하지만, 메서드 호출을 딱 한 번만 하면 됩니다!

새로운 exception 옵션

Integer 같은 형변환 메서드를 사용할 때, 값을 변환할 수 없으면 예외가 발생합니다.

예시:

Integer("a")
# ArgumentError (invalid value for Integer(): "a")

Ruby 2.6에서는 다음 메서드에 새로운 exception 키워드 인수가 추가되었습니다:

  • Integer()
  • Float()
  • Rational()
  • Complex()

이 키워드를 통해 해당 메서드들의 동작 방식을 직접 제어할 수 있습니다.

예시:

Integer("a", exception: false)
# nil

Random.bytes

랜덤 바이트가 필요하다면? Ruby 2.6에서는 Random 클래스에 새로운 bytes 메서드가 추가되었습니다.

사용 예시는 다음과 같습니다:

Random.bytes(10)
# "\xCD\r\xE6Wz\xBA)\x02\xC4\xDB"

사실 이 기능 자체는 완전히 새로운 것은 아닙니다. 예전부터 securerandom 모듈을 통해 동일한 기능을 사용할 수 있었습니다.

require 'securerandom'

SecureRandom.bytes(10)

그렇다면 굳이 새로운 메서드가 필요한 이유는 무엇일까요?

Random.bytes는 보안성을 일부 희생하는 대신 속도를 얻는 방식으로, SecureRandom보다 약 8배 빠릅니다.

Range#%

Ruby 2.6에서는 Range에 새로운 % 메서드가 추가되었습니다.

예시:

((0..) % 2).take(5)

# [0, 2, 4, 6, 8]

이 메서드는 Range#step과 동일하게 동작합니다.

TracePoint#parameters

TracePoint 클래스는 메서드 호출, 클래스 정의, 스레드 같은 이벤트를 추적하는 데 유용한 도구입니다.

Ruby 2.6에는 여기에 새로운 parameters 메서드가 추가되었습니다.

이 메서드를 사용하면 호출되는 메서드의 매개변수 목록을 출력할 수 있습니다.

예시:

TracePoint.trace(:call, :b_call, :c_call) do |tp|
  p [tp.event, tp.parameters]
end

def orange(a,b,c*)
end

orange(1,2,3)

실행 결과:

[:call, [[:req, :a], [:req, :b], [:rest, :c]]]

Transient Heap

Transient Heap은 수명이 짧은 객체를 위한 성능 개선 기능으로, 메모리 단편화 문제와 느린 malloc 호출을 줄이는 것이 목표입니다.

Malloc은 Ruby 인터프리터(그리고 대부분의 C 프로그램)가 운영체제로부터 메모리를 할당받는 방식입니다.

NEWS 항목에 따르면 약 6~7%의 속도 향상을 기대할 수 있다고 합니다.

실제로 몇 가지 벤치마크를 돌려본 결과는 다음과 같습니다:

이 기능은 요소가 10개 미만인 작은 해시를 대량으로 생성할 때 가장 효과적입니다.

Ruby 2.6의 9가지 새로운 기능 총정리

반면 위 결과를 보면, 큰 해시의 경우 Ruby 2.6(프리뷰 3)에서 오히려 느려진 것으로 나타났습니다.

Transient Heap의 혜택을 받을 수 있는 다른 객체들도 있습니다:

  • 배열(Array)
  • Struct
  • 일반 객체(직접 만든 클래스의 인스턴스)

Array#union & Array#difference

Ruby 2.6의 Array 클래스에는 uniondifference라는 두 가지 새로운 메서드가 추가되었습니다.

예시:

[1,2,3,4,5].difference([3])
# [1, 2, 4, 5]

[1,2,3,4,5].union([5,6,7])
# [1, 2, 3, 4, 5, 6, 7]

이 메서드들은 여러 개의 인수를 받을 수 있다는 점도 기억해 두세요.

마무리

Ruby 2.6은 더 적은 시간에 더 좋은 코드를 작성하는 데 도움이 되는 실용적인 새 기능들을 담고 있습니다. 또 다른 성능 관련 신기능인 MJIT(Method Based Just-in-Time Compiler)에 대해서는 별도의 글에서 자세히 다룰 예정입니다.

Ruby 2.62018년 12월 25일 출시될 예정입니다.

최신 변화를 꾸준히 따라가고, Ruby 실력을 한 단계 끌어올려 멋진 루비 개발자가 되고 싶으시다면 지금 바로 뉴스레터에 가입해 보세요.

읽어주셔서 감사합니다!