 |  |
|
난이도 : 초급 Paul Duvall, CTO, Stelligent Incorporated
2007 년 12 월 04 일 Ant는 명실상부한 자바™ 플랫폼을 위한 빌드 툴입니다; 하지만, XML에 부족한 보다 표현적인 패러다임을 지원하는 다른 빌드 툴들이 생겨나고 있습니다.
사람을 위한 자동화
시리즈에서는, 자동화 전문가 Paul Duvall이 Ruby를 기반으로 구현된 빌드 플랫폼인 Raven이 빌드 중심의 Domain Specific Language의 단순함과 완벽한 프로그래밍 언어의 힘을 어떻게 활용하는지를 설명합니다.
필자는 기존의 자바 프로젝트를 갖고 있고, 지난 몇 년 동안, 이 프로젝트를 위해 Ant 빌드 스크립트를 성실히 관리했다. 필자는 Ant에 사용할 수 있는 많은 태스크들을 좋아하지만, 가끔 Ant 스크립트의 XML 신택스가 작성하기에는 다소 성가시다고 생각했다. 더욱이, Ant의 XML은 표현력(expressiveness)에 있어서는 한계를 드러냈다. 사실, 더 높은 수준의 유연성이 필요할 경우, 커스텀 태스크를 작성하거나 Groovy 같은 것을 사용하여 Ant script 태스크 안에 로직을 삽입해야 한다.
표현성의 부족
 |
시리즈 소개 개발자로서, 사용자를 위해 프로세스를 자동화 하고 있습니다. 하지만, 정작 우리들 자신의 개발 프로세스를 자동화 할 수 있는 기회를 간과하고 있습니다. 따라서,
사람을 위한 자동화
시리즈에서는 소프트웨어 개발 프로세스를 자동화 하는 방법을 연구하고, 자동화를 적용할 시기와 방법을 설명합니다. |
|
몇 년 전에, 소프트웨어 구현에 보다 표현적인 툴을 찾기 위해서 필자는 Rake를 배웠다. Rake는 완벽한 Ruby 프로그래밍 언어를 사용하여 소프트웨어를 구현할 수 있는 Domain Specific Language (DSL)이다. Rake를 통해 필자는 표현성을 얻었다. Rake 빌드 스크립트는 Ruby이기 때문에(XML과는 반대), 커스텀 태스크를 작성할 필요가 없다. 따라서, 일부 조건 로직이 필요하면, 필요한 곳에 이것을 쉽게 코딩할 수 있다. 더욱이, Rake는 Ant와 이것의 조상 격인 make와 비슷한 의존성 기반 태스킹 시스템을 적용한다. 예를 들어, rake deploy를 타이핑 하면, Rake는 필자가 설정했던 종속 태스크, 이를 테면, 컴파일, 테스트 실행을 호출한다. Rake는 종속 태스크들을 단 한번 실행하기에는 알맞다. (따라서 Ant와 똑같다.)
Rake는 모든 자바 프로젝트에 다 유용한 것은 아니다. 하지만, Raven이라고 하는 비교적 새로운 프로젝트는 Rake의 힘과 표현성을 자바 애플리케이션 구현을 위한 태스크와 결합시켰다. Raven을 통해, javac을 이용한 컴파일과, jar와 war를 이용한 압축 바이너리, Ruby 프로그래밍 언어의 풍부한 표현력 등 자바 중심의 기능을 제공하는 진정한 빌드 플랫폼이 자바 개발자에게 생긴 것이다.
 |
