빌드 도구와 메이븐

빌드 도구

빌드 도구란?

개발 환경의 변화와 빌드

자바를 처음 공부할 때는 이클립스 혹은 인텔리제이 같은 IDE만으로 프로그램을 뚝딱 만들 수 있다. 그러나 현업에 투입되면 무언가 복잡한 환경을 만나게 된다.

하지만 실제 자바 입문시절에 배운 과정과 현업에서 사용하는 과정에 차이는 없다. 다만 다양한 도구를 사용하여 더 전문화하여 현업 도구에 활용할 뿐이다.

  • 명령행에서 컴파일하기
    아주 간단한 프로그램이라면 명령행에서 javac를 이용하는 것만으로도 충분하다. 하지만 라이브러리 등을 이용하면, classpath에 다수의 라이브러리 경로를 기술한 뒤에 컴파일 해야 한다. 또한 생성된 클래스 파일을 모아 JAR 파일을 생성하려면 이 역시 모두 명령어로 실행해야 한다.
    소스 코드의 컴파일에서 JAR 파일의 생성까지 긴 과정을 수행하려면 방대한 명령어가 필요한데, 이를 매번 수작업으로 작성하면 큰 수고가 든다.
  • 프로젝트 및 라이브러리 설치
    최근에는 개발할 때 모든 프로그램을 처음부터 만드는 경우가 거의 없다. 프로그램에 필요한 기능은 라이브러리를 이용하거나, 프레임워크를 이용하여 애플리케이션을 개발한다.
    이런 경우, 필요한 소프트웨어를 갖추고 정해진 대로 파일을 구성해야 한다.
  • 테스트 자동화
    단순한 프로그램이라면 컴파일 후 실행 및 동작만 확인하는 것으로 충분하지만, 어느 정도 규모 있는 프로그램은 프로그램 생성과 함께 테스트를 실행하는 것이 일반적이다.
  • 프로그램 배포
    웹 애플리케이션은 구현한 프로그램을 서버에 배포하게 된다. 이런 작업을 수작업으로 시행하기가 번거롭다.

빌드 도구의 역할

‘빌드 도구’는 단순히 프로그램을 컴파일하여 애플리케이션을 생성하는 작업 그 이상으로 다양한 기능을 제공한다.

  • 프로그램 빌드
    프로그램을 컴파일하고, 지정된 디렉터리에 필요한 리소스를 모아서 프로그램을 완성한다. 그때 라이브러리등 필요한 파일을 설치하도록 지정할 수 있다.
  • 프로그램 테스트와 실행
    빌드된 프로그램의 실행뿐 아니라 테스트 기능도 제공한다. 빌드를 실행 할 때, 빌드가 완료되면 곧바로 테스트를 실행하는 도구도 있다.
  • 라이브러리 관리
    프로그램에서 필요한 라이브러리들을 관리한다. 빌드 실행 시 자동으로 라이브러리를 다운로드하고 설치하는 등의 작업을 한다.
  • 배포 작업
    빌드한 프로그램을 배포하는 기능을 제공한다.

개발 도구와 빌드 도구

개발 도구에 있어 빌드 도구를 다루는 방식은 크게 두 가지이다.

  • 빌드 도구를 이용하는 기능이 포함된 경우
    이클립스는 메이븐, 인텔리제이는 메이븐과 그레이들을 지원한다.
  • 개발 도구에서 명령어로 실행하는 경우

메이븐 기초

메이븐은 아파치 소프트웨어 재단이 개발하는 오픈 소스 빌드 도구이다. ‘아파치 앤트(Ant)’의 후속으로 개발되었고, 자바 프로그램 개발을 대상으로 한 오픈 소스 빌드 도구이다.

