Ruby 4.0.0 릴리스

작성자: naruse (2025-12-25)
번역자: Kim Dongjin

Ruby 4.0.0 릴리스를 알리게 되어 기쁩니다. Ruby 4.0은 “Ruby Box”와 “ZJIT”를 도입하고, 많은 개선을 추가합니다.

Ruby Box

Ruby Box는 정의에 대한 분리를 제공하는 새로운 (실험적) 기능입니다. Ruby Box는 환경 변수로 RUBY_BOX=1을 지정하여 활성화할 수 있습니다. 클래스 이름은 Ruby::Box입니다.

Box 내에서 로드된 정의는 해당 Box 내에 격리된 상태가 됩니다. Ruby Box가 격리할 수 있는 정의로는 기존 클래스에 대한 몽키 패치, 전역 변수나 클래스 변수 조작, 클래스나 모듈 정의, 그리고 네이티브 라이브러리나 Ruby 라이브러리가 있습니다.

Ruby Box의 주요 사용 사례는 다음과 같은 것들이 예상됩니다.

  • 테스트를 위해 특정 동작을 덮어쓰는 몽키 패치가 필요한 테스트 케이스를 Box 내에서 격리하여 실행하는 것
  • Ruby 프로세스 내의 애플리케이션 서버 상에서 웹 애플리케이션 Box를 병렬적으로 실행하여 Blue-Green 배포를 실행하는 것
  • 의존성 업데이트 시 웹 애플리케이션 Box를 병렬적으로 실행하여 일정 기간 동안 Ruby 코드를 통해 응답 시간 차이를 확인하는 것
  • (아직 미설계인) “패키지” API와 같은 새로운 고수준 API를 만들기 위한 저수준 API로서의 기능을 제공하는 것