DSL이란 무엇인가? Domain Specific Language (DSL)는 특정 태스크를 위한 프로그래밍 언어이다. 자바 언어와 Ruby가 범용 프로그래밍 언어인 반면, Ant와 Rake는 소프트웨어 구현 전용의 DSL이다. Rake는 Ruby로 작성되고 Ruby를 사용하여 확장될 수 있기 때문에 내부 DSL로 간주된다. 반면, Ant는 파싱 된 후 다른 언어로 실행되기 때문에 외부 DSL이라고 한다. (XML은 파싱된 후 자바 프로그래밍을 통해서 실행된다.) |
|
Raven은 Rake이고, Rake는 Ruby이다.
자바 프로젝트용 Raven을 사용하기 전에, Raven과 Rake의 관계를 이해하는 것이 중요하다. 그림 1은 Raven의 논리적 다이어그램이다. 여러분도 보다시피, Raven은 Rake, RubyGems, Ruby를 사용한다. 따라서, 네이티브 Rake 태스크는 Raven을 사용할 때 사용할 수 있다. 게다가, Raven 스크립트 안에서 Ruby를 사용할 수도 있다. RubyGems는 필요한 Ruby 패키지(자바 jar)와 종속물들을 다운로드 하는데 사용될 수 있는 CPAN, RPM, APT와 비슷하다.
그림 1. Raven의 논리적 다이어그램
Raven이 자바 프로젝트를 구현하는데 최상의 플랫폼인지는 확실치 않지만, Raven은 단순하지만 강력한 결합을 통해 보다 자연스러운 소프트웨어 구현을 위한 프로그래밍 언어가 되어가고 있다고 확신한다. 여러분이 필자에게 묻는다면, 자바 프로젝트를 구현할 때 XML에 의존할 필요가 없다는 자체도 Raven을 높이 평가할 근거가 된다.
Raven이 여러분을 기다리고 있다!
Raven 설치와 설정에는 두 가지 방법이 있다. 첫 번째는 Ruby 방식이고, 두 번째는 JRuby를 사용하는 자바 스타일이다. 필자는 자바 방식을 더 선호한다. 설정이 더 간단하기 때문이다. 다음은 Raven 설치와 실행의 단계이다:
- Raven/JRuby를 다운로드 한다. (참고자료).
- 워크스테이션의 한 위치에 파일의 압축을 푼다.
-
JRUBY_HOME이라고 하는 환경 변수를 만든다.
-
PATH 환경 변수에 JRUBY_HOME/bin을 추가한다.
- 명령어 프롬프트를 열고
jruby -version을 입력하여 설치를 확인한다. 모든 것일 올바르게 설치되었다면, 명령어 창에 ruby 1.8.5 (0) [java]가 보일 것이다.
Hello, Raven
물론, Raven의 다운로드와 설치는 그렇게 재미있는 것은 아니다. Raven의 정수는 빌드 스크립트를 만들 때의 유연성이다. Raven 세계에서, 빌드 파일을 Rakefiles라고 하고, 이들은 간단한 포맷이다. 사실, Ruby로 프로그래밍을 해봤다면(또는 Ruby 코드를 본 적이 있다면), 매우 익숙할 것이다. 어쨌든 이것이 Raven의 강점이다. 이것이 바로 Ruby이다. — 다만 특별한 단어가 여기 저기에 삽입되었을 뿐이다.
Raven을 빠르게 시작하기 위해, 가장 기본적인(그리고 중요한) 태스크인 컴파일부터 수행할 것이다. 그림 2의 디렉토리 구조는 필자의 자바 프로젝트 레이아웃이다. 필자의 서드 파티 라이브러리와 소스 코드가 있는 곳을 파악하라.
그림 2. 기존 자바 프로젝트의 디렉토리 구조
그림 2의 lib 디렉토리를 주목하라. 이곳이 서드 파티 JAR가 있는 곳이다. 컴파일 하기 전에, 경로를 만들어야 하는데, Raven을 사용하면 매우 쉬다. dependency 태스크를 통해 classpath를 생성하는 기능을 지원하기 때문이다. (이것은 실제로 dependency라고 하는 Raven에서 제공하는 Ruby 메소드이다.) (Listing 1):
Listing 1. Raven으로 classpath 만들기
require 'raven'
require 'rake'
dependency 'deps' do | task |
task.libs = Dir.glob('lib/**/*.*')
end
|
deps 종속 태스크는 Listing 1에 정의된 것처럼, Dir 클래스와 glob() 메소드를 사용하여 lib 디렉토리에 모든 라이브러리를 포함시킨다. 필자는 또한 종속 태스크를 사용하여 저장소(Maven의 종속 관리 메커니즘과 비슷함)에서 JAR를 다운로드 할 수 있다. (RubyGems를 사용함)
Listing 1에서, 필자는 경로의 일부로서 lib 디렉토리에 있는 무엇이든 포함시켰다. 이 태스크 이름을 deps로 했고 (Listing 2), 컴파일 하기 전에 이 태스크를 분명하게 실행시킬 수 있다:
Listing 2. 간단한 컴파일
javac 'compile' => 'deps' do |task|
task.build_path << "src"
end
|
여러분도 보다시피, Raven의 javac 태스크를 통해 컴파일을 수행하고 있다. 이 태스크는 compile이며, Listing 1의 deps 태스크에 의존하고 있다. => 심볼이 의미하는 것은, Raven이 현재 태스크 전에 이 연산자의 오른쪽으로 태스크(태스크들)을 실행할 것이라는 것을 의미한다. (Ant의 target 엘리먼트의 depends 애트리뷰트와 흡사함.)
javac 태스크의 do와 end 사이에서 모든 마법이 발생한다. 기본적으로, javac 태스크는 build_path의 기본 값으로서 "src/main/java"를 사용한다. 하지만, 필자의 자바 프로젝트는 이러한 규약을 따르지 않기 때문에(그림 2?), build_path 프로퍼티를 수정해야 한다. 필자의 경우, src이다. 이곳에 소스 코드가 있기 때문이다.
이 Raven 스크립트를 테스트 하려면, 명령 프롬프트를 열고 rake compile을 타이핑 해야 한다. 컴파일의 결과로서 생성된 .class 파일은 target/classes 라고 하는 디렉토리에 놓이게 되는데, 이것은 javac Raven 태스크에 의해 자동으로 생성된다.
작은 것이 강하다!
이 시점에서 한 가지 확실히 해 둘 것이 있다. 컴파일 하기 위해 많은 코드를 작성하지 안았다. Raven이 뒤에서 target/classes 디렉토리 생성하기, 결과 클래스 파일을 이 위치에 복사하기 같은 몇 가지 작업을 처리했기 때문이다. 사실, 여러분은 이미 Listing 1과 Listing 2의 Ant 스크립트가 어떤 모습인지를 벌써 잊었을 것이다. Listing 3은 Ant 빌드 스크립트를 사용한 전형적인 컴파일이다:
Listing 3. Ant를 사용한 자바 소스 코드 컴파일
<?xml version="1.0" encoding="iso-8859-1"?>
<project name="compile-code" default="all" basedir=".">
...
<target name="compile-src">
<mkdir dir="${classes.dir}"/>
<javac destdir="${classes.dir}" debug="true">
<src path="${src.dir}" />
<classpath refid="project.class.path"/>
</javac>
</target>
<project>
|
Listing 3과 Listing 1, Listing 2를 비교해 보면 뚜렷한 차이를 알 수 있다. Raven이 XML을 없앨 뿐만 아니라, 몇 가지 기본적인 애트리뷰트를 담당하여, 태스크를 정의할 때 더욱 적게 하게 된다. 더욱이, Listing 2에서 보듯, Raven은 Raven이 담당하는 측면들을 오버라이드 할 수 있다.
Listing 1과 2가 비교의 관점에서 볼 때 확실히 흥미롭지만, 컴파일은 그 시작에 불과하다. 더 재미있는 기능인 자바 웹 애플리케이션의 패키징에 대해 알아보자.
간단한 WAR 파일 생성
Web Archive (WAR) 파일은 웹 애플리케이션을 패키징 하고, 서블릿, 서드 파티 라이브러리, 이미지 같은 다양한 에셋들을 포함하고 있다. 이러한 압축 파일은 표준 디렉토리 네이밍 스킴을 사용하고, web.xml (서블릿 이름과 다른 설정 측면들로 매핑됨) 같은 특정 파일이 WEB-INF 디렉토리에 있을 것으로 기대한다.
Raven을 사용하면 WAR 파일 생성이 매우 쉽다. Listing 4에서, 필자는 'brewery.war'라는 이름을 가진 war 태스크를 사용하고 있는데, 이것은 기본적으로 같은 이름을 가진 WAR 파일을 만든다. webapp_dir의 기본 위치는 src/main/webapp이지만, 필자의 디렉토리 구조는 Raven과는 다르기 때문에 task.webapp_dir = 'src/web'라인을 사용하여 수정해야 한다.
Listing 4. WAR를 생성하여 웹 컨테이너에 전개하기
war 'brewery.war' => ['clean', 'compile', 'java-doc'] do |task|
task.webapp_dir = 'src/web'
end
|
WAR 파일이 생성되기 전에, Raven은 먼저 clean 태스크, compile 태스크, 문서 생성 태스크를 차례로 실행해야 한다. 이러한 태스크들이 성공적으로 실행된 후에, Raven은 압축 파일을 생성할 수 있는데, 약간의 타이핑이 필요하다. 사실, 필자의 프로젝트가 Raven의 기본 디렉토리 레이아웃을 따른다면, 그러한 종속 태스크 외에 어떤 것도 작성할 필요가 없었을 것이다. (do와 end 사이의 코드가 필요하지 않다!)
믿거나 말거나 지만, 이것이 전부이다. — Raven의 war 태스크는 디렉토리 생성, 파일 배치, WAR 파일 생성을 핸들한다. 매우 효율적이지 않은가?
 |
