이번 포스팅은 특별히 루비 크리스마스 달력(Advent Calendar)에 참여하는 글입니다.

ruby gem

RubyGem이란 ruby library를 배포하고 사용하는 표준화 패키징 및 설치 프레임워크입니다. node에서 사용하는 npm이나 마이크로소프트 개발 플랫폼에서 사용하는 nuget과 비슷합니다. 여러가지 gem없이 개발한다는 것은 어려운일로 대부분 프로젝트에서는 gem을 사용하고 있습니다. 이러한 gem을 만드는 방법에 대해 소개합니다.

먼저 알면 좋은것

gem을 만든다는 것은 몇가지 규칙을 지켜서 파일을 만들고 build를 하는 과정을 거치면 됩니다. 특별한 제약은 없으나 gem 이름이나 버전을 정할때 권장사항이 있습니다.

Naming

Gem 이름 규칙은 rubygems.org에서 권장하는 방식을 사용하는 것이 좋습니다. Class명과 모듈을 기반으로 이름을 정합니다.

  • RubyParser ruby_parser
  • RDoc::Data rdoc-data
  • Net::HTTP::Persistent net-http-persistent
  • Net::HTTP::DigestAuth net-http-digest_auth

모듈단위는 -(대시)로 구분하고 클래스명은 _(언더스코어)로 구분하면 됩니다.

Versioning

Semantic Versioning 방법과 rubygems.org에서 권장하는 방식을 사용합니다.

  • PATCH 0.0.x: 기능은 유지하면서 버그를 수정하거나 소스를 보완하였을때 사용합니다.
  • MINOR 0.x.0: 기존 버전과 호환성은 유지하면서 새로운 기능이나 함수를 추가했을때 사용합니다.
  • MAJOR x.0.0: 기존 버전과 호환성을 유지하지 않거나 새로 업데이트가 필요한 경우 사용합니다.

Ruby Gem 만들기

ruby gem은 정해진 파일과 디렉토리 구조가 필요합니다. 개발자가 따로따로 수동으로 만들어 되지만 여기서는 bundler에서 제공하는 template을 활용하여 자동으로 초기화합니다.

파일/디렉토리 초기화

먼저, bundler gem이 설치되어 있지 않다면 설치합니다.

$ gem install bundler

Gem이름으로 초기화합니다. 여기서는 four_sum이라는 gem을 만들어 봅니다. 인자값 4개를 넘기면 전체 합을 리턴하는 간단한 gem입니다.

$ bundle gem four_sum

bundle gem명령어를 실행하면 몇가지를 물어봅니다.

  • Do you want to generate tests with your gem?
    • rspec/minitest/(없음) 중에서 선택합니다. 이번에는 rspec을 이용하기로 합니다.
  • Do you want to license your code permissively under the MIT license?
    • License를 설정합니다. 가장 무난한 MIT를 기본값으로 선택할 수 있습니다. LICENSE.txt 파일을 만듭니다.
  • Do you want to include a code of conduct in gems you generate?
    • CODE_OF_CONDUCT.md 파일을 만듭니다.

명령어 한번 쳤을뿐인데 그럴듯한 구조가 만들어졌습니다.

.
├── CODE_OF_CONDUCT.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin
│   ├── console
│   └── setup
├── four_sum.gemspec
├── lib
│   ├── four_sum
│   │   └── version.rb
│   └── four_sum.rb
└── spec
    ├── four_sum_spec.rb
    └── spec_helper.rb

gemspec 수정

기본으로 만들어준 four_sum.gemspec을 수정합니다.

  spec.summary       = %q{TODO: Write a short summary, because Rubygems requires one.}
  spec.description   = %q{TODO: Write a longer description or delete this line.}
  spec.homepage      = "TODO: Put your gem's website or public repo URL here."

TODO 항목을 찾아 수정해줍니다.

README.md 수정

README.md는 github 첫페이지에 나오는 것으로 gem에 대한 설명을 적는 파일입니다. Readme Driven Develop이라는 개발방법론이 Gem파일을 만들때는 적절하다고 생각하는데 Gem파일이란 혼자 쓰려고 만들수도 있겠지만 기본적으로 공유하고 배포를 하기 때문에 README 파일이 중요하다고 생각합니다. 아무리 잘 만들어도 설명이 없거나 어떻게 사용하는지 API 설명이 부실하다면 쓰지 않기 마련입니다.

bundler가 만들어준 README.md파일은 이미 그럴싸한 내용이 많기 때문에 필요한 부분만 수정하고 추가해주면 됩니다. 일단 Usage부분에 우리가 만들 API 설명을 추가합니다.

## Usage

FourSum.sum 1,2,3,4 # => 10  

README를 적다보니 적절한 샘플이 아닌거 같긴한데 일단 고 합니다 ㅠㅠ.

RSpec 작성

이제 Test Code를 작성합니다. rspec 파일 역시 bundler가 샘플 구조를 잡아 놔서 작성하기 편합니다.

일단 현재 test case가 통과하는지 rspec(또는 rake) 명령을 통해 확인합니다.

$ rake # 또는 rspec

FourSum  
  has a version number
  does something useful (FAILED - 1)

첫번째 케이스는 통과하고 두번째 케이스는 실패하였습니다.

spec/four_sum_spec.rb 파일을 수정합니다.

require 'spec_helper'

describe FourSum do  
  describe '.sum' do
    it 'return 10 if 1,2,3,4 ' do
      sum = FourSum.sum 1,2,3,4
      expect(sum).to be 10
    end
  end
end  

rspec을 잘 작성하는 법은 Better Specs를 참고합니다.

Code 작성

이제 code를 작성하고 rspec을 반복 확인하는 작업을 진행합니다.

lib/four_sum.rb 파일을 수정합니다.

require "four_sum/version"

module FourSum  
  def self.sum(a, b, c, d)
    a + b + c + d
  end
end  

이제 rake를 실행해보면 성공! 했습니다.

Gem build

이제 gem을 build합니다.

$ gem build four_sum.gemspec

위와 같은 명령어는 외우기가 어려우므로 rake -T를 입력해봅니다.

$ rake -T
rake build            # Build four_sum-0.1.0.gem into the pkg directory  
rake clean            # Remove any temporary products  
rake clobber          # Remove any generated file  
rake install          # Build and install four_sum-0.1.0.gem into system gems  
rake install:local    # Build and install four_sum-0.1.0.gem into system gems without network access  
rake release[remote]  # Create tag v0.1.0 and build and push four_sum-0.1.0.gem to Rubygems  
rake spec             # Run RSpec code examples  

몇가지 gem 명령어를 rake로 실행할 수 있습니다.

$ rake build
four_sum 0.1.0 built to pkg/four_sum-0.1.0.gem.  

마치며

Gem을 만드는 가장 기본적인 단계들을 살펴보았습니다. ruby와 gem의 역사만큼 다양한 gem 만드는 가이드가 있지만 bundler와 rake를 적극적으로 활용한 가이드는 없는 것 같아 작성해보았습니다. Gem 만드는데 많은 도움되시고 좋은 Gem 많이 만들어주세요!