메이븐다운(?) 방법으로 웹어플리케이션을 원격서버로 전송하기 위해서 이것저것 찾아보다가 알게 된 거 정리해본다.

1. deploy:deploy
packaging한 artifacts를 리모트의 메이븐저장소로 전송한다. 원격 저장소는  <distributionManagement>엘리먼트의 <repository>에 설정한다. 임의의 파일을 전송하는 건 불가능하다. package 가 war 이고 저장소 경로가 ftp://repository.mycompany.com/repository 라면, 실제로 war 파일은 저장소 layout에 맞춰서 ~/repository/groupId/artifactId/version 디렉토리에 전송된다.

2. site:deploy
 site phase에서 생성된 사이트를 리모트 (웹)서버로 전송한다. 리모트 서버정보는<distributionManagement>엘리먼트의 <site>에 설정한다. inputDirectory 옵션을 통해 target/site 디렉토리가 아닌 다른 디렉토리의 파일들을 전송할 수 있다. 그러나 <site>는 하나만 설정가능하기 때문에 2군데 이상의 서버로 파일들을 전송하는 건 불가능하다.

3. cargo 플러그인
일부 컨테이너에 대해 remote container에 expanded war(war 파일의 압축을 풀어놓은 것. exploded war)를 배포할 수 있다고 cargo 웹사이트에 나온다. 하지만 과연 이게 가능할지는 의구심이 든다. 실제로 작동여부를 테스트해봐야 할 듯하지만, 아마도 war 파일만 원격배포가 가능하지 않을까 싶다. 아직 최신 버전의 상용 WAS에 대한 지원이 미비하다.

4. myfaces의 wagon-maven 플러그인 
임의의 디렉토리 내의 파일들을 원격 서버로 전송한다. 임의의 디렉토리를 2군데 이상의 원격서버에 전송할 수 있다. 실제 프로젝트에서 개발서버 배포를 이 플러그인으로 처리했다. target/webapp 디렉토리의 파일들은 WAS서버로 전송하고, target/htdocs 디렉토리의 파일들은 WEB서버로 전송하도록 말이다. 
아쉽다면, 지정된 디렉토리 내의 모든 파일들을 전송하며 그 디렉토리의 몇몇 파일들만 골라서 전송할 수는 없다는 것이다. 즉 fileset 개념이 없다(사실 이건 이 플러그인의 문제라기 보다 이 플러그인이 이용하는 메이븐 wagon의 문제이다. 몇몇파일만 골라내는 건 ant copy를 써서 target/htdocs처럼 별도의 디렉토리에 전송할 대상만 따로 모아놓으면 해결할 수 있다).
이 플러그인의 장점이라면 디렉토리를 압축하여 전송후 리모트에서 압축을 해제하는 방식의 wagon 기능을 이용하기 때문에 전송할 파일이 많은 경우에 ant의 ftp/scp 타스크를 이용하는 것보다 전송시간이 현저히 줄어든다는 거.
아래는 실제 pom.xml의 일부인데 별거 아닌게 내용이 긴거 같아 맘이 편하지만은 않다.

   <plugin>
    <groupId>org.apache.myfaces.buildtools</groupId>
    <artifactId>myfaces-wagon-plugin</artifactId>
    <version>1.0.0</version>
    <executions>
     <!-- config 배포 작업 -->
     <execution>
      <id>deploy-conf</id>
      <phase>pre-integration-test</phase>
      <goals>
       <goal>deploy</goal>
      </goals>
      <configuration>
       <id>deploy-config</id>
       <url>
        scp://${wasserver.username}:${wasserver.password}@${wasserver.ip}:${wasserver.config.dir}
       </url>
       <inputDirectory>${config.home.dir}</inputDirectory>
      </configuration>
     </execution>
     <!-- 웹어플리케이션 배포 작업 -->
     <execution>
      <id>deploy-web</id>
      <phase>pre-integration-test</phase>
      <goals>
       <goal>deploy</goal>
      </goals>
      <configuration>
       <id>deploy-web</id>
       <url>
        scp://${wasserver.username}:${wasserver.password}@${wasserver.ip}:${wasserver.web.dir}
       </url>
       <inputDirectory>${web.output.exploded.dir}</inputDirectory>
      </configuration>
     </execution>
     <!-- 웹파일 배포 작업 -->
     <execution>
      <id>deploy-html</id>
      <phase>pre-integration-test</phase>
      <goals>
       <goal>deploy</goal>
      </goals>
      <configuration>
       <id>deploy-html</id>
       <url>
        scp://${webserver.username}:${webserver.password}@${webserver.ip}:${webserver.htdocs.dir}
       </url>
       <inputDirectory>${web.output.html.dir}</inputDirectory>
      </configuration>
     </execution>
    </executions>
   </plugin>


