[DOC] 루비와 자바의 환상적인 만남, J루비 개발 테크닉

개발 환경의 대이동 스크립트 언어의 역습





최근 웹 개발 환경을 보면 루비를 선두로 하는 스크립트 언어들의 약진이 눈에 띈다. 이러한 스크립트 언어의 행보는 자바나 닷넷 개발자들을 스크립트 개발자로 변신시키고 있다. 심지어 자바 기술 리더인 브루스 테이트(Bruce Tate)마저 스크립트 언어의 손을 들어주었을 정도다. 그렇다면 이제 기존 개발 언어들은 모두 몰락의 길을 걷게 되는 것일까? 전문가들은 이 문제에 대한 답으로 기존 개발 언어와 스크립트 언어가 공존하며 서로를 보완해 주는 구도가 될 거라 예상한다. 기존 언어들의 장점을 최대한 살리면서 취약한 부분들에 스크립트 언어를 적용하여 안정성과 빠른 개발의 두 마리 토끼를 모두 잡을 수 있다는 것이다. 이번 특집에서는 기존 개발 언어들과 스크립트 언어를 융합하여 사용하는 기술과 활용 방법들에 대해 알아보았다.



기획·정리
| 정희용 기자 flytgr@imaso.co.kr



루비와 자바의 환상적인 만남, J루비 개발 테크닉



이창신 |오픈마루(openmaru) 플랫폼 오프너



1999년부터 2006년까지 무려 8년간 필자는 오직 자바만 팠다. 자바는 실로 모든 것을 할 수 있을 정도로 발전해왔지만, 그것이 모든 것을 잘 할 수 있음을 의미하지는 않다는 사실을 깨달은 것은 솔직히 얼마 되지 않았다. 오히려 자바는 과거의 오명을 많이 씻었다. 느린 성능도 잡아가고 있고, 플랫폼도 오픈 소스화 되어가고 있으며 툴도 풍부해져 가고 있다. 이렇듯 성장해가고 있는 자바라고해도 완벽할 수는 없는 법, 그리고 빠른 개발을 강렬히 원하는 21세기 IT 환경에서 동적 스크립트 언어의 활약은 더욱 기대 받고 있다. 그리고 그 선봉에 루비가 서 있다.



루비에 대해서는 그동안 마소를 통해 많이 소개된 바 있다. 게다가 2006년에는 통산 10대 개발 언어로 우뚝 설 만큼 메이저 프로그래밍 언어로 거듭나기도 한 저력이 있는 스크립트 언어이다. 이 10대 언어 중 1위가 자바였다는 점은 참으로 고무적이다. 그동안 C 계열 언어나 닷넷 진영과의 경쟁이 끊이지 않았음에도 탄생 10년 만에 최고의 자리에 올랐다는 것은 그만큼 쓸모가 있었음을 시사한다. 특히 자바는 엔터프라이즈 시장을 석권하면서 탄탄한 시장을 형성했다. PC를 제외한 다양한 디바이스에까지 선전하며 단순히 프로그래밍 언어로써가 아닌, 플랫폼으로의 확실한 자리매김을 한 것이다. 그러는 동안 자바 커뮤니티도 매우 건실한 성장을 이루었다. 인터넷을 통한 정보 공유, 특히 오픈 소스의 혜택과 맞물려 양적으로나 질적으로 역사상 보기 드문 번영을 누리기도 했다.



그러나 자바는 전통적인 정적 타입을 기반으로 하는 탓에 리플렉션(reflection)과 프록시(proxy)를 통해 동적인 기법을 발휘하는 데에 한계가 있었다. 특히 웹 애플리케이션과 같이 변화가 많고 HTML 등의 마크업 언어와 결부되는 곳에서는 어려움을 감수해야만 했다.





루비와 자바의 만남





필자가 루비를 처음 알게 된 것은 2002년 일본에 있을 때였다. 루비는 자바와 비슷한 시기인 1995년에 세상에 첫 선을 보였다. 일본인이 만든 언어라는 사실에 나는 ‘과연 이 언어가 세계로 뻗어갈 수 있을까?’하는 의문을 가졌다. 그러나 레일즈(Rails)라는 프레임워크를 통해 루비는 일대 전기를 맞이하게 된다. 객체 지향이면서도 간결하고 동시에 유연한 웹 애플리케이션에 있어 이상과 현실의 간극을 가장 잘 메울 수 있는 특성을 지닌 루비의 부각은 어찌 보면 너무나도 자연스러운 일인지도 모른다.



