|
| 1 | +--- |
| 2 | +layout: news_post |
| 3 | +title: "루비 2.7.0-preview3 릴리스" |
| 4 | +author: "naruse" |
| 5 | +translator: "shia" |
| 6 | +date: 2019-11-23 12:00:00 +0000 |
| 7 | +lang: ko |
| 8 | +--- |
| 9 | + |
| 10 | +루비 2.7.0-preview3 릴리스를 알리게 되어 기쁩니다. |
| 11 | + |
| 12 | +프리뷰 버전은 12월에 예정된 최종 릴리스에 대한 의견을 모으기 위해서 릴리스됩니다. |
| 13 | +preview3 은 키워드 인자의 호환성 문제를 확인하기 위해서 릴리스됩니다. |
| 14 | + |
| 15 | +이는 많은 새 기능과 성능 향상을 포함하고 있습니다. 특히 눈에 띄는 것은 다음과 같습니다. |
| 16 | + |
| 17 | +* 압축 GC |
| 18 | +* 패턴 매칭 |
| 19 | +* REPL 개선 |
| 20 | +* 위치 인자와 키워드 인자 분리 |
| 21 | + |
| 22 | +## 압축 GC |
| 23 | + |
| 24 | +이 릴리스는 단편화된 메모리를 최적화할 수 있는 압축 GC를 도입합니다. |
| 25 | + |
| 26 | +몇몇 멀티 스레드를 이용하는 루비 프로그램은 메모리 단편화를 일으킬 수 있고, |
| 27 | +이는 과다한 메모리 사용과 성능 저하로 이어질 수 있습니다. |
| 28 | + |
| 29 | +힙 공간을 압축하는 `GC.compact` 메서드가 도입되었습니다. |
| 30 | +이 함수는 더 적은 페이지를 사용하고, 힙이 CoW(Copy on Write)에 유리하도록 |
| 31 | +힙 내부에 살아있는 객체들을 압축합니다. |
| 32 | +[[Feature #15626]](https://bugs.ruby-lang.org/issues/15626) |
| 33 | + |
| 34 | +## 패턴 매칭 [실험적] |
| 35 | + |
| 36 | +함수형 언어에서 널리 사용되는 패턴 매칭 기능이 실험적으로 도입되었습니다. |
| 37 | +[[Feature #14912]](https://bugs.ruby-lang.org/issues/14912) |
| 38 | + |
| 39 | +이는 주어진 객체를 순회하다가 패턴이 일치하는 경우 그 값을 대입합니다. |
| 40 | + |
| 41 | +{% highlight ruby %} |
| 42 | +require "json" |
| 43 | + |
| 44 | +json = <<END |
| 45 | +{ |
| 46 | + "name": "Alice", |
| 47 | + "age": 30, |
| 48 | + "children": [{ "name": "Bob", "age": 2 }] |
| 49 | +} |
| 50 | +END |
| 51 | + |
| 52 | +case JSON.parse(json, symbolize_names: true) |
| 53 | +in {name: "Alice", children: [{name: "Bob", age: age}]} |
| 54 | + p age #=> 2 |
| 55 | +end |
| 56 | +{% endhighlight %} |
| 57 | + |
| 58 | +더 자세한 설명은 [Pattern matching - New feature in Ruby 2.7](https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7)을 확인해 주세요. |
| 59 | + |
| 60 | +## REPL 개선 |
| 61 | + |
| 62 | +루비에 포함되어 있는 상호작용 환경(REPL; Read-Eval-Print-Loop)인 `irb`가 |
| 63 | +이제 여러 줄 편집을 지원합니다. |
| 64 | +이는 `readline`과 호환되는 순수 루비 구현인 `reline`으로 동작합니다. |
| 65 | +또한 rdoc 통합도 제공됩니다. `irb`에서 주어진 클래스, 모듈, 메서드의 레퍼런스를 볼 수 있습니다. |
| 66 | +[[Feature #14683]](https://bugs.ruby-lang.org/issues/14683), |
| 67 | +[[Feature #14787]](https://bugs.ruby-lang.org/issues/14787), |
| 68 | +[[Feature #14918]](https://bugs.ruby-lang.org/issues/14918) |
| 69 | + |
| 70 | +그뿐만 아니라, `binding.irb`에서 보이는 소스 코드나 코어 클래스 객체의 |
| 71 | +inspect 결과에 색이 추가되었습니다. |
| 72 | + |
| 73 | +<video autoplay="autoplay" controls="controls" muted="muted" width="576" height="259"> |
| 74 | + <source src="https://cache.ruby-lang.org/pub/media/irb_improved_with_key_take2.mp4" type="video/mp4"> |
| 75 | +</video> |
| 76 | + |
| 77 | +## 위치 인자와 키워드 인자 분리 |
| 78 | + |
| 79 | +키워드 인자와 위치 인자의 자동 변환이 폐기 예정 상태가 되었습니다. |
| 80 | +이 변환은 루비 3에서 제거될 예정입니다. |
| 81 | +[[Feature #14183]](https://bugs.ruby-lang.org/issues/14183) |
| 82 | + |
| 83 | +* 메서드 호출이 마지막 인자로 Hash를 넘기며 아무 키워드도 넘기지 않을때, |
| 84 | + 호출된 메서드는 키워드를 받을 때 경고가 발생합니다. |
| 85 | + 계속 키워드로 취급되도록 하려면, 이중 스플랫(double splat) 연산자를 추가해서 |
| 86 | + 경고를 피하고 루비 3에서 올바르게 동작하도록 하세요. |
| 87 | + |
| 88 | + {% highlight ruby %} |
| 89 | + def foo(key: 42); end; foo({key: 42}) # warned |
| 90 | + def foo(**kw); end; foo({key: 42}) # warned |
| 91 | + def foo(key: 42); end; foo(**{key: 42}) # OK |
| 92 | + def foo(**kw); end; foo(**{key: 42}) # OK |
| 93 | + {% endhighlight %} |
| 94 | + |
| 95 | +* 메서드 호출이 키워드를 넘기고 호출된 메서드도 키워드를 받을 때, |
| 96 | + 필요한 위치 인자가 부족한 경우 키워드들을 마지막 위치 인자로 간주하고 경고가 발생합니다. |
| 97 | + 경고를 피하고 루비 3에서 올바르게 동작하도록 하려면 인자를 키워드 대신 해시로 넘기세요. |
| 98 | + |
| 99 | + {% highlight ruby %} |
| 100 | + def foo(h, **kw); end; foo(key: 42) # warned |
| 101 | + def foo(h, key: 42); end; foo(key: 42) # warned |
| 102 | + def foo(h, **kw); end; foo({key: 42}) # OK |
| 103 | + def foo(h, key: 42); end; foo({key: 42}) # OK |
| 104 | + {% endhighlight %} |
| 105 | + |
| 106 | +* 메서드가 키워드 스플랫(splat)은 받지 않고 특정 키워드는 받을 때, |
| 107 | + 심볼과 심볼이 아닌 키를 모두 포함한 해시 또는 키워드 스플랫을 |
| 108 | + 메서드에 넘긴 경우 경고가 발생합니다. |
| 109 | + 루비 3에서 올바르게 동작하려면 메서드를 호출하는 코드가 별도의 해시를 넘기도록 |
| 110 | + 수정해야 합니다. |
| 111 | + |
| 112 | + {% highlight ruby %} |
| 113 | + def foo(h={}, key: 42); end; foo("key" => 43, key: 42) # warned |
| 114 | + def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned |
| 115 | + def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK |
| 116 | + {% endhighlight %} |
| 117 | + |
| 118 | +* 메서드가 키워드를 받지 않는데 키워드와 함께 호출되면, |
| 119 | + 키워드는 위치 인자에 해당하는 해시로 인식되고, 경고가 발생하지 않습니다. |
| 120 | + 이 동작은 루비 3에서도 유지될 것입니다. |
| 121 | + |
| 122 | + {% highlight ruby %} |
| 123 | + def foo(opt={}); end; foo( key: 42 ) # OK |
| 124 | + {% endhighlight %} |
| 125 | + |
| 126 | +* 메서드가 임의의 키워드를 받으면 심볼이 아닌 키도 키워드 인자로 허용됩니다. |
| 127 | + [[Feature #14183]](https://bugs.ruby-lang.org/issues/14183) |
| 128 | + |
| 129 | + {% highlight ruby %} |
| 130 | + def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1} |
| 131 | + {% endhighlight %} |
| 132 | + |
| 133 | +* 메서드가 키워드를 받지 않음을 명시하기 위해 메서드 정의에서 `**nil`을 사용할 수 있습니다. |
| 134 | + 이러한 메서드를 키워드와 함께 호출하면 ArgumentError가 발생합니다. |
| 135 | + [[Feature #14183]](https://bugs.ruby-lang.org/issues/14183) |
| 136 | + |
| 137 | + {% highlight ruby %} |
| 138 | + def foo(h, **nil); end; foo(key: 1) # ArgumentError |
| 139 | + def foo(h, **nil); end; foo(**{key: 1}) # ArgumentError |
| 140 | + def foo(h, **nil); end; foo("str" => 1) # ArgumentError |
| 141 | + def foo(h, **nil); end; foo({key: 1}) # OK |
| 142 | + def foo(h, **nil); end; foo({"str" => 1}) # OK |
| 143 | + {% endhighlight %} |
| 144 | + |
| 145 | +* 키워드를 받지 않는 메서드에 빈 키워드 스플랫을 넘겼을 때, 더 이상 빈 해시를 넘기지 않습니다. |
| 146 | + 파라미터가 필요한 경우 빈 해시를 넘기지만, 경고가 발생합니다. |
| 147 | + 위치 인자로서 해시를 넘기려면 이중 스플랫(double splat)을 제거하세요. |
| 148 | + [[Feature #14183]](https://bugs.ruby-lang.org/issues/14183) |
| 149 | + |
| 150 | + {% highlight ruby %} |
| 151 | + h = {}; def foo(*a) a end; foo(**h) # [] |
| 152 | + h = {}; def foo(a) a end; foo(**h) # {} and warning |
| 153 | + h = {}; def foo(*a) a end; foo(h) # [{}] |
| 154 | + h = {}; def foo(a) a end; foo(h) # {} |
| 155 | + {% endhighlight %} |
| 156 | + |
| 157 | +NOTE: 키워드 인자 비호환으로 인한 너무 많은 폐기 경고가 번잡하다는 의견이 있습니다. |
| 158 | +현재 두 가지 해결책을 의논중입니다. 하나는 기본 설정을 폐기 경고를 비활성화하는 |
| 159 | +것([#16345](https://bugs.ruby-lang.org/issues/16345))과 중복되는 경고의 출력을 |
| 160 | +생략하는 것([#16289](https://bugs.ruby-lang.org/issues/16289))입니다. |
| 161 | +아직 결정이 나지 않았습니다만, 공식 릴리스 이전에 정해질 것입니다. |
| 162 | + |
| 163 | +## 이외의 주목할 만한 새 기능 |
| 164 | + |
| 165 | +* 메서드 참조 연산자 `.:`가 이전 프리뷰에서 실험적으로 도입되었지만 취소되었습니다. |
| 166 | + [[Feature #12125]](https://bugs.ruby-lang.org/issues/12125), |
| 167 | + [[Feature #13581]]( https://bugs.ruby-lang.org/issues/13581), |
| 168 | + [[Feature #16275]](https://bugs.ruby-lang.org/issues/16275) |
| 169 | + |
| 170 | +* 번호 지정 파라미터가 기본 블록 파라미터로서 실험적으로 도입되었습니다. |
| 171 | + [[Feature #4475]](https://bugs.ruby-lang.org/issues/4475) |
| 172 | + |
| 173 | +* 시작 값을 지정하지 않는 범위 연산자가 실험적으로 추가됩니다. |
| 174 | + 종료 지정이 없는 범위 연산자처럼 유용하지 않을 수도 있습니다만, DSL 용도로는 유용할 것입니다. |
| 175 | + [[Feature #14799]](https://bugs.ruby-lang.org/issues/14799) |
| 176 | + |
| 177 | + {% highlight ruby %} |
| 178 | + ary[..3] # identical to ary[0..3] |
| 179 | + rel.where(sales: ..100) |
| 180 | + {% endhighlight %} |
| 181 | + |
| 182 | +* `Enumerable#tally`가 추가됩니다. 이는 각 요소가 몇 번 출현했는지를 셉니다. |
| 183 | + |
| 184 | + {% highlight ruby %} |
| 185 | + ["a", "b", "c", "b"].tally |
| 186 | + #=> {"a"=>1, "b"=>2, "c"=>1} |
| 187 | + {% endhighlight %} |
| 188 | + |
| 189 | +* `self`에 private 메서드를 호출하는 것이 허용됩니다. |
| 190 | + [[Feature #11297]](https://bugs.ruby-lang.org/issues/11297), |
| 191 | + [[Feature #16123]](https://bugs.ruby-lang.org/issues/16123) |
| 192 | + |
| 193 | + {% highlight ruby %} |
| 194 | + def foo |
| 195 | + end |
| 196 | + private :foo |
| 197 | + self.foo |
| 198 | + {% endhighlight %} |
| 199 | + |
| 200 | +* `Enumerator::Lazy#eager`가 추가됩니다. |
| 201 | + 지연 열거자(lazy enumerator)에서 지연 없는 열거자를 생성합니다. |
| 202 | + [[Feature #15901]](https://bugs.ruby-lang.org/issues/15901) |
| 203 | + |
| 204 | + {% highlight ruby %} |
| 205 | + a = %w(foo bar baz) |
| 206 | + e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager |
| 207 | + p e.class #=> Enumerator |
| 208 | + p e.map {|x| x + "?" } #=> ["FOO!?", "BAR!?", "BAZ!?"] |
| 209 | + {% endhighlight %} |
| 210 | + |
| 211 | +## 성능 향상 |
| 212 | + |
| 213 | +* JIT [실험적] |
| 214 | + |
| 215 | + * 최적화 가정이 유효하지 않은 경우 JIT으로 컴파일된 코드는 최적화 레벨이 낮은 |
| 216 | + 코드로 재컴파일됩니다. |
| 217 | + |
| 218 | + * 순수하다고 판단된 메서드를 인라인으로 삽입하게 됩니다. |
| 219 | + 이 최적화는 아직 실험적이며 많은 메서드는 아직 순수하다고 판단되지 않는 상태입니다. |
| 220 | + |
| 221 | + * `--jit-min-calls`의 기본값이 5에서 10,000으로 변경됩니다. |
| 222 | + |
| 223 | + * `--jit-max-cache`의 기본값이 1,000에서 100으로 변경됩니다. |
| 224 | + |
| 225 | +* ~~`Symbol#to_s`, `Module#name`, `true.to_s`, `false.to_s`, `nil.to_s`가 이제 항상 얼린 문자열을 반환합니다. |
| 226 | + 주어진 객체에 대해 항상 동일한 문자열이 반환됩니다. [실험적] |
| 227 | + [[Feature #16150]](https://bugs.ruby-lang.org/issues/16150)~~ 취소되었습니다. |
| 228 | + |
| 229 | +* `CGI.escapeHTML`의 성능이 향상되었습니다. [GH-2226](https://github.com/ruby/ruby/pull/2226) |
| 230 | + |
| 231 | +* Monitor와 MonitorMixin의 성능이 향상되었습니다. |
| 232 | + [[Feature #16255]](https://bugs.ruby-lang.org/issues/16255) |
| 233 | + |
| 234 | +## 그 이외의 2.6 이후로 주목할 만한 변경 |
| 235 | + |
| 236 | +* 표준 라이브러리를 업데이트했습니다. |
| 237 | + * Bundler 2.1.0.pre.3 |
| 238 | + ([History](https://github.com/bundler/bundler/blob/2-1-stable/CHANGELOG.md#210pre3-november-8-2019)) |
| 239 | + * RubyGems 3.1.0.pre.3 |
| 240 | + ([History](https://github.com/rubygems/rubygems/blob/3.1/History.txt)) |
| 241 | + * CSV 3.1.2 |
| 242 | + ([NEWS](https://github.com/ruby/csv/blob/v3.1.2/NEWS.md)) |
| 243 | + * Racc 1.4.15 |
| 244 | + * REXML 3.2.3 |
| 245 | + ([NEWS](https://github.com/ruby/rexml/blob/v3.2.3/NEWS.md)) |
| 246 | + * RSS 0.2.8 |
| 247 | + ([NEWS](https://github.com/ruby/rss/blob/v0.2.8/NEWS.md)) |
| 248 | + * StringScanner 1.0.3 |
| 249 | + * 기존 버전이 없는 다른 몇몇 라이브러리도 업데이트되었습니다. |
| 250 | + |
| 251 | +* 표준 라이브러리가 기본 젬으로 승격됩니다. |
| 252 | + * 다음 기본 젬들이 rubygems.org 에서 배포중입니다. |
| 253 | + * benchmark |
| 254 | + * cgi |
| 255 | + * delegate |
| 256 | + * getoptlong |
| 257 | + * net-pop |
| 258 | + * net-smtp |
| 259 | + * open3 |
| 260 | + * pstore |
| 261 | + * singleton |
| 262 | + * 다음 기본 젬들은 ruby-core에서는 젬으로 승격되었지만, 아직 rubygems.org에서 배포하고 있지 않습니다. |
| 263 | + * monitor |
| 264 | + * observer |
| 265 | + * timeout |
| 266 | + * tracer |
| 267 | + * uri |
| 268 | + * yaml |
| 269 | + |
| 270 | +* 블록을 넘긴 메서드의 호출 안에서 블록이 없는 `Proc.new`와 `proc`을 사용하면 경고가 발생합니다. |
| 271 | + |
| 272 | +* 블록을 넘긴 메서드의 호출 안에서 블록이 없는 `lambda`는 에러가 발생합니다. |
| 273 | + |
| 274 | +* 유니코드와 에모지의 버전을 11.0.0에서 12.0.0으로 업데이트했습니다. |
| 275 | + [[Feature #15321]](https://bugs.ruby-lang.org/issues/15321) |
| 276 | + |
| 277 | +* 유니코드를 일본의 새로운 연호 레이와를 가리키는 코드(U+32FF SQUARE ERA NAME REIWA)에 대한 지원을 추가한 12.1.0으로 업데이트했습니다. |
| 278 | + [[Feature #15195]](https://bugs.ruby-lang.org/issues/15195) |
| 279 | + |
| 280 | +* `Date.jisx0301`, `Date#jisx0301`, `Date.parse`에서 새 일본 연호를 지원합니다. |
| 281 | + [[Feature #15742]](https://bugs.ruby-lang.org/issues/15742) |
| 282 | + |
| 283 | +* 루비 빌드에 C99를 지원하는 컴파일러를 요구합니다. |
| 284 | + [[Misc #15347]](https://bugs.ruby-lang.org/issues/15347) |
| 285 | + * 이에 대한 자세한 정보: <https://bugs.ruby-lang.org/projects/ruby-master/wiki/C99> |
| 286 | + |
| 287 | +* ~~`Regexp#match{?}`에 `nil`을 넘기면 String, Symbol에서 처럼 TypeError를 던집니다. |
| 288 | + [[Feature #13083]](https://bugs.ruby-lang.org/issues/13083)~~ 취소되었습니다. |
| 289 | + |
| 290 | +[NEWS](https://github.com/ruby/ruby/blob/v2_7_0_preview3/NEWS)나 |
| 291 | +[커밋 로그](https://github.com/ruby/ruby/compare/v2_6_0...v2_7_0_preview3)에서 |
| 292 | +더 자세한 설명을 확인할 수 있습니다. |
| 293 | + |
| 294 | +이러한 변경사항에 따라, 루비 2.6.0 이후로 [파일 3895개 수정, 213426줄 추가(+), 96934줄 삭제(-)](https://github.com/ruby/ruby/compare/v2_6_0...v2_7_0_preview3)가 이루어졌습니다! |
| 295 | + |
| 296 | +루비 2.7을 즐겨주시기 바랍니다! |
| 297 | + |
| 298 | +## 다운로드 |
| 299 | + |
| 300 | +{% assign release = site.data.releases | where: "version", "2.7.0-preview3" | first %} |
| 301 | + |
| 302 | +* <{{ release.url.bz2 }}> |
| 303 | + |
| 304 | + SIZE: {{ release.size.bz2 }} |
| 305 | + SHA1: {{ release.sha1.bz2 }} |
| 306 | + SHA256: {{ release.sha256.bz2 }} |
| 307 | + SHA512: {{ release.sha512.bz2 }} |
| 308 | + |
| 309 | +* <{{ release.url.gz }}> |
| 310 | + |
| 311 | + SIZE: {{ release.size.gz }} |
| 312 | + SHA1: {{ release.sha1.gz }} |
| 313 | + SHA256: {{ release.sha256.gz }} |
| 314 | + SHA512: {{ release.sha512.gz }} |
| 315 | + |
| 316 | +* <{{ release.url.xz }}> |
| 317 | + |
| 318 | + SIZE: {{ release.size.xz }} |
| 319 | + SHA1: {{ release.sha1.xz }} |
| 320 | + SHA256: {{ release.sha256.xz }} |
| 321 | + SHA512: {{ release.sha512.xz }} |
| 322 | + |
| 323 | +* <{{ release.url.zip }}> |
| 324 | + |
| 325 | + SIZE: {{ release.size.zip }} |
| 326 | + SHA1: {{ release.sha1.zip }} |
| 327 | + SHA256: {{ release.sha256.zip }} |
| 328 | + SHA512: {{ release.sha512.zip }} |
| 329 | + |
| 330 | +## 루비는 |
| 331 | + |
| 332 | +루비는 1993년에 Matz(마츠모토 유키히로)가 처음 개발했고, 현재는 오픈 소스로서 개발되고 있습니다. |
| 333 | +이는 여러 플랫폼에서 동작하며, 특히 웹 개발에서 전 세계적으로 이용되고 있습니다. |
0 commit comments