현재까지 패턴을 적용하여 임의의 파일/디렉토리를 내 맘대로 전송할 수 있는 방법은 메이븐에서는 antrun을 이용하는 방법밖에 없는 듯싶다. maven의 wagon api와 file management api 이용하여 직접 플러그인을 만드는 것도 재밌을거 같다.

Posted by 에코지오
,

메이븐의 wagon 기능을 통해서 리모트 머신에 파일을 전송할 때 wagon은 CVS 폴더까지 함께 압축해서 전송한다. 따라서 CVS로 관리되는 폴더를 전송하고자 한다면 전송해야할 파일들을 ant copy 등을 이용해서 빌드 결과 폴더(target)로 먼저 복사한 뒤 그것을 전송하는 것이 좋다. wagon은 ant의 defaultexcludes 옵션이 없다....

Ant에서는 고민꺼리가 아닌 것이 Maven에서는 고민이 된다... 메이븐의 배려가 아쉽다....

Posted by 에코지오
,

메이븐에는 wagon이라는 게 있는데 ftp, http, scp, webdav 같은 전송 프로토콜을 추상화한 것인데 site:deploy는 site 파일들을 리모트에 전송하기 위해 wagon 기능을 이용한다.  리모트 경로는 아래처럼 "프로토콜://~" 형식으로 설정하면 되며, 메이븐은 설정된 프로토콜에 적당한 프로바이더를 찾아서 파일을 전송해준다.

  <distributionManagement>
    <site>
      <id>www.yourcompany.com</id>
      <url>scp://www.yourcompany.com/www/docs/project/</url>
    </site>
  </distributionManagement>

site:deploy를 실행하고 콘솔에 찍히는 로그를 살펴보면 

- 로컬에서 .wagon12345.zip 과 같은 임시 zip 파일이 만들어진다
- zip 파일을 리모트 서버로 전송한다. ######## 표시가 늘어나는 식로 전송 진행상태를 보여준다.
- 리모트서버에서 unzip 명령으로 해당 경로에 압축을 풀고, 압축이 다 풀리면 zip 파일을 삭제한다.

그러니까 ant의 scp 타스크나 ftp 타스크가 지정된 fileset에 대해서 파일을 낱개로 하나씩 보내는 반면에,
wagon은 파일에셋을 로컬에서 압축하여 하나의 zip파일로 보낸 뒤 리모트에서 zip을 풀어내는,
나름 효율적인 방식으로 작동한다.

그러나 리모트에서 zip 파일을 푸는 방법에 문제가 있다. 리모트 서버에서 unzip이 없으면 에러가 발생하는 것이다.
실제로 지금 있는 프로젝트의 hp-ux 서버에는 unzip이 설치되어 있지 않았다.
(또 이상한 건 unzip 설치후 ssh 클라이언트로 접속해서 unzip을 실행해보면 잘 실행이 되는데도 불구하고,
wagon으로 파일을 전송해보면 unzip이 없다는 에러가 발생한다. unzip을 /usr/bin에 두어 해결은 했지만,
지금도 잘 이해가 되질 않는다. /usr/bin 이외의 다른 위치에 있으면 unzip이 없다는 에러가 발생한다는게..쫌...)

구걸링을 해보니 메이븐 1.x에서는 압축파일의 포맷과 압축해제 실행파일의 위치를 지정할 수 있게했다고 한다.
즉 tar로 묶는 것도 되고 gunzip으로 zip을 풀 수도 있었단 거다. 그러던 것이 메이븐 2.x에 와서 zip, unzip으로 고정이 돼버렸다.

http://jira.codehaus.org/browse/MSITE-30?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=147326#action_147326

황당한 생각에 wagon-ssh 프로바이더의 소스를 다운받아 까보니
org.apache.maven.wagon.providers.ssh.ScpHelper 클래스의 putDirectory() 메소드에
이렇게 하드 코딩이 돼있다.

executor.executeCommand( "cd " + path + "; unzip -q -o " + zipFile.getName() + "; rm -f " + zipFile.getName() );

왜 이렇게 fix 시켰을까?  막돼먹은 코딩인가? 아니면 관습의 강요인가?

Posted by 에코지오
,