메이븐 특징

  • 빌드 파일은 XML로 작성
  • 단위 작업 ‘골’
    골은 메이븐에서 실행하는 작업의 목적을 지정한다. 메이븐 명령어를 실행할 때 골을 지정하면, 어떤 작업을 수행하여 무엇을 작성할지 지정할 수 있다.
  • 라이브러리 관리와 중앙 저장소
    빌드를 실행하는 사이에, 빌드 파일에 기술된 정보를 바탕으로 필요한 라이브러리를 자동으로 다운로드하여 포함시킨다. 이를 가능하게 하는 것이 중앙 저장소이다. 중앙 저장소는 메이븐에서 이용 가능한 라이브러리를 모아서 관리하는 웹 서비스이다.
  • 테스트와 문서 생성
    엔트의 표준에는 포함되지 않았던 JUnit 테스트 및 Javadoc 문서 생성 등의 기능을 갖추고 있다.
  • 플러그인을 이용한 확장
    플러그인을 사용하면 메이븐에 기능을 추가할 수 있다.

메이븐 프로젝트 생성

메이븐에 포함된 **archetype:generate**라는 골을 이용하면, 간단하게 프로젝트의 기본 부분을 만들 수 있다. 아키타입(archetype)은 프로그램의 템플릿 모음이다.

Intellij를 이용해서도 메이븐을 기반으로 프로그램을 빌드하는 프로젝트를 생성할 수 있다. New Project -> 목록에서 Maven 선택 -> Create from archetype 체크 -> maven-archetype-quickstart 선택

메이븐에서는 mvn 명령어로 각종 조작을 할 수 있는데, 이 명령어들을 인텔리제이의 ‘Run’을 이용하여 실행할 수 있다. 실행할 내용을 컨피그레이션에 설정하면 인텔리제이의 ‘Run’으로 프로그램의 빌드와 실행, 디버그 등의 기능을 수행할 수 있다. (‘Run…’ -> Edit Configurations’ 메뉴에서 설정 가능)

pom.xml

pom.xml 파일에서 POM은 ‘Project Object Model’을 말한다. 이 파일에 프로젝트에 관한 각종 정보를 기술한다.

<project>와 기본속성

  • 모델 버전

    1
    <modeVersion>4.0.0</modeVersion>

    기본적으로 메이븐은 하위 호환성을 지원하기 때문에 이후 새로운 버전이 되더라도 이곳의 버전 번호를 바꾸면 이외 부분은 크게 수정하지 않고도 사용할 수 있다.

  • 그룹 ID

    1
    <groupId>com.jongmin</groupId>

    그룹 ID는 작성할 프로그램이 어디에 소속되어 있는지를 나타낸다.

  • 아티팩트 ID

    1
    <artifactId>mvn-app</artifactId>

    그룹 ID와 함께 프로그램을 식별하는 데 사용된다. ID이기 때문에 같은 그룹 내에서 같은 프로젝트 이름이 중복되지 않도록 주의해야 한다.

  • 버전

    1
    <version>1.0-SNAPSHOT</version>

    메이븐을 사용하는 프로젝트를 빌드하거나 패키징한 경우 여기서 지정된 번호가 생성된 프로그램의 버전으로 설정된다. 보통은 생성된 JAR 파일의 파일명에도 사용된다.

  • 패키지 종류

    1
    <packaging>jar</packaging>

    보통은 jar을 지정하지만, zip이라고 지정하면 ZIP 파일로 패키징한다.

  • 애플리케이션 이름

    1
    <name>mvn-app</name>

    작성하는 애플리케이션의 이름을 지정한다. 그룹 ID나 아티팩트 ID와 달리 유일한 값일 필요가 없다.

  • URL

    1
    <url>http://maven.apache.org</url>

    기본값으로는 메이븐 사이트의 URL이 지정되어 있다.

**<properties>**는 pom.xml에서 이용되는 속성값을 설정한다.

1
2
3
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

기본값으로는 <project.build.sourceEncoding>라는 항목이 설정되어 있는데 이는 소스 파일의 문자 인코딩 방식을 지정한다.

<dependencies>와 의존성 설정

dependencies 태크를 통해 필요한 라이브러리를 관리할 수 있다. 여기에 의존성을 적어두면 필요한 라이브러리 등을 자동으로 다운로드하여 설치 등을 할 수 있다.

