Maven에서 패키징은 package 단계(phase)에서 수행됩니다. pom.xml에 지정된 jar,war,ear 등의 packaging 타입에 따라서 적절한 파일들을 모아서 묶어냅니다. Buildr의 패키징도 메이븐만큼 쉽습니다.
먼저 컴파일된 클래스들을 모아 jar 파일로 묶어보죠.
buildr package 명령을 실행하면 default로 target 디렉토리에 "#{project.name}-#{project.version}.jar' 파일이 만들어집니다. 파일의 이름을 바꾸고 싶으면 :file 옵션을 추가합니다.
package 메소드가 입력받는 type에는 :zip, :jar, :war, :ear, :tar, :sources, :javadoc 등이 있습니다.
이번에는 웹어플리케이션을 war 로 묶어봅니다. (위의 package :jar 문을 지우지 않아도 됩니다. package 메소드는 여러번 사용가능하고, package 타스크는 각각의 패키지 파일들을 모두 만들어줍니다)
:jar 타입과 마찬가지로 default로 target 디렉토리에 "#{project.name}-#{project.version}.war' 파일이 만들어집니다. 만들어진 war 안에는 3가지 유형의 파일들이 포함됩니다.
(1) path_to(:source, :main, :webapp) 디렉토리 밑의 모든 파일들 : war 루트에 포함됨
(2) compile.target 디렉토리와 resources.target 디렉토리의 파일들 : WEB-INF/classes 에 포함됨
(3) compile.dependencies 아티펙트 파일들 : WEB-INF/lib 에 포함됨
여기서 메이븐과의 차이가 보입니다. 메이븐은 war 타입의 프로젝트에 대해서 패키징을 할 때 war:war 골이 실행되는데, war:war 골은 원본 webapp 디렉토리(src/main/webapp)의 파일들을 war로 묶지 않습니다. 대신 war:exploded 골에 의해 'target/프로젝트명' 디렉토리'로 빌드(복사)된 파일들을 war로 묶게 됩니다.
이것은 이클립스의 WTP가 웹어플리케이션을 빌드하는 것과 유사합니다. java 소스를 컴파일하여 class를 만들듯이, html, jsp 같은 웹파일들도 별도의 디렉토리에 빌드한다는 개념이 들어있습니다. 그래서 컴파일/빌드된 파일들만을 가지고 패키징을 합니다.
그러나 Buildr에는 메이븐의 war:exploded에 해당하는 작업이 없습니다. 메이븐 war 패키징이 war:exploded => war:war 순서로 진행된다면, Buildr의 war 패키징은 war:inplace => war:war 순서로 진행하는 것과 같습니다. 제 생각에는 메이븐 방식이 더 나아보입니다. 그래야 원본 웹파일들을 건드리지 않고 리소스 치환 같은 가공작업을 추가로 수행할 수 있기 때문입니다.
다행히도 Buildr의 유연성 덕분에 war 안에 기본적으로 패키징되는 webapp 디렉토리를 쉽게 바꿀 수 있습니다. (일단 원본 웹파일들은 target/webapp 으로 복사된다고 가정합니다. filter 메소드로 간단히 처리가능하죠.)
package(:war).exclude(_(:source, :main, :webapp)).include(_(:target, :main, :webapp), :as=>'.')
include와 exclude 메소드를 이용해서 쉽게 작업을 마쳤습니다. include 메소드에서 :as 옵션을 통해 target/webapp 폴더의 내용물이 war 파일의 최상위에 위치하게 했습니다. 그렇지 않으면 war 파일에 webapp 폴더 자체가 들어가게 됩니다. 이런게 귀찮으면 with 메소드를 쓰면 간단해집니다. package(:war).with _(:target, :main, :webapp)
위에서 compile.dependencies의 아티펙트 파일들이 war 안의 WEB-INF/lib 경로에 자동으로 함께 묶인다고 했습니다. 근데 WEB-INF/lib 경로에 함께 묶여서는 안되는(묶일 필요가 없는) 아티팩트 파일들이 존재할 수 있습니다. 메이븐으로 치자면 provided 나 system 스코프의 의존 라이브러리들이 이에 해당합니다. 이경우 이렇게 빼주시면 됩니다.
또는 컴파일 의존 라이브러리 설정시 provided 스코프와 system 스코프의 라이브러리들을 변수에 할당하여 사용하는 것이 깔끔한 것같네요.
SYSTEM_DEPENDENCIES = [스펙a,스펙b,...]
compile.with PROVIDED_DEPENDENCIES, SYSTEM_DEPENDENCIES,
'org.apache.axis2:axis2:jar:1.2',
transitive('org.acegisecurity:acegi-security:jar:1.0.5')
package(:war).libs -= artifacts(SYSTEM_DEPENDENCIES, PROVIDED_DEPENDENCIES)
package 타스크의 실행 순서와 관련하여 주의할 점이 있습니다. package 메소드는 타스크를 리턴합니다. 예를 들어, package :war 문은 WarTask 타스크 객체를 리턴합니다. 그런데 타스크를 리턴하기 전에, 방금 생성된 타스크를 프로젝트 'package' 타스크의 선행(의존) 타스크로 추가합니다. 따라서 package 타스크 실행전에 어떤 작업을 해야한다면, 그 작업에 대한 의존관계 문장은 package 메소드 문장보다 위에 와야합니다.
package :war, :file=>'target/myproject.war'
task :package=>[:before_package]
# (2) before_package 타스크가 실행된 후에 war 파일이 만들어집니다.
task :package=>[:before_package]
package :war, :file=>'target/myproject.war'
또하나 package 타스크에 후행 작업을 정의할 때 package 메소드를 쓰면 안됩니다. compile, build 같은 타스크의 경우는 compile do ~~~ end 식으로 써도 되지만, package 타스크는 task 메소드로 package 타스크를 찾아서 추가 액션을 넣어 주어야합니다.
... ...
end
'Build&Deploy > Buildr' 카테고리의 다른 글
Buildr : 설정정보 관리 (0) | 2008.12.24 |
---|---|
Buildr : 코드분석 리포트 생성 (0) | 2008.12.23 |
Buildr : 아티팩트 다운로드 받기 (0) | 2008.12.17 |
Buildr : 타스크 의존 관계 (0) | 2008.12.11 |
Buildr : 리소스 교체 (3) | 2008.12.09 |