루비는 이미 다양한 플랫폼에 포팅되어 있다. 대부분의 유닉스를 지원하며 많은 루비 개발자들이 선호한다는 맥(Mac) OS X는 물론이고, 윈도우에서도 루비를 쓸 수 있다. 즉, 모든 플랫폼에 각각 네이티브 구현이 되어 있다는 뜻이기도 하다. 그런데, J루비(Ruby)라는 것이 등장하면서 루비에 대한 관심이 또다시 증폭되었다. 루비 프로그래밍 언어의 100% 순수 자바 구현이라는 J루비는 과연 어떤 의미를 가지는 것일까? 그 해답에 대해 말하기에 앞서 J루비에 대한 진신을 한 꺼풀씩 벗겨 나가면서 J루비가 껴안은 루비와 자바가 어떻게 융합되는지를 주목해보자.





J루비 준비하기





J루비 프로젝트는 최초 sourceforge.net에서 시작했다가 2006년에 codehaus.org로 옮겼다. 현재 공식 사이트는 http://jruby. codehaus.org/이고 따라서 이 사이트에서 J루비를 내려 받을 수 있다. 아직 1.0도 되지 않은 초기 상태여서 코드 변화도 많은 탓에 2007년 1월 15일 현재 최신 릴리스 버전인 0.9.2보다는 SVN에 있는 소스를 빌드해 쓰는 것을 권한다. 먼저 배포판을 설치하는 경우, http://dist.codehaus.org/jruby/에서 자신의 JDK 버전에 맞는 바이너리 압축 파일을 받아 적당한 디렉토리에 푼다(jruby-java4-bin-0.9.2.tar.gz나 jruby-java5-bin-0.9.2.tar.gz중 택일).



J루비 SVN에 있는 최신 개발 소스로 J루비를 설치하려면 먼저 svn://svn.codehaus.org/jruby/trunk/jruby에서 J루비 트렁크(trunk)를 체크아웃(check-out)해야 한다.



만약, SVN 명령을 쉘에서 실행할 수 있다면,



svn co svn://svn.codehaus.org/jruby/trunk/jruby jruby



를 실행한다. 앞의 명령을 실행한 디렉토리 바로 밑에 jruby라는 디렉토리가 생기면서 소스를 모두 내려 받는다. 이번에는 생성된 jruby 디렉토리로 가서



ant jar



를 실행하면 J루비가 빌드된다.



이렇게 바이너리나 소스를 통해 J루비를 설치하고 나면, J루비를 쉘에서 편하게 쓸 수 있도록 환경 설정이 필요하다. J루비가 설치된 디렉토리를 JRUBY_HOME 환경 변수로 잡은 다음, PATH 환경 변수에 JRUBY_HOME/bin을 추가하면 된다. 예를 들어 윈도 운영체계에서 J루비를 C:\jruby에 설치했다면,



set JRUBY_HOME=C:\jruby
set PATH=%JRUBY_HOME%\bin;%PATH%



와 같이 설정한다. 이로써 J루비를 사용할 준비를 마친 셈이다. 그러면 다음으로 J루비가 과연 루비와 자바를 어떻게 지원하는지 살펴보자.





Hello World 구동하기





J루비는 자바로 구현한 루비이므로 당연히 루비 프로그램을 실행시킬 수 있다. 그럼 만고불변의 예제, “Hello World”를 돌려보자.




<리스트 1> hello-world.rb

puts "Hello World"



너무 간단해서 심심한 감이 있지만, <리스트 1>의 한 줄 코드를 hello-world.rb 파일로 저장한 다음



jruby hello-world.rb



을 실행하면 화면에 Hello World가 표시된다(원래 루비라면 jruby 대신 ruby라고 하면 된다). 루비 코드를 실행하는 방법으로 ruby 말고도 irb(interactive ruby shell)이라는 것이 있는데 J루비도 jirb라는 명령으로 지원한다. jirb를 실행하면,