<dependency> 태그를 설정하는 것만으로 의존 라이브러리가 자동으로 로드되는 것은 메이븐의 중앙 저장소 때문이다. 중앙 저장소는 메이븐을 개발한 아파치 소프트웨어 재단이 운영하는 사이트이다.

기본적인 ‘골’

메이븐은 골을 지정하여 실행할 처리의 역할을 정한다.

1
mvn 골
  • compile

    1
    mvn compile

    자바 소스 코드 파일을 컴파일 한다. 프로젝트 폴더 내에 target 폴더가 생성된다.

  • test-compile

    1
    mvn test-compile

    유닛 테스트용 클래스를 컴파일한다. src 폴더 안의 test 안에 작성된 유닛 테스트용 소스 코드 파일을 컴파일하여, target 폴더 안에 test-class 폴더를 작성하고 그 안에 클래스 파일을 생성한다.

  • test

    1
    mvn test

    메이븐은 테스트(유닛 테스트)가 거의 표준 기능으로 포함되어 있다. 테스트를 개별적으로 실행하는 골이 test이다.작성한 유닛 테스트용 클래스를 이용하여 테스트가 실행되고 그 결과가 출력된다.

  • package

    1
    mvn package

    mvn compile을 실행하면 클래스 파일이 생성되지만, 일반적으로 자바 프로그램은 클래스파일을 그대로 배포하지는 않는다. 일반적으로 JAR 파일 등으로 패키징하여 배포한다.

    명령 한 번으로 프로그램을 컴파일하여 유닛 테스트를 실행한 후 JAR 파일로 패키징하는 처리가 모두 자동적으로 수행된다.

    실행 후 target 폴더 안에 jar 파일이 생성된다.

  • clean

    1
    mvn clean

    메이븐은 프로그램을 빌드하면서 컴파일된 클래스 파일 뿐만 아니라, 테스트, 압축을 실행하는 파일 등을 만든다. clean은 부가적으로 생성된 파일을 모두 지운다.

프로그램 실행하기

클래스가 하나인 코드는 java 명령어로도 쉽게 실행할 수 있다. 그러나 다양한 라이브러리를 이용하는 프로젝트에서는 모든 클래스 경로를 직접 지정해야 하기 때문에 java 명령어를 이용해 실행하는 일은 번거롭다.

메이븐에는 표준으로 자바 프로그램을 실행하는 골은 없다. 하지만 exec-java-plugin 플러그인을 이용하면 프로그램을 실행할 수 있다.

pom.xml의 <project> 태그 안에 있는 <dependencies> 종료 태그의 다음 행에 다음과 같이 플러그인을 추가한다.

1
2
3
4
5
6
7
8
9
10
11
12
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<configuration>
<mainClass>com.jongmin.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>

명령행에 다음과 같이 실행하면 App 클래스가 실행된다. 만약 mvn clean으로 프로젝트의 빌드 결과물을 제거한 경우 다시 mvn package로 빌드한 후에 실행한다.

1
mvn exec:java

exec-maven-plugin은 메인 클래스를 지정해야 한다. 플러그인에 정보를 지정할 때는 <configuration> 태그를 이용한다.

빌드 플러그인

<build> 태그는 빌드에 관한 정보를 기술하는 태그이다. 형태는 다음과 같다.

1
2
3
4
5
6
7
<build>
<plugins>
<plugin>...</plugin>
<plugin>...</plugin>
...
</plugins>
</build>

<build>와 <plugins> 태그는 여러 개 사용할 수 없다. 반드시 1개씩 있고, 그 안에 모든 <plugin>을 모아서 사용한다.

메이븐의 골과 플러그인

exec:java 골은 플러그인을 사용해 추가된 것이다. 사실, 지금까지 사용했던 모든 골들도 플러그인으로 추가된 것이다.

  • compile : maven-compiler-plugin
  • package : maven-jar-plugin
  • test : maven-surefire-plugin

하지만 위의 플러그인은 표준으로 포함되어 있기 때문에 플러그인이라고 의식하지 못했던 것이다.

