예제 프로젝트 생성

이제 젠킨스에서 실제 빌드 작업 설정을 하기 위해 필요한 예제  프로젝트를 만들어 보자. 만들 프로젝트는 jar 라이브러리를 만드는 lib-hello 와 이를 사용하는 웹 프로젝트인 hello-webapp 라는 프로젝트이다.

먼저 lib-hello 프로젝트를 생성하고 버전 관리에 등록해 보자.

  1. 메이븐 아키타입 플러그인을 사용하여 jar 파일 프로젝트를 생성한다.

    mvn archetype:generate -B -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DgroupId=com.example -DartifactId=lib-hello -Dversion=1.0-SNAPSHOT

  2. 라이브러리 프로젝트이므로 패키징 형식은 jar 파일이며 메이븐에 디플로이한 후에 hello-webapp 프로젝트에서 이 아티팩트를 사용할 예정이다. 외부에서 사용할 메소드를 추가하기 위해 src/main/java/com/example/Hello.java 파일을 만들고 간단한 메소드를 작성하자.

    package com.example;
    
    public class Hello
    {
        public String getMessage( )
        {
            return "Hello";
        }
    }
    CODE
  3. nexus 연계 및 지속적인 통합 연계를 위해 메이븐의 pom 파일을 수정해 보자. 수정할 부분은 다음과 같다.

    1. 내부 넥서스 저장소 추가 : 전 장에서 구축한 내부 넥서스 저장소를 설정한다.

      <repositories>
        <repository>
          <id>public</id>
          <name>internal maven Repository</name>
          <url>http://nexus.example.com/content/groups/public/</url>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>central</id>
          <name>Maven Plugin Repository</name>
          <url>http://nexus.example.com/content/repositories/central/</url>
        </pluginRepository>
      </pluginRepositories>
      XML
    2. junit 버전 갱신 : 지속적인 통합시 자동화된 테스트를 빌드마다 수행하는게 좋다. 아키타입으로 프로젝트 생성시 junit 은 버전 3로 설정되므로 단위 테스트 작성이 쉬운 버전 4 로 변경해 보자. 

      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.1</version>
        <scope>test</scope>
      </dependency>
      CODE
    3. lib-hello 는 jar 이므로 넥서스에 바로 디플로이 할수 있도록 <distributionManagement> 항목을 설정한다. 별도의 저장소와 계정을 만들었다면 해당 정보로 수정한다.

      <distributionManagement>
        <repository>
          <id>releases</id>
          <url>http://nexus.example.com/content/repositories/releases</url>
        </repository>
        <snapshotRepository>
          <id>snapshots</id>
          <url>http://nexus.example.com/content/repositories/snapshots</url>
        </snapshotRepository>
      </distributionManagement>
      CODE
    4. distributionManagement에 맞게 .m2/settings.xml 에 인증 정보를 설정한다.

      <servers>
        <server>
          <id>releases</id>
          <username>deployment</username>
          <password>deployment123</password>
        </server>
        <server>
          <id>snapshots</id>
          <username>deployment</username>
          <password>deployment123</password>
        </server>
      </servers>
      CODE
  4. 빌드때마다 돌릴 간단한 테스트 코드를 작성해 보자. 이 테스트 코드는 위에서 작성한 Hello.java 를 테스트하는 HelloTest.java 이다. 메이븐의 표준 디렉터리 구성에 맞게 src/test/java/com/example/HelloTest.java 파일로 저장하자.

    package com.example;
    import static org.junit.Assert.assertTrue;
    import org.junit.Test;
    public class HelloTest
    {
        @Test
        public void testHello( )
        {
            Hello h = new Hello();
            assertTrue(h.getMessage().contains("Hello"));
        }
    }
    CODE
  5. 이제 모든 준비가 끝났다. 정상적으로 동작하는지 메이븐 빌드를 돌리고 저장소에 디플로이 해 보자.

    mvn clean deploy

    2개의 테스트 케이스가 통과하면 스냅샷 저장소에 디플로이 하는 것을 확인할 수 있다.

    메이븐 실행 결과

이제 프로젝트 빌드가 성공했다면 소스를 버전 관리에 추가할 시점이다. 하지만 지금은 메이븐 빌드로 인해 아티팩트가 생성 되었고 지금 추가하면 컴파일된 클래스와 아티팩트가 버전 관리에 추가되어 버린다.

흔히 하는 실수로 컴파일해서 나오는 바이너리와 아티팩트를 버전 관리에 추가하는 건 좋지 않으므로 깨끗하게 지우자. 메이븐의 clean 골을 실행하는 명령어인 mvn clean 을 실행하거나 또는 target 디렉터리를 삭제하면 된다.