“Ruby Box”의 자세한 내용은 다음 문서를 참조하세요. Ruby::Box. [Feature #21311] [Misc #21385]

ZJIT

ZJIT는 차세대 YJIT으로 개발된 새로운 just-in-time(JIT) 컴파일러입니다. ZJIT 지원을 포함하여 Ruby를 빌드하려면 Rust 1.85.0 이상이 필요하며, --zjit를 지정하면 ZJIT가 활성화됩니다.

우리가 Ruby를 위한 새로운 컴파일러를 개발하는 이유는 성능 상한선을 높이고(더 큰 컴파일 단위 크기와 SSA IR을 도입), 더 전통적인 메서드 컴파일러로 만들어 외부의 기여를 촉진하고 싶기 때문입니다. 자세한 내용은 블로그 게시물을 참조하세요.

ZJIT는 Ruby 인터프리터보다 빠르지만, 아직 YJIT만큼 빠르지는 않습니다. ZJIT를 시도해 보길 권장하지만, 현시점에서는 프로덕션 환경 배포는 삼가는 것이 좋을 수 있습니다. Ruby 4.1의 ZJIT를 기대해 주세요.

Ractor 개선

Ruby에서 쉽게 병렬 처리를 수행하기 위한 Ractor에 많은 개선이 있었습니다. 먼저 Ractor::Port라는 클래스를 추가하여 메시지 송수신에 대한 문제를 해결했습니다(블로그 게시물을 참조하세요). 또한 Ractor.shareable_proc을 통해 Ractor 간에 Proc 객체를 공유하기 쉽게 만들었습니다.

성능 측면에서는 많은 내부 데이터 구조를 개선하여 전역 락에 대한 경합이 크게 감소하고 병렬 처리 성능이 향상되었습니다. 또한 Ractor 간에 공유하는 내부 데이터를 줄임으로써 병렬 실행 시 CPU 캐시 충돌을 줄였습니다.

Ractor는 Ruby 3.0에서 처음 실험적 기능으로 도입되었습니다. 내년에는 “실험적” 상태를 해제하려고 합니다.

언어 변경

  • **nilnil.to_hash를 호출하지 않는 것과 마찬가지로, *nil은 더 이상 nil.to_a를 호출하지 않습니다. [Feature #21047]

  • 줄 시작 부분에 있는 논리 이항 연산자(||, &&, and, or)는 유연한 점(fluent dot)처럼 이전 줄을 이어갑니다. 다음 두 코드는 동일합니다.

      if condition1
         && condition2
        ...
      end
    

    기존 작성법:

      if condition1 && condition2
        ...
      end
    
      if condition1 &&
         condition2
        ...
      end
    

    [Feature #20925]

코어 클래스 변경

주의: 주목할 만한 클래스 변경만을 포함합니다.

  • Array

    • array.reverse_each.find보다 효율적인 대안으로 Array#rfind가 추가되었습니다. [Feature #21678]
    • Enumerable#find를 더 효율적으로 실행하는 Array#find가 추가되었습니다. [Feature #21678]
  • Binding

    • Binding#local_variables는 더 이상 번호가 매겨진 매개변수를 포함하지 않습니다. 또한, Binding#local_variable_get, Binding#local_variable_set, Binding#local_variable_defined?는 번호가 매겨진 매개변수를 처리하지 않습니다. [Bug #21049]

    • 번호 매개변수 및 “it” 매개변수에 액세스하기 위해 Binding#implicit_parameters, Binding#implicit_parameter_get, Binding#implicit_parameter_defined?가 추가되었습니다. [Bug #21049]

  • Enumerator

    • Enumerator.produce는 이제 열거자의 크기를 지정하는 선택적 키워드 인자 size를 받습니다. 크기에는 정수, Float::INFINITY, 람다와 같은 호출 가능한 객체, 또는 알 수 없음을 나타내는 nil을 지정할 수 있습니다. 생략 시에는 Float::INFINITY가 기본 크기 값입니다.

        # 무한 열거자
        enum = Enumerator.produce(1, size: Float::INFINITY, &:succ)
        enum.size  # => Float::INFINITY
      
        # 크기가 알려진/계산 가능한 유한 열거자
        abs_dir = File.expand_path("./baz") # => "/foo/bar/baz"
        traverser = Enumerator.produce(abs_dir, size: -> { abs_dir.count("/") + 1 }) {
          raise StopIteration if it == "/"
          File.dirname(it)
        }
        traverser.size  # => 4
      

      [Feature #21701]

  • ErrorHighlight

    • ArgumentError가 발생했을 때 메서드 호출 측(caller)과 메서드 정의 측(callee) 양쪽의 코드 조각을 표시합니다. [Feature #21543]

      test.rb:1:in 'Object#add': wrong number of arguments (given 1, expected 2) (ArgumentError)
      
          caller: test.rb:3
          | add(1)
            ^^^
          callee: test.rb:1
          | def add(x, y) = x + y
                ^^^
              from test.rb:3:in '<main>'
      
  • Fiber

    • Kernel#raise와 유사한 Fiber#raise(cause:) 인자 지원이 도입되었습니다. [Feature #21360]
  • Fiber::Scheduler

    • 주어진 예외로 fiber를 인터럽트하기 위한 Fiber::Scheduler#fiber_interrupt가 도입되었습니다. 초기 사용 사례는 IO 작업이 닫힐 때 블로킹 IO 작업을 기다리는 fiber를 인터럽트하는 것입니다. [Feature #21166]

    • 시그널 예외가 비활성화되어 있어도 스케줄러가 처리를 계속할 수 있도록 Fiber::Scheduler#yield가 추가되었습니다. [Bug #21633]

    • 비동기 IO#closeFiber::Scheduler#io_close 훅이 재도입되었습니다.

    • IO 쓰기 버퍼를 플러시할 때 Fiber::Scheduler#io_write를 호출합니다. [Bug #21789]

  • File

    • 커널과 파일 시스템에서 지원하는 경우, File::Stat#birthtime이 statx 시스템 콜을 통해 Linux에서 사용 가능합니다. [Feature #21205]
  • IO

    • IO.select는 타임아웃 인자로 Float::INFINITY를 허용합니다. [Feature #20610]

    • 폐기 예정이었던, 선행 |를 사용한 IO 클래스 메서드의 프로세스 생성 기능이 제거되었습니다. [Feature #19630]

  • Kernel

    • Kernel#inspect는 이제 #instance_variables_to_inspect 메서드의 존재 여부를 확인하여, #inspect 문자열에 표시되는 인스턴스 변수를 제어할 수 있습니다.

        class DatabaseConfig
          def initialize(host, user, password)
            @host = host
            @user = user
            @password = password
          end
      
          private def instance_variables_to_inspect = [:@host, :@user]
        end
      
        conf = DatabaseConfig.new("localhost", "root", "hunter2")
        conf.inspect #=> #<DatabaseConfig:0x0000000104def350 @host="localhost", @user="root">
      

      [Feature #21219]

    • 폐기 예정이었던, 선행 |를 사용한 Kernel#open의 프로세스 생성 기능이 제거되었습니다. [Feature #19630]

  • Math

  • Pathname

    • Pathname이 기본 gem에서 Ruby의 코어 클래스로 승격되었습니다. [Feature #17473]
  • Proc

    • Proc#parameters는 이제 선택적 익명 매개변수를 [:opt, nil] 대신 [:opt]로 표시하여, 익명 매개변수가 필수인 경우와 일관된 출력을 제공합니다. [Bug #20974]
  • Ractor

    • Ractor 간 통신을 위한 새로운 동기화 메커니즘으로 Ractor::Port 클래스가 추가되었습니다. [Feature #21262]

        port1 = Ractor::Port.new
        port2 = Ractor::Port.new
        Ractor.new port1, port2 do |port1, port2|
          port1 << 1
          port2 << 11
          port1 << 2
          port2 << 12
        end
        2.times{ p port1.receive } #=> 1, 2
        2.times{ p port2.receive } #=> 11, 12
      

      Ractor::Port는 다음 메서드를 제공합니다.

      • Ractor::Port#receive
      • Ractor::Port#send(또는 Ractor::Port#<<)
      • Ractor::Port#close
      • Ractor::Port#closed?

      그 결과, Ractor.yieldRactor#take가 제거되었습니다.

    • Ractor의 종료를 기다리기 위해 Ractor#joinRactor#value가 추가되었습니다. 이들은 Thread#joinThread#value와 유사합니다.

    • Ractor#join을 내부적으로 구현하는 데 사용되는 저수준 인터페이스로 Ractor#monitorRactor#unmonitor가 추가되었습니다.

    • Ractor.select는 이제 Ractor와 Port만 받습니다. Ractor가 주어지면, Ractor가 종료될 때 반환됩니다.

    • Ractor#default_port가 추가되었습니다. 각 RactorRactor.send, Ractor.receive에서 사용하는 기본 포트를 가집니다.

    • Ractor#close_incomingRactor#close_outgoing이 제거되었습니다.

    • 공유 가능한 Proc 또는 람다를 만들기 위해 Ractor.shareable_procRactor.shareable_lambda가 도입되었습니다. [Feature #21550] [Feature #21557]

  • Range

    • Range#to_set은 이제 끝이 없는 범위 문제를 방지하기 위해 크기 검사를 수행합니다. [Bug #21654]

    • Range#overlap?은 이제 무한한(경계가 없는) 범위를 올바르게 처리합니다. [Bug #21185]

    • 시작이 없는 정수 범위에서 Range#max 동작이 수정되었습니다. [Bug #21174] [Bug #21175]

  • Ruby

    • Ruby 관련 상수를 포함하는 새로운 최상위 모듈 Ruby가 정의되었습니다. 이 모듈은 Ruby 3.4에서 예약되었으며 이제 공식적으로 정의되었습니다. [Feature #20884]
  • Ruby::Box

  • Set

    • Set은 이제 코어 클래스이며, 더 이상 자동 로드되는 표준 라이브러리 클래스가 아닙니다. [Feature #21216]

    • Set#inspect은 이제 배열 리터럴과 비슷하게 간결한 출력을 사용합니다(예: #<Set: {1, 2, 3}> 대신 Set[1, 2, 3]). [Feature #21389]

    • Set#to_setEnumerable#to_set에 인자를 전달하는 것은 폐기 예정 상태가 되었습니다. [Feature #21390]

  • Socket

    • Socket.tcpTCPSocket.new는 초기 연결에 대한 타임아웃을 지정하기 위해 open_timeout 키워드 인자를 허용합니다. [Feature #21347]
    • TCPSocket.new에서 사용자 지정 타임아웃이 발생한 경우, 상황에 따라 Errno::ETIMEDOUT 또는 IO::TimeoutError가 발생할 수 있었지만, 이제는 일관되게 IO::TimeoutError를 발생시킵니다(단, Socket.tcp에서는 유사한 상황에서 Errno::ETIMEDOUT이 될 수 있으며, OS 수준의 타임아웃에서는 어느 경우든 Errno::ETIMEDOUT이 발생할 수 있습니다).
  • String

    • 유니코드 17.0.0 및 이모지 버전 17.0으로 업데이트합니다. [Feature #19908][Feature #20724][Feature #21275] (Regexp에도 적용됩니다)

    • String#strip, strip!, lstrip, lstrip!, rstrip, rstrip!*selectors 인자를 허용하도록 확장되었습니다. [Feature #21552]

  • Thread

    • Kernel#raise와 유사한 Thread#raise(cause:) 인자 지원이 도입되었습니다. [Feature #21360]

표준 라이브러리 변경

주목할 만한 기능 변경인 표준 라이브러리 변경만을 나열합니다.

다른 변경 사항은 아래 섹션에 나열되어 있습니다. Ruby 3.4.0에 번들된 버전 이후의 릴리스 내역이 GitHub 릴리스에 있는 경우 함께 나열했습니다.

다음 번들 gem이 기본 gem에서 승격되었습니다.

다음 기본 gem이 추가되었습니다.

  • win32-registry 0.1.2

다음 기본 gem이 업데이트되었습니다.

다음 번들 gem이 업데이트되었습니다.

RubyGems와 Bundler

Ruby 4.0에는 RubyGems와 Bundler 4가 동봉되어 있습니다. 자세한 내용은 다음 링크를 참조하세요.

지원 플랫폼

  • Windows

    • 14.0보다 오래된 MSVC 버전(_MSC_VER 1900) 지원이 중단되었습니다. 이는 Visual Studio 2015 이상이 필요함을 의미합니다.

호환성 문제

  • Ractor::Port 추가로 인해 다음 메서드가 Ractor에서 제거되었습니다.

    • Ractor.yield
    • Ractor#take
    • Ractor#close_incoming
    • Ractor#close_outgoing

    [Feature #21262]

  • ObjectSpace._id2ref가 폐기 예정 상태가 되었습니다. [Feature #15408]

  • Process::Status#&Process::Status#>>가 제거되었습니다. Ruby 3.3에서 폐기 예정 상태가 되었습니다. [Bug #19868]

  • rb_path_check가 제거되었습니다. 이 함수는 Ruby 2.7에서 제거된 $SAFE 경로 검사에 사용되었으며, 이미 폐기 예정이었습니다. [Feature #20971]

  • “wrong number of arguments”의 ArgumentError 백트레이스에 수신자의 클래스/모듈 이름이 포함됩니다(예: bar가 아닌 Foo#bar). [Bug #21698]

  • 백트레이스에 internal 프레임이 표시되지 않습니다. 이 메서드도 다른 C 구현 메서드와 마찬가지로 Ruby 소스 파일 상에 있는 것처럼 표시됩니다. [Bug #20968]

    변경 전:

    ruby -e '[1].fetch_values(42)'
    <internal:array>:211:in 'Array#fetch': index 42 outside of array bounds: -1...1 (IndexError)
            from <internal:array>:211:in 'block in Array#fetch_values'
            from <internal:array>:211:in 'Array#map!'
            from <internal:array>:211:in 'Array#fetch_values'
            from -e:1:in '<main>'
    

    변경 후:

    $ ruby -e '[1].fetch_values(42)'
    -e:1:in 'Array#fetch_values': index 42 outside of array bounds: -1...1 (IndexError)
            from -e:1:in '<main>'
    

표준 라이브러리 호환성 문제

  • CGI 라이브러리가 기본 gem에서 제거되었습니다. 이제 다음 메서드를 위한 cgi/escape만 제공합니다.

    • CGI.escapeCGI.unescape
    • CGI.escapeHTMLCGI.unescapeHTML
    • CGI.escapeURIComponentCGI.unescapeURIComponent
    • CGI.escapeElementCGI.unescapeElement

    [Feature #21258]

  • Set이 표준 라이브러리에서 코어 클래스로 이동함에 따라, set/sorted_set.rb가 제거되었고, SortedSet은 더 이상 자동 로드되는 상수가 아닙니다. SortedSet을 사용하려면 sorted_set gem을 설치하고 require 'sorted_set'을 통해 이용해주세요. [Feature #21287]

  • Net::HTTP

    • 본문(body)을 가진 요청(예: POST, PUT)에서 Content-Type 헤더가 명시적으로 설정되지 않은 경우 기본적으로 application/x-www-form-urlencoded를 자동 설정하는 동작이 제거되었습니다. 애플리케이션이 이 자동 설정에 의존하고 있었다면, 이제 Content-Type 헤더 없이 요청이 전송되며 특정 서버와의 호환성이 손실될 수 있습니다. [GH-net-http #205]

C API 변경

  • IO

    • rb_thread_fd_close는 폐기 예정 상태가 되었으며 이제 아무 작업도 하지 않습니다. C 확장에서 Ruby 코드로 파일 디스크립터를 노출해야 하는 경우, RUBY_IO_MODE_EXTERNAL을 사용하여 IO 인스턴스를 만들고 rb_io_close(io)를 사용하여 닫으세요(이렇게 하면 IO 인스턴스의 모든 대기 중인 작업도 인터럽트하고 대기합니다). 파일 디스크립터를 직접 닫으면 대기 중인 작업을 인터럽트하지 않으며, 정의되지 않은 동작이 발생할 수 있습니다. 다시 말해, 두 개의 IO 객체가 같은 파일 디스크립터를 공유하는 경우, 하나를 닫아도 다른 하나에는 영향을 미치지 않습니다. [Feature #18455]
  • GVL

    • rb_thread_call_with_gvl은 이제 GVL 유무에 관계없이 작동합니다. 이를 통해 gem은 ruby_thread_has_gvl_p 확인을 피할 수 있습니다. 그래도 GVL에 대해서는 여전히 주의해주세요. [Feature #20750]
  • Set

    • Set에 대한 C API가 추가되었습니다. 다음 메서드가 지원됩니다. [Feature #21459]

      • rb_set_foreach
      • rb_set_new
      • rb_set_new_capa
      • rb_set_lookup
      • rb_set_add
      • rb_set_clear
      • rb_set_delete
      • rb_set_size

구현 개선

  • Class#new(예: Object.new)가 전반적으로 고속화되었으며, 특히 키워드 인수를 전달할 때가 개선되었습니다. YJIT와 ZJIT에도 적용됩니다. [Feature #21254]
  • 크기 풀이 다른 GC 힙을 독립적으로 성장시켜, 일부 풀에만 수명이 긴 객체가 있는 경우 메모리 사용량을 줄입니다.
  • 큰 객체 페이지에서의 GC 스윕이 고속화되었습니다.
  • “Generic ivar” 객체(String, Array, TypedData 등)는 새로운 내부 “fields” 객체를 사용하여 인스턴스 변수 액세스를 고속화합니다.
  • GC는 내부 id2ref 테이블을 첫 사용 시까지 보유하지 않도록 하여 object_id 할당과 GC 스윕을 고속화합니다.
  • Class와 Module 객체에서의 object_idhash가 고속화되었습니다.
  • 더 큰 Bignum 정수도 가변 폭 할당을 통해 임베디드 상태로 유지할 수 있게 되었습니다.
  • Random, Enumerator::Product, Enumerator::Chain, Addrinfo, StringScanner 및 일부 내부 객체가 쓰기 배리어로 보호되어 GC 오버헤드를 줄입니다.

Ractor

Ractor를 더 안정적이고, 성능이 좋고, 사용하기 쉽게 만들기 위해 많은 작업이 진행되었습니다. 이러한 개선으로 Ractor 구현이 실험적 상태를 벗어나는 데 더 가까워졌습니다.

  • 성능 개선
    • 얼린 문자열과 심볼 테이블은 내부적으로 잠금 없는 해시 셋 사용 [Feature #21268]
    • 메서드 캐시 조회는 대부분의 경우 잠금을 회피
    • 클래스 및 generic ivar 인스턴스 변수 접근이 더 빠르고 잠금을 회피
    • Ractor별 카운터를 사용하여 객체 할당 중 CPU 캐시 경합을 회피
    • 스레드 로컬 카운터를 사용하여 xmalloc/xfree에서 CPU 캐시 경합을 회피
    • object_id는 대부분의 경우 잠금을 회피
  • 버그 수정 및 안정성
    • Ractor와 Thread를 결합할 때 발생할 수 있는 데드락 수정
    • Ractor에서 require 및 autoload 관련 문제 수정
    • Ractor 간 인코딩/트랜스코딩 문제 수정
    • GC 작업 및 메서드 무효화의 경쟁 조건 수정
    • Ractor 시작 후 프로세스 fork 관련 문제 수정
    • Ractor 환경에서 GC의 할당 카운트가 정확해짐
    • GC 후 TracePoint가 동작하지 않는 문제 수정 [Bug #19112]

JIT

  • ZJIT
    • 실험적 메서드 기반 JIT 컴파일러가 도입되었습니다. ZJIT는 런타임에서 --zjit 옵션을 지정하거나 RubyVM::ZJIT.enable을 호출해 활성화할 수 있습니다. ZJIT 지원을 포함하여 Ruby를 빌드하려면 Rust 1.85.0 이상이 필요합니다.
    • Ruby 4.0.0 기준, ZJIT는 인터프리터보다 빠르지만 아직 YJIT만큼 빠르지는 않습니다. ZJIT를 시도해 보길 권장하지만, 아직 프로덕션 배포는 권장하지 않습니다.
    • Ruby 4.1에서 ZJIT를 YJIT보다 빠르게 만들고 프로덕션에 사용할 수 있게 만드는 것이 목표입니다.
  • YJIT
    • RubyVM::YJIT.runtime_stats
      • ratio_in_yjit는 기본 빌드에서 더 이상 작동하지 않습니다. --yjit-stats에서 활성화하려면 configure에서 --enable-yjit=stats를 사용하세요.
      • 기본 통계에 invalidate_everything이 추가되었습니다. TracePoint에 의해 모든 코드가 무효화될 때 증가합니다.
    • RubyVM::YJIT.enablemem_size:call_threshold: 옵션이 추가되었습니다.
  • RJIT
    • --rjit가 제거되었습니다. 서드파티 JIT API의 구현을 ruby/rjit 저장소로 이동할 예정입니다.

자세한 내용은 NEWS 또는 커밋 로그를 참조하세요.

이러한 변경사항에 따라, Ruby 3.4.0 이후로 파일 3889개 변경, 230769줄 추가(+), 297003줄 삭제(-)가 이루어졌습니다!

메리 크리스마스, 새해 복 많이 받으시고, Ruby 4.0과 함께 즐거운 해킹 되세요!

다운로드

  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.tar.gz

    SIZE: 23955109
    SHA1: 754e39e9ad122e1b6deaed860350bac133a35ed3
    SHA256: 2e8389c8c072cb658c93a1372732d9eac84082c88b065750db1e52a5ac630271
    SHA512: 688254e939b197d564e896fb951bc1abf07142f489e91c5ed0b11f68f52d6adb6b1f86616fe03f1f0bb434beeef7e75e158b9c616afb39bb34403b0b78d2ee19
    
  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.tar.xz

    SIZE: 18008368
    SHA1: 05ec670e86f84325c5353ef2f2888e53b6adc602
    SHA256: a72bacee9de07283ebc19baa4ac243b193129f21aa4e168c7186fb1fe7d07fe1
    SHA512: 2d5b2e566eaf70a5f3ea6ce6afc0611c0415de58a41336ef7a0b855c9a91eda9aa790a5f8b48e40a1eb9d50f8ea0f687216e617f16c8d040a08474f3116518a4
    
  • https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.0.zip

    SIZE: 29253204
    SHA1: 0b69f89d1d140157251c0d3a6032f6c45cdf81e8
    SHA256: 70cb1bf89279b86ab9a975d504607c051fc05ee03e311d550a5541b65e373455
    SHA512: a72e076ef618c0aeb9d20cf22e6fb12fda36809c0064ef0f98153b95a0bac257ef606342444a38f992c4594bf376a4d264686cf597463aa6f111220798784302
    

Ruby는

Ruby는 1993년에 Matz(마츠모토 유키히로)가 처음 개발했고, 현재는 오픈 소스로 개발되고 있습니다. 여러 플랫폼에서 동작하며, 전 세계적으로 특히 웹 개발에 사용됩니다.

최근 소식

Ruby 문서의 새로운 모습

ruby-lang.org 재디자인에 이어, Ruby의 30주년을 기념하는 또 다른 소식을 전합니다. docs.ruby-lang.org가 RDoc의 새로운 기본 테마인 Aliki와 함께 완전히 새로운 모습으로 탈바꿈했습니다.

작성자: Stan Lo (2025-12-23)

사이트 아이덴티티 재디자인

사이트의 전면적인 재디자인을 발표하게 되어 기쁩니다. 이번 업데이트의 디자인은 Taeko Akatsuka가 제작했습니다.

작성자: Hiroshi SHIBATA (2025-12-22)

뉴스 더보기...