irb(main):001:0>



와 같이 프롬프트가 뜨는데, 여기에 puts “Hello World”를 입력하면



irb(main):001:0> puts “Hello World”
Hello World
=> nil
irb(main):002:0>



와 같이 Hello World가 출력되며 puts 메소드의 반환 값인 nil(자바로 치면 null)이 나온 뒤에 다음 명령을 받을 준비를 한다. irb는 인터프리터 방식으로 코드를 실행할 수 있어, 간단히 테스트 짠다거나 아이디어를 확인해볼 수 있어 매우 유용하다.



루비에서 자바 API 사용하기



사실 루비 프로그램을 실행한다는 측면에서는 J루비와 루비가 동일하다. 그렇다면, 자바로 되어 있어서 가지는 J루비의 강점은 과연 무엇일까? 바로 루비 코드에서 자바 API를 자연스럽게 사용할 수 있다는 점이다. <리스트 2>를 통해 자바 API를 루비에서 사용하는 간단한 예를 살펴보자. 먼저 적당한 디렉토리(예: c:\jruby-test)를 만든 다음 그 디렉토리에 call_java.rb로 저장한 다음 jruby call_java.rb로 실행한다.



<리스트 2> call_java.rb

require "java"

include_class "java.util.TreeSet"

set = TreeSet.new
set.add "ias"
set.add "cb"
set.each { |v| puts "value: #{v}" }



<리스트 2>는 자바 코어 API의 java.util.TreeSet을 사용하고 있다. 이를 위해 먼저 require “java”로 자바 지원을 명시하고, 그 다음 include_class 명령으로 사용한 자바 클래스를 패키지 이름과 클래스 이름으로 지정한다. 오브젝트 생성을 위한 자바 문법인 new TreeSet() 대신, 루비의 오브젝트 생성 메소드인 new를 사용한다. 즉



TreeSet set = new TreeSet();



가 루비에서는



set = TreeSet.new



가 된다(루비는 타입 선언을 하지 않으며, 인수가 없는 메소드에는 괄호()를 쓰지 않아도 된다). set에 문자열을 넣는 경우에도, 자바라면



set.add(“ias”)



가 되겠지만 루비에서는 인수가 한 개이면 괄호를 쓰지 않아도 된다. 그러니 다음과 같이 괄호를 생략해서 써도 된다.



set.add “ias”



이렇듯 루비는 코드를 줄여서 쓰는 표기법이 특징이다. 마지막으로 순환문(loop)의 경우 자바와 많이 다르다. 자바라면



for (String v : set) {
System.out.printf(“value: %s\n”, v);
}



인 것을 루비로 짜면