이제 버전 관리 서버에 소스를 추가해 보자. 

서브버전을 사용하는 독자들은 서브버전 장에서 익힌 svn import 명령어를 사용하고 git 이나 gitlab 사용 독자들은 각각의 저장소에 프로젝트를 생성해 보자.

원격지에 있는 버전 관리 서버에 넣어서 실제 환경과 동일하게 구성하는게 더 좋지만 그렇지 않다면 간단하게 젠킨스가 구동되는 서버에서 젠킨스 계정으로 버전 관리 저장소를 구성해도 된다.

아직 원격 버전 관리 서버가 구축되지 않았다면 간단하게 로컬에서 환경을 만들어도 된다.

서브버전 사용자라면 다음과 같은 절차에 따라서 빌드할 프로젝트를 버전 관리 저장소에 임포트 해 보자.

서브버전 저장소 연결 방식이 file:/// 일 경우 서브버전이 1.8 이면 젠킨스와 연계할 수 없다.

서브버전 1.8 부터 저장소의 로우 레벨 포맷이 변경 되었지만 젠킨스의 서브버전 플러그인은 1.7 이므로 file:// 방식의 저장소를 읽을 수 없다.

이를 해결하려면 다음과 같은 방법이 있다.

  1. 서브버전 패키지를 1.7 로 다운그레이드 (권장하지 않음)
  2. svnadmin create 로 로컬 저장소 생성시 하위 호환성 옵션으로 생성 (권장)
    svnadmin create ~/svnrepos  --compatible-version 1.7 
  3. file:/// 방식대신 http:// 나 https:// 방식의 저장소 연결 방식을 사용(권장)

  1. 서브버전 저장소 생성

    svnadmin create ~/svnrepos

  2. lib-hello 프로젝트 디렉터리로 이동한다.

    cd lib-hello

  3. 소스를 서브버전 저장소에 임포트한다. 저장소가 로컬이므로 URL 은 file:/// 이 붙어야 한다. 저장소 경로는 서브버전 관례에 따라 lib-hello/trunk 에 넣는다. ${HOME} 는 사용자의 홈 디렉터리를 의미하는 환경 변수이다.

    svn import . file:///${HOME}/svnrepos/lib-hello/trunk -m "project import"

  4. 정상적으로 임포트되었다면 원래 소스 디렉터리인 lib-hello 는 삭제하거나 이름을 변경한다.

    cd ..

    mv lib-hello lib-hello-org

  5. 서브버전 저장소에서 소스를 체크 아웃 해 본다. 체크 아웃하는 URL 은 젠킨스의 작업 설정에 꼭 필요하므로 잘 기억해 두자.

    svn co file:///${HOME}/svnrepos/lib-hello/trunk lib-hello

깃 사용자라면 더 간단하게 로컬에 저장소를 만들수 있다.

  1. lib-hello 프로젝트 디렉터리로 이동한다.

    cd lib-hello 

  2. git 저장소를 초기화한다.

    git init 

  3. 프로젝트 파일과 디렉터리를 스테이징 영역에 추가한다.

    git add pom.xml src/ 

  4. 변경 내역을 커밋한다.

    git commit -m "first commit" 

깃도 젠킨스에서 클론해야 하므로 URL 이 필요하다. 다음 로컬의 저장소 URL 을 기억해 두자. (경로는 독자마다 다를 수 있다.)

file:///${HOME}/lib-hello


이제 lib-hello 프로젝트를 사용하는 웹 app 인 hello-webapp 프로젝트를 생성해 보자. 역시 메이븐의 아키타입을 사용하여 프로젝트 초기 구성을 할 수 있다.

mvn archetype:generate -B -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.example -DartifactId=hello-webapp -Dversion=1.0

정상적으로 메이븐이 실행됐다면 hello-webapp 라는 디렉터리가 생성됐을 것이다.