Raven, Rake, Ruby..어떤 것인가? 모두 해당한다. Rake는 Ruby를 사용하여 프로젝트를 구현하는 DSL이다. Raven은 Rake를 사용하여 자바 프로젝트를 구현하는데 필요한 자바 중심의 기능을 제공한다. Raven을 사용하여, Rake와 마찬가지로, 빌드 스크립트 내에서 완전한 Ruby 프로그래밍 언어로 접근할 수 있다. |
|
문서를 쉽게 생성하기
프로젝트 문서를 생성하는 것은 팀 멤버들에게 도움이 되는 정보를 배포하는데 유용하다. 다른 사람들도 사용할 수 있는 프레임웍 코드나 유틸리티를 작성하고 있다면, 클래스, 메소드, 퍼블릭 인스턴스 변수들을 기술하고 있는 HTML 파일로 된 Javadoc을 만들어야 한다.
Javadoc 메커니즘을 사용하여 문서를 생성하는 일은 Raven을 사용하면 매우 쉽다. (Listing 5):
Listing 5. Raven을 사용하여 Javadoc 문서 생성하기
javadoc 'java-doc' => 'deps' do |task|
task.build_path << "src"
end
|
필자의 프로젝트는 Raven의 모델을 따르지 않기 때문에, javadoc 태스크의 build_path 프로퍼티를 수정해야 한다. 또한, 이 태스크는 deps 태스크에 의존(Listing 1)하여, 어떤 클래스 레퍼런스라도 포함시킨다.
프로젝트가 Raven의 원하는 레이아웃을 따른다면, 여러분의 빌드 스크립트는 훨씬 더 단순해진다!
추가 설명!
지금까지 Raven의 몇 가지 기능들을 설명했지만, 이 혁신적인 빌드 플랫폼으로 할 수 있는 일은 더 많이 있다. 특히, 빌드 시 버전화 된 바이너리들의 자동 다운로드를 위한 메커니즘인 RubyGems를 사용하여 빌드 종속물(서드 파티 라이브러리)을 핸들하는 것이 Raven에서는 지원된다. RubyGems는 Maven과 Ivy와 비슷한 방식으로 서드 파티 라이브러리를 핸들한다.
RubyGems 외에도, Raven은 JUnit 테스트를 실행하고, 일반 JAR 파일을 구현하며, 디렉토리를 청소할 수 있다. 표 1은 자바 프로젝트를 구현하는 Raven에서 가능한 일반적인 태스크들이다:
표 1. 대표적인 (유용한) Raven 태스크들
| 태스크 | 설명 |
|---|
javac
| 자바 소스 파일을 컴파일 하고, 결과 클래스 파일들을 target/classes 디렉토리에 배치한다. |
jar
| JAR 파일을 생성하는데, 이것은 .class 파일의 컬렉션이다. |
war
| 자바 웹 컨테이너에 전개할 수 있는 웹 애플리케이션 압축 파일을 생성한다. |
javadoc
| 소스 코드에서 Javadoc을 만든다. |
junit
| JUnit 테스트를 실행한다. |
jar_source
| 자바 소스 파일에서 JAR 파일을 생성한다. |
gem_wrap_inst
| JAR 파일을 RubyGem으로 변형하고, 이 파일을 저장소에 설치한다. |
Raven이 성숙해 가면서, 표 1 역시도 성장할 것이다. 또한, Raven에 여러분이 필요로 하는 기능이 없다면, 여러분 스스로 작성해도 무방하다!
맺음말
빌드 스크립트 안에서 Ruby 언어의 힘과 유연성을 활용할 수 있도록 하는 Raven의 강점을 충분히 알았을 것이라 믿는다. Raven이 자바 프로젝트를 구현하는데 있어 잘 쓰이든 아니든, 필자는 Raven이 올바른 방향으로 가고 있다고 확신한다. 특히, Raven은 명령 프로그래밍 언어들(XML 같은 선언적 언어와는 다름)로 종속 기반의 태스크를 실행한다. 직접 해 보면 필자의 말이 더욱 잘 이해될 것이다.
참고자료 교육
-
Raven: Ruby를 이용한 자바 빌드 스크립트
(Matthieu Riou, Apress, 2007)
- "Rake 빌드 언어 사용하기" (Martin Fowler, martinfowler.com, 2005년 8월)
- "Ruby off the Rails" (Andrew Glover, developerWorks, 2005년 10월): Ruby 이해하기
- "아파치 메이븐 2 시작하기 (한글)" (Sing Li, developerWorks, 2007년 5월): 이 튜토리얼로 메이븐 2를 시작해 보자.
- "
Practically Groovy: Groovy를 사용한 Ant 스크립팅" (Andrew Glover, developerWorks, 2004년 12월)
- "What's after Ant?" (Andrew Glover, thediscoblog.com, 2007년 4월)
-
사람을 위한 자동화
(Paul Duvall, developerWorks): 모든 시리즈 보기.
-
developerWorks: 자바 프로그래밍과 관련된 다양한 기술자료 보기.
제품 및 기술 얻기
토론
필자소개
기사에 대한 평가
 |
| 이 문서 북마킹 하기
|
|  |