set.each { |v| puts “value: #{v}” }



가 된다. #{v}와 같이 보간식(interpolation)을 써서 편리한 출력을 포맷할 수 있다. 이와 같이 기존의 자바 API를 호출하는 것 말고, 자신이 작성한 클래스를 호출하는 것은 어떨까?




<리스트 3> CallMe.java

package ias;

public class CallMe {

private String name;

public CallMe() {
this("ias");
}

public CallMe(String name) {
this.name = name;
}

public void hello() {
System.out.println("Hello from " + name);
}



<리스트 3>의 자바 클래스를 작성한 뒤에 call_java.rb와 같은 디렉토리에 저장하고 나서



java -d . *.java



를 실행한다. 그다음 CLASSPATH 환경 변수에 현재 디렉토리를 설정하는데, 윈도우라면



set CLASSPATH=.



와 같이 하면 된다. 그러고 나서 call_java.rb에 이 CallMe 클래스를 호출하는 코드를 추가한다.




<리스트 4> call_java.rb

require "java"

include_class "java.util.TreeSet"
include_class "ias.CallMe"

set = TreeSet.new
set.add "ias"
set.add "cb"
set.each { |v| puts "value: #{v}" }

cm = CallMe.new
cm.hello
cm = CallMe.new 'cb'
cm.hello





ias.CallMe 클래스를 임포트하는 문장을 추가하고, 맨 밑에 CallMe 오브젝트를 만든 다음 hello 메소드를 호출하도록 한다. 실행 결과를 살펴보자. 먼저 인수 없는 기본 생성자를 부르는 경우 CallMe의 name 필드는 ias가 되므로 화면에는 Hello from ias가 표시되고, ‘cb’를 인수로 new를 부르면 name 필드가 cb로 설정되어 Hello from cb가 출력된다.





자바와 루비의 결합





기존 API의 호출과 자작 클래스 호출에 이어 마지막으로 살펴볼 것은 매우 흥미로운 루비와 자바의 결합이다. 자바로 인터페이스를 작성한 다음, 그것을 루비 클래스로 구현하는 것이다. 먼저 자바 인터페이스를 보자.




<리스트 5 - ISpeaker.java>

package ias;

public interface ISpeaker {
public void say(String msg);
}



이 인터페이스는 say 메소드를 정의하고 있다. 때문에, 이 인터페이스를 구현하면 say 메소드를 채워 넣어야 한다. 앞서 CallMe.java와 마찬가지로



javac -d . *.java



로 컴파일 한다. 이 ISpeaker.java를 call_java.rb에서 구현해보면 <리스트 6>과 같이 된다.



<리스트 6> call_java.rb

require "java"

include_class "java.util.TreeSet"
include_class "ias.CallMe"

set = TreeSet.new
set.add "ias"
set.add "cb"
set.each { |v| puts "value: #{v}" }

cm = CallMe.new
cm.hello
cm = CallMe.new 'cb'
cm.hello

class CallJava < ISpeaker
def say(msg)
puts "Ruby saying #{msg}"
end
end

cm = CallJava.new
cm.say("hi")



<리스트 6>의 class CallJava 뒷부분을 살펴보면 루비로 어떻게 자바 인터페이스를 구현하는지 알 수 있다. 먼저 ‘<’로 자바의 implements 키워드를 대신하고, 메소드의 시그니처는 루비 문법에 맞게 반환 타입과 인수 타입 없이 서술한다. CallJava 클래스 선언을 마치고나면 테스트로 CallJava 오브젝트를 만들어 say 메소드를 불러보고 있다.





자바에서 J루비 사용하기





지금까지는 루비에서 자바를 어떻게 사용하는가에 초점을 맞춰 알아보았다. 그렇다면, 그 반대인 자바에서 루비를 사용하는 경우는 어떨까? J루비는 이 경우에도 인터페이스를 마련해놓았다.



<리스트 7> CallRuby.java

package ias;

import org.jruby.IRuby;
import org.jruby.Ruby;

public class CallRuby {

public static void main(String[] args) throws Exception {
IRuby runtime = Ruby.getDefaultInstance();
runtime.evalScript("puts 1 + 2");
}
}



CallRuby.java를 컴파일하고 실행하기 위해서는, JRUBY_ HOME/lib에 있는 jruby.jar와 asm-2.2.2.jar를 CLASSPATH에 포함시켜야 한다. 코드는 아주 간단하지만, 이만큼 J루비가 어떻게 루비 프로그램을 자바에서 실행하게 해주는지 잘 보여주는 예도 없다. 안타깝게도 이 방식은 J루비가 자체적으로 제공하는 방식이며, 일반적으로 자바에서 다른 스크립트 언어를 호출하는 방식은 아니다. 이 주제에 있어 JSR 223 Scripting for Java Platform라는 자바 표준이 있어서 자바 SE 6에서 기본으로 지원하고 있다.



자바 SE 6와 연동하기



이번에는 자바 SE 6와 J루비를 연동하는 방법에 대해 알아보자. 이제부터 나오는 예제는 JDK 6가 필요하다. JDK 6는 JDK 5와는 달리 호환성에 큰 차이는 없다. 이미 JDK 5를 쓰고 있다면 업그레이드에 크게 무리가 없을 것이다. http://java.sun. com/javase/downloads/ 에 가면 이미 JDK 6가 Latest Release로 자리 잡고 있음을 알 수 있다. JDK 6에 JSR 223 API가 기본 탑재되어 있기는 하지만, 각 언어별 어댑터까지 내장되어 있지는 않다. java.net의 스크립팅 프로젝트(https://scripting.dev .java.net/)에서 오픈소스로 개발되고 있는데, 프로젝트 공식 사이트의 “프로젝트 문서” 왼쪽 메뉴를 클릭하여 jsr223-engin es.tar.gz나 jsr223-engines.zip을 받아 적당한 디렉토리에 푼다.




<리스트 8> CallRuby2.java

package ias;

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class CallRuby2 {

public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine rubyEngine = m.getEngineByName("jruby");

rubyEngine.getContext().setAttribute("label", new Integer(2), ScriptContext.ENGINE_SCOPE);
rubyEngine.eval("puts 1 + $label");
}
}



<리스트 8>을 컴파일하고 실행하려면 앞서 강조했듯이 JSR 223 API를 내장한 JDK 6가 필요하다. 더불어 J루비와의 연동을 위한 J루비 스크립트엔진(ScriptEngine)을 구현한 라이브러리도 필요하다. 따라서 CLASSPATH에는 앞서 압축을 푼 jsr223-engines 라이브러리의 내용 중에 jruby/build/jruby-engine.jar를 추가하면 된다. 예를 들어 윈도우에서 jsr223-engines.zip을 C:\jsr223에 풀었다면, 다음과 같이 입력하면 된다.



set CLASSPATH = C:\jsr223\jruby\build\jruby-engine.jar



<리스트 8>에서 main 메소드의 전반부 두 줄은 J루비 스크립트엔진을 얻어오는 코드이다. 먼저 ScriptEngineManager를 얻은 다음, jruby라는 이름으로 엔진을 식별한다. CallRuby2의 실행 결과는 CallRuby와 같은데, 실제 코드에서의 차이점은 Scr iptEngine에 label이라는 전역변수를 넘기는 것이다(루비에서 $변수가 바로 전역변수이다). 각 ScriptEngine에는 Script Con text라는 것이 있는데, 여기에 속성(attribute)을 추가하거나 접근함으로써 스크립트를 부르는 자바와 호출되는 스크립트 사이에 컨텍스트를 공유한다.



ScriptEngine.eval에는 문자열뿐 아니라 java.io.Reader도 넘길 수 있어 다음과 같이 쓰면 call_java.rb 파일을 실행할 수도 있다.



rubyEngine.eval(new FileReader(“call_java.rb”));



JSR 223의 자세한 용법은 이 글의 주제를 넘어서므로 마소에 그간 소개되었던 JSR 223이나 Java SE 6 관련 기사를 참고하기를 권한다.





J루비 온 레일즈(JRuby on Rails)






J루비가 루비와 자바라는 두 마리 토끼를 다 잡는 용감한 시도를 하고 있지만, 많은 사람들이 실제로 관심을 가지는 것은 J루비로 웹 애플리케이션을 작성하는 것이다. 더 구체적으로 말하면 최근 각광받고 있는 레일즈 프레임워크의 언어로써 J루비를 생각하는 것이다. 물론 레일즈하면 루비, 그래서 루비 온 레일즈(Ruby on Rails)이지만, 레일즈의 독특한 사상에 매료된 타 언어 개발자들이 그레일즈(Grails)(이번 특집에서 강규영 님이 소개하는 그루비 온 레일즈), SQL 온 레일즈(SQL on Rails) 등 기상천외한 레일즈 응용을 내놓고 있다.



사실 J루비 온 레일즈(JRuby on Rails)는 그런 시도에 비하면(기본적으로 J루비도 루비이므로) 오히려 얌전한 편이지만, 아직 루비 수준의 완전한 상태는 아니다. 한 가지 반가운 것은 많은 얼리어댑터들의 채택이 줄을 잇고 있으며, 최근 한 개발자가 실제 프로젝트에서 J루비 온 레일즈를 쓴 소감이 올라오는 등 상황이 무척 고무적이라는 점이다.





J루비에 레일즈 설치하기





J루비에서 레일즈를 설치하는 일은 그냥 루비에서 레일즈를 설치하는 것과 크게 다르지는 않다. 다만, 아직 J루비의 성능이 많이 떨어져서 rdoc이나 ri 같은 문서 시스템을 설치하면 기다림에 지칠 수 있어 설치 시에 제외하면 좋다. 간단히 다음 명령을 쉘에서 실행하자.



gem install rails -y --no-ri --no-rdoc



gem은 루비의 패키지 관리 프로그램이다. 아주 직관적으로 레일즈 패키지를 설치하라는 뜻임을 알 수 있다. -y는 레일즈가 필요로 하는 패키지들을 알아서 설치하라는 뜻이고, 뒤의 옵션은(J루비에서 아주 오래 걸리는) 참고 문서 설치를 하지 말라는 뜻이다.



설치를 잘 마쳤다면, 시험 삼아 레일즈를 실행해보자. 가끔 ‘stack level too deep’ 이라는 오류 메시지가 표시되면서 설치가 정상적으로 되지 않는 경우가 있다. 이럴 때는 명령을 실행하는 디렉토리를 바꿔보면 좋다. 예를 들어 C:\ruby에서 gem을 실행했는데 잘 안되면, C:\ 로 가서 gem을 실행하는 식이다.



rails test



로 쉘에서 실행하면, 이 명령을 실행한 디렉토리 밑으로 test라는 디렉토리가 생기면서 test 애플리케이션이 생성된다. 혹시 이 경우에도 ‘stack level too deep’ 같은 에러가 표시되면 실행 디렉토리를 바꿔보길 권한다. 윈도우 환경에서는 rails.bat 배치 명령이 JRUBY_HOME/bin에 생성되지 않는 경우도 있다. 이럴 때에는 직접 다음 내용을 입력하여 rails.bat를 만든 뒤에 JRUBY_HOME/bin에 저장해두면 된다.



jruby %JRUBY_HOME%\bin\rails %*



test 애플리케이션이 정상적으로 만들어졌다면 이번에는 test 디렉토리로 가서



jruby script/server



를 실행하면 3000번 포트에 WEBrick이라는 간이 웹 애플리케이션 서버가 뜬다. 웹 브라우저로 http://localhost:3000/를 열어보면 test 애플리케이션이 잘 기동했음을 확인할 수 있다.





JDBC





레일즈 킬러 컴포넌트중의 하나인 ActiveRecord는 ORM (Object-Relational DB Mapping)으로 DB 연결을 한다. DB를 연결 하면 자바는 JDBC라는 표준 인터페이스를 통해 J루비도 이것을 활용하도록 안내하고 있다. 이를 위해 먼저 Active Record-JDBC 패키지를 설치한다. ActiveRecord-JDBC 패키지를 설치하려면 다음과 같이 입력하면 된다.



gem install activerecord-jdbc --no-rdoc --no-ri



이제, 앞서 생성한 test 애플리케이션이 JDBC로 DB를 연결하도록 설정할 차례다. JDK 6에는 자바DB(실은 Apache Derby)가 내장되어 있어 DB도 따로 설치할 필요가 없다. 여기에서는 자바DB를 대상으로 알아보자. 먼저 test 디렉토리 밑의 config/database.yml을 수정한다.



development:
adapter: jdbc
driver: org.apache.derby.jdbc.EmbeddedDriver
url: jdbc:derby:embedded_db;create=true



처음 생성된 database.yml에는 MySQL 중심의 뭔가 복잡한 설정이 있을 것이다. test나 production은 건드리지 말고 devel opment 항목만 위와 같이 깔끔하게 고친다(참고로 yml은 루비에서 주로 쓰는 설정 파일 포맷이다). 이렇게 설정하고 나면 자바DB의 내장 모드가 사용되기 때문에 따로 자바DB를 서버 모드로 띄울 필요가 없다(대신 test 디렉토리 밑으로 embedded_db 라는 디렉토리가 생기며 이것이 바로 DB 그 자체가 된다).



설정을 마치고 나면 config/environment.rb에 JDBC 어댑터를 쓰도록 설정한다.



require File.join(File.dirname(__FILE__), ‘boot’)
require ‘jdbc_adapter’ << 여기에 추가
Rails::Initializer.run do |config|



require 문장 하나를 추가하는 것이다. 마지막으로, CLASS PATH 환경 변수에 자바DB 관련 라이브러리를 추가한다. JAVA_HOME/db/lib/derby.jar, JAVA_HOME/db/lib/ derbyclient.jar, JAVA_HOME/db/lib/derbytools.jar 총 세 개가 필요한데, 만약 JAVA_HOME 환경 변수를 잡은 상태의 윈도우 환경이라면 다음과 같이 된다.



set CLASSPATH=%JAVA_HOME%\db\lib\derby.jar;%JAVA_ HOME%\db\lib\derbyclient.jar;%JAVA_HOME%\db\lib\derbytools.jar



이로써 JDBC로 자바DB를 사용할 준비를 마쳤다. 이제 실제 ActiveRecord를 써서 테스트를 해보자.





scaffold 예제





J루비가 레일즈 1.2를 완전히 지원하지는 않지만, 1.2에서 새로이 추가된 scaffold_resource는 기본적으로 지원하여 RESTful scaffold도 가능하다. 레일즈에는 scaffold라는 개념이 있는데, 이는 하나의 데이터 모델에 대한 CRUD(Create, Retrieve, Up date, Delete)를 위한 콘트롤러와 뷰를 쉽게 짤 수 있도록 해준다. 여기에 scaffold로 만든 모델 데이터도 웹의 리소스로 공개하여 RESTful 리소스로 쉽게 만들어준다.



J루비에서 레일즈 1.2를 쓰려면 가장 먼저 이전에 설치한 레일즈 1.1.6을 지워야 한다.



gem uninstall rails



이렇게 입력하여 레일즈를 지운 다음(윈도우는 레일즈 배치 스크립트를 지우겠냐는 질문에 지우지 말라고 하는 것이 편하다. 아니면 앞에서 했던 것과 같이 레일즈 1.2를 다시 설치한 다음 rails.bat를 또 만들어야 한다), 레일즈가 의존하는 a로 시작하는 패키지를 모두 지운다.



gem uninstall act*



이제, 선택하는 화면에서 ActiveRecord-JDBC를 뺀 나머지 패키지들을 선택하여 차례대로 지우면 된다.



gem clean



으로 패키지를 깔끔하게 정리한 뒤에 다음 내용을 입력해서 레일즈 1.2를 설치한다.



gem install rails --source http://gems.rubyonrails.org/ -y --no-rdoc --no-ri




--source 옵션은 아직 정식 릴리스되지 않은 레일즈 1.2 RC 버전이 있는 위치를 지정한다. 이제 새로운 애플리케이션을 만들어 보자.



rails test2



로 test2 애플리케이션을 만든 다음, 앞서 했었던 JDBC 관련 설정을 똑같이 하면 scaffold를 할 준비를 마친 셈이다. test2 디렉토리에서



jruby script/generate scaffold_resource item name:string content:string



라고 실행하면, item이라는 웹 리소스에 대한 모델과 뷰, 콘트롤러가 한 번에 생성된다. DB 테이블 생성을 위해



rake db:migrate



를 실행하면 내장 자바DB에 item에 대응하는 테이블이 생성되어 애플리케이션을 온전히 실행할 수 있다.



jruby script/server



로 애플리케이션을 띄운 다음 브라우저로 http://localhost: 3000/items를 열면 먼저 item의 목록이 나온다. 현재는 아무런 데이터가 없으므로 목록 화면에 New라는 링크만 눈에 뜨일 것이다. 이 링크를 누르면 문자열(string) 타입으로 설정한 name과 content를 받을 폼이 나오고, 입력하여 전송하면 다시 목록이 나오는데 이번에는 아까 입력한 항목이 포함되어 있다. 참고로 scaffold_resource로 만든 item은 RESTful하므로,



http://localhost:3000/items.xml -> 전체 item을 XML로 전달
http://localhost:3000/items/1.xml -> 1번 item을 XML로 전달



할뿐만 아니라 POST, PUT, DELETE 등의 HTTP 메소드를 통해 해당 item을 CRUD할 수 있다. 또한 XML 형식뿐 아니라 RSS, JSON(JavaScript Object Notation)으로도 제공할 수 있어 RSS 리더나 Ajax에도 매우 친화적이다.



J루비는 근본적으로 루비이므로, 루비로 할 수 있는 일이라면 J루비에서도 모두 시도해볼만하다. 다만, 아직 성능상 네이티브 루비를 따라잡지 못하고 있고(보통 체감으로도 네이티브 루비와 많이 차이가 난다) 루비 표준 라이브러리나 레일즈를 100% 지원하는 것도 아니므로 그 정도의 부족함은 감안해야 한다.
작년에 J루비의 코어 개발자 두 명이 썬에 고용되었다는 소식이 화제가 되었다. 그만큼 J루비는 자바와 썬의 전폭적인 지원을 받고 있다. 올해 안에 1.0이 나올지는 모르겠지만(아직 0.9.2 이후의 로드맵이 나오지 않은 상태) 아주 빠르고 열정적인 개발이 이루어지고 있어 앞서 지적했던 성능이나 API 지원도 점차 네이티브 루비와 레일즈를 따라잡으리라 믿는다.



만약 지금 당장 루비나 레일즈를 배우거나 써야겠다면 네이티브를 선택하는 편이 좋다. 벌써부터 J루비를 실제 프로젝트에 적용하는 사례가 나오고는 있지만, 매우 제한적인 사용일 수밖에 없을 것이다. 만약 자신의 프로젝트가 자바SE나 자바EE와 연동해야 하고, 작은 부분이지만 매우 동적으로 빠르게 개발이 되어야 한다면, 그리고 적용한 부분의 성능이 전체 성능에 큰 영향을 끼치지 않는다면 J루비는 자바와 함께 쓸 좋은 스크립트 언어중의 하나라고 생각한다.





Rjb(Ruby Java Bridge)



J루비가 루비를 통째로 구현하는 다소 과격한 방식을 통해 루비와 자바를 잇는 반면, 간단한 브릿지 방식으로 루비에서 자바를 쓸 수 있는 라이브러리도 있다. 필자가 이 주제에 관심이 많았던 것은 실제 참여하고 있는 프로젝트에서 루비와 자바의 연동을 모색해보았기 때문이다.



Rjb는 이름에서도 볼 수 있듯이 루비 코드에서 자바 API를 호출할 수 있도록 해준다. 제작자는 우연히도 내가 번역하고 있는 루비 온 레일즈 책의 저자인 arton이었다. 이 사람은 Rjb뿐만 아니라 ASP에서 루비를 쓸 수 있도록 해주는 ASR(ActiveScriptRuby)도 만들어 배포하고 있다. 근본적인 사용법은 J루비와 같지만, 초기 설정이 달라서 다음과 같은 방법으로 instance에 자바의 String 오브젝트가 생긴다. 자세한 것은 공식 사이트인 http://rjb.rubyforge.org/ 을 참고하길 바란다.



require ‘rjb’

Rjb::load
str = Rjb::import(‘java.lang.String’)
instance = str.new





레일즈 1.2 지원



2007년 1월 15일 현재 J루비의 레일즈 지원은 1.1.6(역시 1월 15일 현재 최신 릴리스 버전) 수준이다. 한편, 레일즈 1.2는 1.1.6에 비해 많은 변경을 예고하며 RC2가 릴리스되어 곧 정식 릴리스될 예정이다(아마도 이 글을 읽고 있는 시점에는 이미 1.2가 최신 릴리스 버전일 것이다). J루비도 물론 레일즈 1.2 지원을 위해 열심히 달리고 있지만, 아직은 기본적인 기능에 있어서도 많이 부족한 상황이다. 이는 레일즈 1.2에서 상당히 근본적인 부분까지 건드린 여파인데, J루비가 레일즈 1.2를 어느 정도 쓸 만하게 지원하는 데에는 상당한 시간이 필요할 것으로 보인다.



따라서 안타깝지만 J루비에서 레일즈를 무리 없이 쓰고자한다면 1.1.6 버전에 머물러 있기를 권하며, 설치할 때부터



gem install rails -v 1.1.6



으로 버전을 지정하는 것이 J루비의 레일즈 1.2 완전 지원 소식을 듣기 전까지 유용할 것이다.





참고 자료



1. http://docs.google.com/View?docid=dfp6jsgc_7cxkwnc 필자가 작성한 J루비 (on Rails). 특히 JRoR 관련 링크들을 집대성했다.

댓글

이 블로그의 인기 게시물

[MSSQL] 데이터베이스가 사용 중이어서 배타적으로 액서스할 수 없습니다

[LINUX] CentOS 부팅시 오류 : UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY

구글코랩) 안전Dream 실종아동 등 검색 오픈API 소스를 공유합니다. (구글드라이브연동, 이미지 수집 소스)