표준이 아닌 <plugin> 태그에 의해 추가된 플러그인의 골을 지정하는 경우에는 xx:xx와 같이 요소가 둘인 경우가 일반적이다. 플러그인 하나가 여러 골을 가질 수도 있기 때문에 ‘플로그인:골’ 형태로 기술한다.

<plugin>이 필수는 아니다. 플러그인으로 추가하여 이용하는 골이라고 해서 <plugin>에 기술하지 않으면 사용하지 못하는 것은 아니다. <plugin>은 플러그인에 포함된 설정 등의 정보를 기술하는 태그이다. 그렇기 때문에 설정이 필요하지 않으면 기술할 필요가 없다.

인텔리제이에서 사용하기

플러그인을 통해 개발 도구의 프로젝트로 변환이 가능하다.

1
mvn idea:idea

위 골을 실행하면 인텔리제이에서 프로젝트를 다루는데 필요한 파일들이 생성된다.

1
mvn idea:clean

인텔리제이 프로젝트에서 인텔리제이 관련 파일을 삭제하여 원래의 메이븐 프로젝트로 돌리려면 위의 골을 실행한다.

실행 가능한 JAR 파일 만들기

앞서 mvn package로 패키징했지만 이렇게 생성된 JAR 파일은 단순히 패키징 된 것이기 때문에 실행되지는 않는다.

1
java -jar 00.jar

따라서 위의 명렁을 실행해도 00.jar에 기본 Manifest 속성이 없어 실행에 실패하게 된다.

실행 가능한 JAR 파일을 만들기 위해서는 maven-jar-plugin을 이용해 다음과 같은 <plugin> 태그를 작성하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>버전</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>메인 클래스</mainClass>
</manifest>
</archive>
</configuration>
</plugin>

<archive> 태그는 압축에 관한 설정이다. addClasspath는 클래스 경로에 JAR 파일이 있는 경로를 추가하기 위한 태그인데 보통은 true로 지정한다.

이렇게 설정 후 다시 mvn package로 JAR 파일을 생성한 후 java -jar로 실행해보면 문제없이 실행할 수 있다.

저장소 이용

<dependency> 를 추가하는 것만으로 필요한 라이브러리를 추가해 사용할 수 있었던 것은 중앙 저장소 때문이다. 그런데 저장소가 중앙 저장소만 있는 것은 아니다. 다른 원격 저장소나 로컬 저장소도 있다.

로컬 저장소

자신이 만든 라이브러린, 그다지 유명하지 않은 라이브러리라면 아직 중앙 저장소에 공개되지 않을 수도 있다. 이러한 라이브러리는 로컬 저장소를 이용해 사용할 수 있다.

  • 원격 저장소 : 네트워크를 거쳐 서버에 접속하여 이용하는 공개된 저장소. 중앙 저장소도 원격 저장소의 한 종류이다.
  • 로컬 저장소 : 로컬 환경에 있는 저장소이다.

원격 저장소 이용

원격 저장소는 pom.xml에 <repositories> 태그 안에 저장소 정보를 기술한다.

1
2
3
4
5
6
7
<repositories>
<repository>
<id>저장소 ID</id>
<name>이름</name>
<url>저장소 주소(URL)</url>
</repository>
</repositories>

로컬 저장소에 라이브러리 추가하기

추가하고자 하는 라이브러리 프로젝트에서 다음과 같이 실행하면 target에 빌드된 JAR 파일을 로컬 저장소에 설치한다.

1
mvn install

또는 설치할 JAR 파일이 별도로 준비되어 있다면 install:install-file 골을 실행해서 지정한 라이브러리 파일을 로컬 저장소에 설치할 수 있다.

1
2
3
4
5
6
mvn install:install-file
-Dfile="라이브러리 jar의 경로"
-DgroupId="그룹 ID"
-DartifactId="아티팩트 ID"
-Dpackaging="패키징(jar)"
-Dversio="버전(1.0)"

로컬 저장소의 위치 알아보기

로컬 저장소의 위치는 다음과 같다.

1
홈 디렉터리/.m2/repository

이 폴더에는 라이브러리가 그룹 ID마다 폴더로 정리되어 있다.