이제 프로젝트 구조에 맞게 메이븐 설정 파일인 pom.xml 을 수정해 보자.  수정해야 하는 항목은 다음과 같다.

  • lib-hello 의존성 추가 : lib-hello 를 사용하므로 <dependency> 항목에 lib-hello 를 추가하자.

    <dependency>
      <groupId>com.example</groupId>
      <artifactId>lib-hello</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    CODE
  • jUnit 버전 갱신: 아키타입으로 생성하면 jUnit 3 가 설정되므로 4로 변경하자.

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>
    CODE
  • 내부 넥서스 저장소 추가 : lib-hello 아티팩트는 내부 넥서스 저장소에 있으므로 저장소 설정이 제대로 되지 않으면 lib-hello 찾지 못해서 빌드를 하지 못하므로 제대로 설정하자.

    <repositories>
      <repository>
        <id>public</id>
        <name>internal maven Repository</name>
        <url>http://nexus.example.com/content/groups/public/</url>
      </repository>
    </repositories>
    <pluginRepositories>
      <pluginRepository>
        <id>public</id>
        <name>Maven Plugin Repository</name>
        <url>http://nexus.example.com/content/groups/public/</url>
      </pluginRepository>
    </pluginRepositories>
    CODE

편집이 끝났으면 저장하고 메이븐으로 프로젝트를 빌드 해서 정상 설정 여부를 확인해 보자.

mvn clean package

빌드가 성공했다면 설정이 정상적으로 이루어진 것이다. lib-hello 를 찾지 못한다면 저장소가 잘못 설정되었거나 아티팩트의 정보(groupId, arfitactId, version 등)가 잘못 설정되었을 소지가 높다.

다음과 같은 순서로 원인을 찾고 문제를 해결해 보자.

  1. 넥서스에 아티팩트가 존재하는지 확인한다. 웹 브라우저로 연결하여 저장소내 아티팩트를 직접 확인해 보면 편리하다.
  2. 저장소의 URL 을 확인한 후에 pom.xml 에 설정한 정보와 일치하는지 확인한다.

보통 이쯤에서 문제가 해결되지만 계속 아티팩트를 못 찾는다면 넥서스에 아티팩트가 디플로이 되기 전에 메이븐 빌드를 수행해서 문제가 될 수 있다.

메이븐은 로컬 저장소에 아티팩트 정보를 캐싱하는데 릴리스 저장소일 경우 재확인하는 시간의 간격이 매우 길다.

메이븐 실행시 넥서스에는 lib-hello 아티팩트가 없었다면 메이븐은 로컬 저장소에 아티팩트에 "Not Found" 정보를 설정하고 일정 시간동안 계속 캐싱하고 있는다.

이후에 넥서스에 lib-hello 아티팩트가 디플로이되도 메이븐은 캐싱 정보만 사용하여 아티팩트가 없다고 표시할 수 있다. 이런 경우 다음과 같은 두 가지 방법으로 해결해 볼 수 있다.

  1. 로컬 저장소의 아티팩트 캐싱 정보 삭제
    $HOME/.m2/repository 밑에 그룹ID 형식으로 디렉터리가 생성되어 있다.  ~/.m2/repository/com/example/ 디렉터리를 삭제하면 메이븐이 넥서스에 새로 접속하므로  문제가 해결될 수 있다.
  2. 메이븐 실행시 강제 업데이트 옵션인 -U 추가
    메이븐의 로컬 저장소 캐시를 사용하지 않도록 -U 옵션을 추가하여 실행

이제 문제가 해결되고 정상 빌드되었다면 버전 관리에 임포트 해보자.

먼저 서브버전 사용자이다. 로컬 저장소는 위에서 이미 생성했으므로 임포트만 하면 된다.

  1. hello-webapp 프로젝트 디렉터리로 이동한다.

    cd hello-webapp 

  2. 프로젝트 소스를 서브버전 저장소의 hello-webapp/trunk 경로에 임포트 한다.

    svn import . file:///${HOME}/svnrepos/hello-webapp/trunk -m "project import" 

  3. 정상적으로 임포트되었다면 원래 소스 디렉터리인 hello-webapp는 삭제하거나 이름을 변경한다.

    cd ..

    mv hello-webapp hello-webapp-org 

  4. 서브버전 저장소에서 소스를 체크 아웃 해본다. 체크 아웃하는 URL 은 젠킨스의 작업 설정에 꼭 필요하므로 잘 기억해 두자.

    svn co file:///${HOME}/svnrepos/hello-webapp/trunk hello-webapp 

깃 사용자도 hello-webapp 프로젝트를 로컬 저장소에 추가하자.

  1. hello-webapp 프로젝트 디렉터리로 이동한다.

    cd hello-webapp 

  2. git 저장소를 초기화한다.

    git init 

  3. 프로젝트 파일과 디렉터리를 스테이징 영역에 추가한다.

    git add pom.xml src/ 

  4. 변경 내역을 커밋한다.

    git commit -m "first commit" 

이제 젠킨스에서 클론할수 있게 다음 로컬 저장소 URL 을 기억해 두자. (경로는 독자마다 다를 수 있다.)

file:///${HOME}/hello-webapp