저작권 안내: 저작권자표시 Yes 상업적이용 No 컨텐츠변경 No

스프링5 입문

JSP 2.3

JPA 입문

DDD Start

인프런 객체 지향 입문 강의

메이븐을 사용하다보면 오라클 JDBC 드라이버처럼 라이선스 문제로 메이븐 중앙 리포지토리나 다른 공개 리포지토리에 존재하지 않는 jar 파일이 존재한다. 이런 경우에는 다음과 같이 maven-install 플러그인을 사용해서 jar 파일을 로컬 메이븐 리포지토리에 등록해주면 된다. (공간상 두 줄로 표시했으며, 실제로는 한 줄로 입력한 것이다.)


mvn install:install-file -Dfile=ojdbc14.jar -DgroupId=com.oracle

  -DartifactId=ojdbc14 -Dversion=10.2.0.2.0 -Dpackaging=jar


여력이 된다면, 로컬 리포지토리에 일일이 등록하는 것 보다는, 내부에 Nexus를 이용해서 메이븐 리포지토리를 구축하는 것이 더 좋다. Nexus에 대한 내용은 "Maven 내부용 리포지토리 만들고 Maven 설정하기" 글을 참고하기 바란다.

Posted by 최범균 madvirus

댓글을 달아 주세요

자바로 테스트 코드 만드는 게 좀 짜증이 나서 편하게 사용할만한 테스트 프레임워크를 뒤지다가 페이스북에서 Spock 이라는 놈을 줏어 들었다. 자바 기반의 프로젝트를 진행중인데, Spock가 그루비 기반이라서 궁합도 잘 맞을 것 같기에 일부 테스트 코드에서 넣어보기로 결심을 했다.


본격 사용하기에 앞서 개발 환경 구축은 필수! 아래의 순서로 진행을 했다.

  1. 이클립스에서 그루비 플러그인 설치
  2. pom.xml에 Spock 실행 위한 설정 추가
  3. src/test/groovy 폴더 생성
  4. Spock 테스트 코드 실행
그루비 플러그인 설치


http://groovy.codehaus.org/Eclipse+Plugin 사이트에 가면 이클립스 버전 별로 업데이트 사이트 주소를 확인할 수 있다. 필자는 이클립스 4.3 (Kepler) 버전을 사용중이서 http://dist.springsource.org/release/GRECLIPSE/e4.3/ 주소를 이용해서 플러그인을 설치했다. 메이븐 플러그인(m2e)와 연동을 해야 하므로, 메이븐 플러그인 커넥터도 함께 설치했다. (사실은 다 설치했다.)


그루비 플러그인을 설치한 다음에는 Windows > Preferences > Groovy > Compiler 에서 컴파일러 버전을 2.0 으로 변경한다. (변경하면 이클립스를 재시작한다.) 2.1이 아닌 2.0을 사용하는 이유는 Spock 0.7 버전이 현재 그루비 2.0 까지만 지원하기 때문이다.


pom.xml 파일 설정


메이븐 pom.xml 설정이 다소 복잡한데, 사용한 설정은 아래와 같다. Spock 0.7 버전은 현재 그루비 1.8 버전 또는 2.0 버전을 지원한다.


<project ...>

    <dependencies>

        ...

        <dependency>

            <groupId>org.spockframework</groupId>

            <artifactId>spock-core</artifactId>

            <version>0.7-groovy-2.0</version>

            <!-- 0.7-groovy-1.8 -->

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.codehaus.groovy</groupId>

            <artifactId>groovy-all</artifactId>

            <version>2.0.5</version>

            <scope>test</scope>

        </dependency>

    </dependencies>


    <build>

        <plugins>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-compiler-plugin</artifactId>

                <version>3.1</version>

                <configuration>

                    <source>${java.version}</source>

                    <target>${java.version}</target>

                    <encoding>${project.build.sourceEncoding}</encoding>

                    <compilerId>groovy-eclipse-compiler</compilerId>

                </configuration>

                <dependencies>

                    <dependency>

                        <groupId>org.codehaus.groovy</groupId>

                        <artifactId>groovy-eclipse-compiler</artifactId>

                        <version>2.8.0-01</version>

                    </dependency>

                    <dependency>

                        <groupId>org.codehaus.groovy</groupId>

                        <artifactId>groovy-eclipse-batch</artifactId>

                        <version>2.0.7-03</version>

                        <!-- <version>1.8.6-01</version> -->

                    </dependency>

                </dependencies>

            </plugin>

        </plugins>

    </build>


</project>


테스트 목적으로만 쓸 거라서 groovy-all 의존의 범위를 test로 지정하였다.


주의사항:

  • spock 0.7 메이븐 의존은 Junit-dep 4.10 버전에 대한 의존을 갖는다. 따라서, Junit 4.11과 같이 다른 버전의 JUnit을 사용하고 있다면, JUnit 버전을 맞추기 위해 spock 의존 설정에 <exclustion>을 추가해서 junit-dep 의존을 제거한다.
  • groovy-all 용량이 커서, 최초 다운로드에 올래 걸리기도 한다. 메이븐 프로젝트 구성할 때에 인내심이 필요할 수 있다.

src/test/groovy 폴더 생성


그루비로 만든 테스트 코드를 넣기 위해 src/test 폴더 아래 groovy 폴더를 생성한다.


Spock 테스트 코드 실행


이제 남은 건 Spock 테스트 코드를 실행하는 것이다. src/test/groovy 폴더에 Spock 홈페이지에 있는 테스트 코드를 넣어본다. (HelloSpock.groovy)


import spock.lang.*


class HelloSpock extends spock.lang.Specification {

def "length of Spock's and his friends' names"() {

expect:

name.size() == length


where:

name     | length

"Spock"  | 5

"Kirk"   | 4

"Scotty" | 6

}

}


JUnit을 실행하는 것과 동일하게 "JUnit Run"으로 실행한다. 그러면, 아래와 같이 테스트가 통과하는 것을 확인할 수 있다.




Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 미니양 2014.02.11 04:43 신고  댓글주소  수정/삭제  댓글쓰기

    Spock을 한번 따라해 보고 싶어서 작성해 주신 글대로 따라 해 봤습니다.
    Spock의 기본 샘플로 주신건 실행이 되는데,
    def MockSampleObj = Mock(SampleObj)
    이렇게 하면 MockSampleObj.someMethod를 하면 someMethod를 가져오지 못하고 밑줄이 그어지네요.

    혹시 원인을 알 수 있나요?

배치 프로그램이나 명령행에서 실행할 간단한 자바 프로그램을 만들 때가 있는데, 이 프로그램이 스프링 프레임워크를 이용한 경우 관련된 jar 파일들을 함께 배포하고 실행 스크립트에 클래스패스를 설정해주고 하는 것이 귀찮을 때가 있다. 내가 만든 클래스 파일/자원 파일뿐만 아니라 스프링 jar 파일에 포함된 클래스/메타 파일들을 모두 하나의 jar 파일로 만들어서 배포하면 프로그램을 실행하는 스크립트가 매우 간단해질텐데, 메이븐의 어셈블리 플러그인이 제공하는 jar-with-dependencies 기능을 사용하면 이 작업을 매우 쉽게 할 수 있다.


maven-assembly-plugin은 jar-with-dependencies 설정을 제공하는데, 이 설정을 사용하면 내가 만든 클래스 및 자원 파일과 의존하는 jar 파일에 포함된 모든 파일을 묶어서 하나의 jar 파일로 만들어준다. 다음은 설정 예이다.



<build>

        <plugin>

            <groupId>org.apache.maven.plugins</groupId>

            <artifactId>maven-assembly-plugin</artifactId>

            <executions>

                <execution>

                    <id>create-jar</id>

                    <phase>package</phase>

                    <goals>

                        <goal>single</goal>

                    </goals>

                    <configuration>

                        <descriptorRefs>

                            <descriptorRef>

                                jar-with-dependencies

                            </descriptorRef>

                        </descriptorRefs>

                    </configuration>

                </execution>

            </executions>

        </plugin>


        <plugin>

            <groupId>org.apache.maven.plugins</groupId>

            <artifactId>maven-shade-plugin</artifactId>

            <executions>

                <execution>

                    <phase>package</phase>

                    <goals>

                        <goal>shade</goal>

                    </goals>

                    <configuration>

                        <transformers>

                            <transformer

                                implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">

                                <mainClass>com.prototype.springintegration.AppBootstrapper</mainClass>

                            </transformer>

                            <transformer

                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">

                                <resource>META-INF/spring.handlers</resource>

                            </transformer>

                            <transformer

                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">

                                <resource>META-INF/spring.schemas</resource>

                            </transformer>

                            <transformer

                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">

                                <resource>META-INF/spring.factories</resource>

                            </transformer>

                            <transformer

                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">

                                <resource>META-INF/spring.factories</resource>

                            </transformer>

                            <transformer

                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">

                                <resource>META-INF/spring.tooling</resource>

                            </transformer>

                        </transformers>

                    </configuration>

                </execution>

            </executions>

        </plugin>

    </plugins>

</build>


위 코드에서 maven-shade-plugin 을 사용했는데, 이 플러그인을 사용한 이유는 스프링의 각 jar 파일에 포함되어 있는 메타 파일들을 하나의 파일로 합치기 위함이다. 이 플러그인을 사용하지 않으면 스프링의 각 jar 파일에 포함된 메타 파일을 한 개 jar 파일에 모으는 과정에서 합쳐지지 않고 뎝어쓰기때문에 XML 확장 스키마 등의 설정이 올바르게 동작하지 않게 된다.


위와 같이 설정을 했다면 mvn package 명령어로 의존하는 jar 파일에 속한 모든 내용과 내가 만든 클래스/자원 파일들이 포함된 한 개의 jar 파일을 얻을 수 있다.

Posted by 최범균 madvirus

댓글을 달아 주세요

필자는 Maven을 너무 좋아하기에 안드로이드 개발도 Maven 프로젝트로 관리하고 싶었다. 그래서 구글링을 좀 했고, 영어로 된 걸 매번 보고 싶지 않아 나중을 위해 한글로 정리해둔다.


M2E를 위한 Android Connector 설치


먼저 할 일은 이클립스에 설치한 Maven 플러그인과 ADT를 연결하는 위해 Android Connector를 설치하는 것이다. 설치를 하려면 Preferences > Android/Discovery > Open Catalog 메뉴를 실행한 뒤, 아래 그림이 나올 때 android로 검색하면 된다.



검색 결과로 나온 Android Connector를 선택한 뒤 설치하자.


Android용 Archetype 추가 (옵션)


Android Connector를 설치 후, pom.xml 파일에 maven-android-plugin을 설정하면 해당 프로젝트를 ADT와 연동해 준다. 하지만, pom.xml 파일을 처음부터 만들면 (다소) 귀찮을 수 있는데, 그걸 대신 해주는 archetype을 추가해주면 좀 더 편하게 pom.xml 파일을 생성할 수 있다.


Archetype 타입을 추가해주는 방법은 간단하다. New > Maven Project > Next > Select an Archetype 화면에서 [Add Archetype...] 버튼을 클릭한다. 그런 다음 아래와 같이 정보를 입력하고 [OK] 버튼을 클릭하면 해당 Archetype이 추가된다.


* Group Id: de.akquinet.android.archetypes

* Artifact Id: android-quickstart

* Version: 1.0.8


안드로이드 프로젝트 생성하기


안드로이드 프로젝트를 생성하는 방법은 간단하다. 앞서 생성한 android-quickstart Archetype을 이용해서 안드로이드 프로젝트를 생성하면 된다. android-quickstart Archetype을 선택하면 아래 그림과 같은 화면이 나온다. platform의 값에 사용할 안드로이드 플랫폼 버전을 입력해주면 된다.



프로젝트를 생성하면 잠시 후 아래 그림과 같이 Maven 프로젝트가 ADT와 연동된 것을 확인할 수 있다. 아래 그림을 보면 자원 관리를 위한 res 폴더, 자동 생성되는 파일을 위한 gen 폴더 등이 생성된 것을 확인할 수 있다.



생성된 pom.xml 파일을 maven-android-plugin 설정 및 플랫폼 버전 정보 등이 포함된 것을 확인할 수 있다.


<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.madvirus</groupId>

    <artifactId>NetworkExplorer</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <packaging>apk</packaging>

    <name>NetworkExplorer</name>


    <properties>

        <platform.version>2.3.2</platform.version>

    </properties>


    <dependencies>

        <dependency>

            <groupId>com.google.android</groupId>

            <artifactId>android</artifactId>

            <version>${platform.version}</version>

            <scope>provided</scope>

        </dependency>

    </dependencies>


    <build>

        <plugins>

            <plugin>

                <groupId>com.jayway.maven.plugins.android.generation2</groupId>

                <artifactId>android-maven-plugin</artifactId>

                <version>3.1.1</version>

                <configuration>

                    <androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>

                    <assetsDirectory>${project.basedir}/assets</assetsDirectory>

                    <resourceDirectory>${project.basedir}/res</resourceDirectory>

                    <nativeLibrariesDirectory>${project.basedir}/src/main/native</nativeLibrariesDirectory>

                    <sdk>

                        <platform>10</platform>

                    </sdk>

                    <undeployBeforeDeploy>true</undeployBeforeDeploy>

                </configuration>

                <extensions>true</extensions>

            </plugin>


            <plugin>

                <artifactId>maven-compiler-plugin</artifactId>

                <version>2.3.2</version>

                <configuration>

                    <source>1.6</source>

                    <target>1.6</target>

                </configuration>

            </plugin>

        </plugins>

    </build>

</project>




참고로, Android Connector와 android-maven-plugin인에 대한 보다 자세한 내용이 궁금하면 아래 사이트를 방문해서 확인하면 된다.


Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 예감 2013.07.29 12:09 신고  댓글주소  수정/삭제  댓글쓰기

    Maven관련 자료 잘보고 갑니다^^

회사를 옮길 때 마다 Maven 리포지토리와 관련된 비슷한 짓거리를 하고 그 내용을 동료들에게 알려주어야 하는 귀찮음을 줄이고자 정리해 보았다.


회사에서 내부적으로 사용할 Maven 리포지토리가 필요한 경우가 있다. 예를 들어, 오라클 JDBC 드라이버는 Maven 중앙 리포지토리에 존재하지 않기 때문에 모든 개발자들이 로컬 리포지토리에 따로 등록해주는 수고를 해야 하는데, 내부용 Maven 리포지토리를 만들어서 그곳에 오라클 JDBC 드라이버를 등록하면 한 사람만 내부용 리포지토리에 등록해주는 수고를 해 주면 나머지 개발자는 편하게 오라클 JDBC 드라이버를 Maven의 depedency로 등록해서 사용할 수 있게 된다. (한 사람이 노력으로 많은 개발자들의 중복 작업이 사라진다. DRY!!) 외부의 jar 파일 뿐만 아니라 내부에서 사내의 다수 프롤젝트에서 사용될 모듈을 만드는 경우에도 내부용 리포지토리를 만들면 쉽게 관련 모듈을 사용/관리할 수 있게 된다.

내부용 리포지토리 구축을 쉽게 하고 싶을 때에는 Nexus(http://www.sonatype.org/nexus/)를 사용하면 된다. Nexus는 자바로 만들어져 있으며, WAR로도 배포되기 때문에 손쉽게 설치할 수 있다는 장점이 있다. 설치에 대한 정보는 Nexus 홈페이지를 참고하기 바란다.

Nexus를 설치하면 최초에 다음의 리포지토리를 제공해준다.
  • Releases: 내부에서 만들어진 모듈의 정식 버전을 등록할 때 사용 (releases)
  • Snapshots: 내부에서 만들어진 모듈의 스냅샵 버전을 등록할 때 사용 (snapshots)
  • 3rd party: 외부 업체 제공 모듈을 등록할 때 사용 (예를 들어, 오라클 JDBC 드라이버 등) (thirdparty)
  • 기타 Central, Apache Snapshots, Codehaus Snapshots 등 외부 리포지토리 연결 (central 등)
  • 그리고, 이들을 하나처럼 보이게 해 주는 Public Repositories (public)
위 목록에서 뒤의 괄호안에 있는 이름이 리포지토리 주소에서 사용되는 경로인데, 예를 들어, Releases 리포지토리의 주소는 http://host/nexus-ver/content/repositories/releases/ 의 형식을 가지며, 그룹의 경우는 http://host/nexus-ver/content/groups/public의 형식을 갖는다.

릴리즈하기 위한 Maven 설정

내가 만든 Maven 프로젝트를 리포지토리에 배포하려면 다음의 세 가지 작업을 해 주어야 한다.
  • pom.xml 파일에 배포 대상 리포지토리 설정하기
  • settings.xml 파일에 배포 대상 리포지토리 연결 정보 설정하기
  • 배포하기
먼저 pom.xml 파일에 다음과 같이 <distributionManagement> 태그를 등록한다.

pom.xml 파일

<distributionManagement>
<repository>
<id>mycompany.internal.release</id>
<name>MyCompany Internal Repository</name>
<url>http://host/nexus/content/repositories/releases/</url>
</repository>
</distributionManagement>

두 번째로 settings.xml 파일에 pom.xml 파일에 설정한 리포지토리에 연결할 때 사용할 정보를 추가해주는 것이다. settings.xml 파일은 여러 위치에 만들 수 있는데 필자의 경우 [홈디렉토리]/.m2 디렉토리에 주로 만들어준다. 아래 코드는 settings.xml 파일의 작성 예이다.

settings.xml 파일

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>mycompany.internal.release</id>
<username>deployment</username>
<password>deployment123</password>
</server>
</servers>

</settings>

<server> 태그는 특정 서버에 연결할 때 사용할 아이디/암호를 입력하는데 이때 <id>의 값은 pom.xml에 등록한 리포지토리의 <id> 값과 일치해야 한다.

위와 같이 작업이 끝났다면 이제 배포만 하면 된다. Maven 프로젝트 디렉토리에서 다음과 같이 deploy 명령어를 실행하면 pom.xml 파일에 등록했던 배포 대상 리포지토리에 프로젝트의 artifact가 배포된다.

mvn deploy

등록된 것 사용하기

배포된 artifact를 다른 프로젝트에서 사용하려면 다음과 같이 앞서 구축한 내부용 리포지토리를 등록해주고 depedency를 추가해주면 된다.


<repositories>

<repository>

<id>mycompany.internal.repo</id>

<url>http://host/nexus/content/repositories/releases/</url>

<releases>

<enabled>true</enabled>

</releases>

</repository>

</repositories>


<dependencies>

<dependency>

<groupId>com.mycompany</groupId>

<artifactId>my-common-module</artifactId>

<version>3.0</version>

</dependency>

</dependencies>


Snapshot 등도 동일한 방식으로 등록 및 사용할 수 있다.



Posted by 최범균 madvirus

댓글을 달아 주세요

  1. moonv11 2014.07.17 13:49 신고  댓글주소  수정/삭제  댓글쓰기

    좋은 글 잘 보았습니다. 출처 명시하고 퍼가겠습니다.

  2. 카루딘 2016.07.06 11:12 신고  댓글주소  수정/삭제  댓글쓰기

    감사합니다. 출처 명시하고 담아가겠습니다. ^^

  3. 라이더 2017.04.19 18:55 신고  댓글주소  수정/삭제  댓글쓰기

    감사합니다. 정리 깔끔하시네요 ^^

  4. Ironcow 2018.07.06 09:27 신고  댓글주소  수정/삭제  댓글쓰기

    좋은 글 감사합니다.
    공부중에 필요한 정보였는데 출처 명시하고 담아가겠습니다!!

이 글은 Jetty 6 버전 기준이긴 하지만, 플러그인 버전이나 의존 라이브러리에서 차이가 날 뿐 Jetty 7 버전에서도 크게 다르지 않다.

Jetty 서버를 임베딩하기 위한 pom.xml 설정

Maven 프로젝트에서 Jetty 서버를 임베딩하려면 먼저 Jetty 관련 클래스들을 사용할 수 있어야 하므로, 아래와 같이 의존 라이브러리에 Jetty 관련 artifact를 추가해 준다.

<dependencies>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jsp-api-2.1</artifactId>
        <version>6.1.14</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>servlet-api-2.5</artifactId>
        <version>6.1.14</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty</artifactId>
        <version>6.1.14</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jsp-2.1</artifactId>
        <version>6.1.14</version>
        <scope>test</scope>
    </dependency>
    ...

위 설정에서 눈여겨 볼 점은 서블릿/JSP API를 위한 artifact는 provided 범위를 갖는 반면에 Jetty 자체를 임베딩해서 실행하기 위한 artifact는 test 범위를 갖는다는 것이다. test 범위를 갖도록 한 이유는 Jetty 임베딩을 ATDD를 위한 용도로만 사용하기 때문이다.

Jetty 서버 임베딩으로 실행하기

Maven 프로젝트 구조에서 Jetty 서버를 임베딩으로 실행하고 종료하는데 사용된 코드는 다음과 같다.

public class JettyServer {

    private static Server server;
   
    public static void start() throws Exception {
        server = new Server(9090);

        WebAppContext context = new WebAppContext();
        context.setResourceBase("src/main/webapp");
        context.setContextPath("/goodjob");
        context.setParentLoaderPriority(true);

        server.setHandler(context);
       
        server.start();
    }

    public static void stop() throws Exception {
        server.stop();
    }
}

ATDD를 수행하는 코드에서는 다음과 같이 픽스처 구성시 JettyServer.start() 메서드를 이용해서 Jetty 서버를 임베딩해서 실행하고, 테스트 완료 후 JettyServer.stop() 메서드를 이용해서 Jetty 서버를 중지시켜주면 된다.

public class EndToEndTestBase {

    @BeforeClass
    public static void init() throws Exception {
        JettyServer.start();
    }

    @AfterClass
    public static void close() throws Exception {
        JettyServer.stop();
    }

}

일단, Jetty 서버를 임베딩으로 실행하면 http://localhost:9090/goodjob/authentication/login 과 같은 URL을 이용해서 실제 기능 테스트를 수행할 수 있다. 예를 들어, 웹 기능 테스트를 위한 코드는 아래와 같은 구성을 갖게 된다.

public class AllTeamsSummaryReportEndToEndTest extends EndToEndTestBase {

    @BeforeClass
    public static void initData() throws Exception {
        // 테스트 목적을 위한 데이터 초기화
        ...
    }

    @Test
    public void queryAllTeamsWeekSummaryReport() throws Throwable {
        // HtmlUnit이나 HttpClient와 같은 라이브러리를 이용해서
        // http://localhost:9090/goodjob/testurl 등 테스트 URL에 연결하고
        // 그 결과를 검증하는 코드 삽입
    }

}




Posted by 최범균 madvirus

댓글을 달아 주세요

Maven의 기본 라이프사이클에서 compile 시기에 실행되는 compiler 플러그인은 별도 설정이 없을 경우, 자바 1.3 버전 기준으로 컴파일 할 소스 코드를 파싱하고 자바 1.1 버전에 호환되도록 클래스 파일을 생성한다. 따라서, 제너릭(generic)이나 어노테이션(annotation)과 같이 자바 5 이상 버전에서만 유효한 문법이 코드에 포함되어 있을 경우 컴파일 과정에서 문법 에러가 발생하게 된다.

maven-compiler-plugin 설정하기

Maven이 기본적으로 사용하는 소스 및 생성 클래스의 자바 버전을 변경하려면 pom.xml 파일에서 maven-compiler-plugin의 <configuration> 영역에서 <source>와 <target>을 이용해서 소스 코드 및 생성 대상 자바 버전을 지정할 수 있다. 아래 코드는 설정 예를 보여주고 있다.

<project>
    ....
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            ...
        </plugins>
    </build>
</project>

만약 소스 코드의 인코딩이 운영체제의 기본 인코딩과 다르다면 <encoding> 속성을 이용해서 소스 코드의 인코딩을 지정해주면 된다.

위와 같이 maven-compiler-plugin 에서 소스 및 대상 자바 버전을 명시하면 eclipse:eclipse를 이용해서 생성한 이클립스 프로젝트도 설정한 자바 버전을 사용하도록 설정된다.

관련 자료:



 

Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 여름나라겨울이야기 2013.10.17 01:35 신고  댓글주소  수정/삭제  댓글쓰기

    고이 고이 퍼 갑니다. 잘 활용하도록 하겠습니다. ^^/

Maven을 이용해서 생성한 프로젝트를 이클립스에서 바로 사용할 수는 없다. 대신, Maven은 maven-eclipse-plugin을 이용해서 Maven 프로젝트를 이클립스에서 import 해서 사용할 수 있도록 지원해 주고 있다. 본 글에서는 Maven 프로젝트를 이클립스에서 사용하기 위한 기본 절차를 설명하고, 생성할 이클립스 프로젝트 정보를 커스터마이징 하는 방법을 살펴보도록 하겠다.

이 글을 최초로 썼던 2008년 시점과 달리, 현재는 이클립스의 메이븐 연동 플러그인(m2e 플러그인)이 잘 동작하기 때문에, 이 글의 방법을 사용해서 메이븐 프로젝트를 이클립스에 임포트 할 일이 없다. m2e 플러그인을 설치하면 이클립스에서 메이븐 프로젝트를 바로 임포트 할 수 있고, 또 메이븐 프로젝트를 생성할 수도 있다. 특히 이클립스 4.3 / 4.4 버전부터는 m2e 플러그인이 기본으로 포함되어 나오기 때문에, 플러그인을 따로 설치할 필요도 없어졌다. - 2014년 7월


Maven 프로젝트에서 이클립스 프로젝트 정보 생성하는 방법

Maven 프로젝트를 이클립스에서 import 할 수 있도록 하기 위해 이클립스 프로젝트 정보를 생성하려면 아래 절차에 따라 필요한 작업을 수행하면 된다.

  1. 이클립스 워크스페이스에 Maven 관련 클래스패스 변수 추가하기. 이는 아래 명령어를 이용해서 실행하면 된다. (이 과정은 워크스페이스에 대해 한번만 실행해주면 된다.) 이 작업을 수행하면 해당 워크스페이스와 관련해서

    mvn -Declipse.workspace=<path-to-eclipse-workspace> eclipse:add-maven-repo

  2. 프로젝트 루트 디렉터리에서 eclipse:eclipse 플러그인 골을 실행해서 이클립스 프로젝트 정보를 생성한다.

    mvn eclipse:eclipse

    위 명령어가 성공적으로 실행되면 .project, .classpath, .settings/ 등 이클립스 프로젝트와 관련된 설정 파일이 생성된다.
  3. 이클립스를 실행한 뒤, File > Import > Existing Projects into Workspace 메뉴를 이용해서 생성된 이클립스 프로젝트를 import 한다.

1번 작업은 이클립스 워크스페이스 별로 한번씩 해 주면 된다. 2번 작업의 경우 POM 파일의 의존 설정 부분이 수정될 때 마다 eclipse:eclipse 플러그인 골을 실행해서 새로운 이클립스 프로젝트 설정 파일을 생성해 주어야 한다. 또한, 이클립스 설정이 변경된 프로젝트에 대해 'Refresh'를 실행해서 프로젝트 정보를 다시 읽어오도록 해 주어야 한다.

의존 라이브러리 소스 다운로드 설정

개발하다보면 디버그 과정에서 외부 라이브러리의 코드를 참조하고 싶을 때가 있다. maven-eclipse-plugin 플러그인은 프로젝트 정보를 생성할 때 관련 소스 코드 정보를 함께 생성해주는 기능을 제공하고 있다. 간단한 방법은 다음과 같이 eclipse:eclipse 플러그인 골을 실행할 때 donwloadSources 시스템 프로퍼티 값을 true로 주는 것이다.

mvn eclipse:eclipse -DdownloadSources=true

이 경우 Maven은 Maven 중앙 리포지토리에서 소스 코드를 포함하는 jar 파일을 다운로드 받아 로컬 리포지토리에 저장한 뒤, 이클립스 프로젝트 설정 파일에 소스 첨부 정보를 추가한다.

소스 코드를 다운로드 받도록 하는 또 다른 방법은 pom.xml 파일에서 maven-eclipse-plugin 플러그인 설정 정보를 직접 명시해주는 것이다. 아래는 pom.xml 파일 설정 예를 보여주고 있다.

<project>
  ...
  <dependencies>...</dependencies>
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <configuration>
          <downloadSources>true</downloadSources>
          <downloadJavadocs>true</downloadJavadocs>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

위 코드와 같이 pom.xml 파일에 maven-eclipse-plugin의 설정 정보에서 downloadSources 설정 값을 true로 주면 eclipse:eclipse 골을 실행할 때 마다 소스 코드 다운로드를 시도하게 된다.

생성되는 프로젝트의 캐릭터 셋 설정하기

'mvn eclipse:eclipse' 명령어를 사용해서 이클립스 프로젝트 정보를 생성할 때, 생성되는 프로젝트의 인코딩은 이클립스에서 기본값으로 설정한 캐릭터 인코딩으로 설정된다. 그런데, 현재 이클립스의 기본 인코딩은 MS949인데, 새로 진행되는 프로젝트의 인코딩이 UTF-8 이라면 어떻게 해야 할까? 이미 다른 프로젝트들이 MS949 인코딩을 이용해서 개발되었기 때문에 이클립스의 기본 인코딩을 UTF-8로 변경할 수는 없을 것이다.

이렇게 프로젝트 별로 인코딩을 지정해주어야 하는 경우에는 pom.xml 파일에서 다음과 같이 maven-eclipse-plugin 플러그인의 <additionalConfig> 설정 정보를 추가해주면 된다.

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-eclipse-plugin</artifactId>
      <configuration>
        <additionalConfig>
          <file>
            <name>.settings/org.eclipse.core.resources.prefs
            </name>
            <content>
     <![CDATA[eclipse.preferences.version=1
encoding/<project>=UTF-8
]]>
            </content>
          </file>
        </additionalConfig>

      </configuration>
    </plugin>

<addionalConfig>/<file>을 설정하면 이클립스 프로젝트 생성시 추가적으로 <name>에 설정한 파일을 생성해준다. 위 코드의 경우 이클립스에서 인코딩 설정 정보를 저장할 때 사용되는 파일을 생성해 주도록 하였다. 생성되는 설정 파일(org.eclipse.core.resources.prefs)에서 encoding/<project> 설정 값을 UTF-8로 줌으로써, 이클립스에서 생성된 프로젝트의 인코딩을 UTF-8로 지정해 줄 수 있게 된다.


관련링크:


Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 구구구구우 2017.03.03 09:49 신고  댓글주소  수정/삭제  댓글쓰기

    eclipse:configure-workspace 는 deprecated 되었다고 하네요
    eclipse:configure-workspace - > eclipse:configure-workspace 이걸 쓰면 된다고 합니다.

본 글에서는 Maven을 이용해서 프로젝트를 생성하는 방법과, 디렉토리 구조, POM 파일 기본 구성, Maven 라이프 사이클 그리고 Maven 프로젝트를 이클립스 프로젝트로 생성하는 방법을 살펴보도록 하겠다.


본 글의 내용 중 일부를 현재 메이븐 버전인 3.5에 맞게 수정했다. - 2017년 12월


Maven 설치

http://maven.apache.org/ 사이트를 방문하면, 최신 버전의 메이븐을 다운로드 받을 수 있다. 이 글을 쓰는 시점에서 메이븐 최신 버전은 3.5.2이다. 바이너리 배포판을 다운로드 받은 아무 곳이나 원하는 디렉토리에 압축을 푼다. 설치 과정은 다음과 같다.

  1. 다운로드 받은 파일의 압축을 푼다. 예, apache-maven-3.5.2.zip 파일의 압축을 C:에 풀면 c:\apache-maven-3.5.2 디렉토리가 생성된다.
  2. PATH 환경 변수에서 메이븐 bin 디렉토리를 추가한다. 
  3. 예) PATH=c:\apache-maven-3.5.2\bin;%PATH%
  4. JAVA_HOME 환경 변수가 올바르게 설정되어 있는지 확인한다. 참고로, 메이븐 3.3 이후부터는 자바 1.7 이상을 요구한다.
  5. 설치를 끝냈으면, 다음 명령어를 실행해서 메이븐이 올바르게 동작하는지 확인한다.
환경 변수를 모두 설정해 주었다면 아래의 명령어를 사용해서 Maven이 제대로 실행되는 지 확인해보자.

$ mvn -version
Apache Maven 3.5.2 (138edd61fd100ec658bfa2d307c43b76940a5d7d; 2017-10-18T16:58:13+09:00)
Maven home: /Users/madvirus/apache-maven-3.5.2
Java version: 9.0.1, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home
Default locale: ko_KR, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.1", arch: "x86_64", family: "mac"

Maven 프로젝트 생성하기

설치가 끝났다면 Maven 프로젝트를 생성해 보자. 명령 프롬프트에서 아래 명령어를 실행하면 된다. (아래 명령어를 처음 실행할 경우 꽤 오랜 시간이 걸리는데, 그 이유는 Maven이 필요한 플러그인과 모듈을 다운로드 받기 때문이다. Maven 배포판은 최초로 Maven을 사용하는 데 필요한 모듈만 포함하고 있고, 그 외에 archetype 플러그인, compiler 플러그인 등 Maven을 사용하는 데 필요한 모듈은 포함하고 있지 않다. 이들 모듈은 실제로 필요할 때 Maven 중앙 리포지토리에서 로딩된다.)


mvn archetype:generate


위 명령어를 실행하면 Maven 프로젝트를 생성하는 데 필요한 정보를 입력하라는 메시지가 단계적으로 뜨고, 각 항목별로 알맞은 값을 입력해주면 된다. 아래는 실행 화면 예이다. 붉은색으로 표시한 것은 입력한 값이다.


C:\Users\madvirus>mvn archetype:generate

[INFO] Scanning for projects...

[INFO] 

[INFO] ------------------------------------------------------------------------

[INFO] Building Maven Stub Project (No POM) 1

[INFO] ------------------------------------------------------------------------

...생략

Choose archetype:

1: remote -> am.ik.archetype:maven-reactjs-blank-archetype (Blank Project for React.js)

2: remote -> am.ik.archetype:msgpack-rpc-jersey-blank-archetype (Blank Project for Spring Boot + Jersey)

...생략

1090: remote -> org.apache.maven.archetypes:maven-archetype-portlet (An archetype which contains a sample JSR-268 Portlet.)

1091: remote -> org.apache.maven.archetypes:maven-archetype-profiles (-)

1092: remote -> org.apache.maven.archetypes:maven-archetype-quickstart (An archetype which contains a sample Maven project.)

...생략

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 1092: [엔터]

Choose version:

1: 1.0-alpha-1

2: 1.0-alpha-2

3: 1.0-alpha-3

4: 1.0-alpha-4

5: 1.0

6: 1.1

Choose a number: 6: [엔터]

Define value for property 'groupId': : net.madvirus

Define value for property 'artifactId': : sample

Define value for property 'version':  1.0-SNAPSHOT: : [엔터]

Define value for property 'package':  net.madvirus: :  [엔터]

Confirm properties configuration:

groupId: net.madvirus

artifactId: sample

version: 1.0-SNAPSHOT

package: net.madvirus

 Y: : [엔터]

 [INFO] ----------------------------------------------------------------------------

[INFO] Using following parameters for creating project from Old (1.x) Archetype: maven-archetype-quickstart:1.1

[INFO] ----------------------------------------------------------------------------

[INFO] Parameter: groupId, Value: net.madvirus

[INFO] Parameter: packageName, Value: net.madvirus

[INFO] Parameter: package, Value: net.madvirus

[INFO] Parameter: artifactId, Value: sample

[INFO] Parameter: basedir, Value: C:\Users\madvirus

[INFO] Parameter: version, Value: 1.0-SNAPSHOT

[INFO] project created from Old (1.x) Archetype in dir: C:\Users\madvirus\sample


[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 25:52 min

[INFO] Finished at: 2014-07-02T15:17:56+09:00

[INFO] Final Memory: 12M/111M

[INFO] ------------------------------------------------------------------------


과정에서 실제로 입력하는 값은 다음과 같다.

  • groupId - 프로젝트 속하는 그룹 식별 값. 회사, 본부, 또는 단체를 의미하는 값이 오며, 패키지 형식으로 계층을 표현한다. 위에서는 net.madvirus를 groupId로 이용하였다.
  • artifactId - 프로젝트 결과물의 식별 값. 프로젝트나 모듈을 의미하는 값이 온다. 위에서는 sample을 artifactId로 이용하였다.
  • version - 결과물의 버전을 입력한다. 위에서는 기본 값인 1.0-SNAPSHOT을 사용하였다.
  • package - 기본적으로 생성할 패키지를 입력한다. 별도로 입력하지 않을 경우 groupId와 동일한 구조의 패키지를 생성한다.
Maven 프로젝트의 기본 디렉토리 구조


archetype:generate 골이 성공적으로 실행되면, artifactId에 입력한 값과 동일한 이름의 폴더가 생성된다. 위 경우에는 현재 폴더에 sample 이라는 하위 폴더가 생성된다. 위 과정에서 선택한 archetype은 maven-archetype-quickstart 인데, 이 archetype을 선택했을 때 생성되는 폴더 구조는 다음과 같다.


sample
├─src
│   ├─main
│   │  └─java
│   │      └─net
│   │          └─madvirus
│   │              └─App.java
│   ├─test
│       └─java
│           └─net
│               └─madvirus
│                   └─AppTest.java
└─pom.xml


기본적으로 생성되는 폴더를 포함한 Maven 프로젝트의 주요 폴더는 다음과 같다.

  • src/main/java - 자바 소스 파일이 위치한다.
  • src/main/resources - 프로퍼티나 XML 등 리소스 파일이 위치한다. 클래스패스에 포함된다.
  • src/main/webapp - 웹 어플리케이션 관련 파일이 위치한다. (WEB-INF 폴더, JSP 파일 등)
  • src/test/java - 테스트 자바 소스 파일이 위치한다.
  • src/test/resources - 테스트 과정에서 사용되는 리소스 파일이 위치한다. 테스트 시에 사용되는 클래스패스에 포함된다.

기본적으로 생성되지 않은 폴더라 하더라도 직접 생성해주면 된다. 예를 들어 src/main 폴더에 resources 폴더를 생성해주면 Maven은 리소스 폴더로 인식한다.


자바 버전 수정


pom.xml 파일을 열어서 아래 코드를 추가하자. 이 설정은 컴파일 자바 버전을 1.8로 설정한다.



    ...생략


    <build>

        <plugins>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-compiler-plugin</artifactId>

                <configuration>

                    <source>1.8</source>

                    <target>1.8</target>

                    <encoding>UTF-8</encoding>

                </configuration>

            </plugin>

        </plugins>

    </build>


</project>



컴파일 해보기/테스트 실행 해보기/패키지 해보기

이제 간단하게 컴파일과 테스트를 실행해보자. 소스 코드를 컴파일 하려면 다음과 같은 명령어를 실행해주면 된다.


C:\Users\madvirus\sample>mvn compile
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building sample 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ sample ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory C:\Users\madvirus\sample\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ sample ---
[INFO] Compiling 1 source file to C:\Users\madvirus\sample\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.205 s
[INFO] Finished at: 2014-07-03T09:51:15+09:00
[INFO] Final Memory: 11M/110M
[INFO] ------------------------------------------------------------------------


컴파일 된 결과는 target/classes 폴더에 생성된다.


테스트 클래스를 실행해보고 싶다면, 다음과 같은 명령어를 사용하면 된다.


$ mvn test

[INFO] Scanning for projects...

[INFO]                                                                         

[INFO] ------------------------------------------------------------------------

[INFO] Building sample 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO] 

[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ sample ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] skip non existing resourceDirectory /Users/madvirus/sample/src/main/resources

[INFO] 

[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ sample ---

[INFO] Compiling 1 source file to /Users/madvirus/sample/target/classes

[INFO] 

[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ sample ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] skip non existing resourceDirectory /Users/madvirus/sample/src/test/resources

[INFO] 

[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ sample ---

[INFO] Compiling 1 source file to /Users/madvirus/sample/target/test-classes

[INFO] 

[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ sample ---

...최초 실행시 관련 플러그인 파일 다운로드

-------------------------------------------------------

 T E S T S

-------------------------------------------------------

Running net.madvirus.AppTest

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec


Results :


Tests run: 1, Failures: 0, Errors: 0, Skipped: 0


[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 10.238 s

[INFO] Finished at: 2014-07-03T22:20:08+09:00

[INFO] Final Memory: 13M/228M

[INFO] ------------------------------------------------------------------------


그러면, 테스트 코드를 컴파일한 뒤 테스트 코드를 실행한다. 그리고 테스트 성공 실패 여부를 화면에 출력한다. 컴파일 된 테스트 클래스들은 target/test-classes 폴더에 생성되고, 테스트 결과 리포트는 target/surefire-reports 폴더에 저장된다.


(아무것도 한게 없으니 당연하지만) 모든 코드가 정상적으로 만들어지고 테스트도 통과했으니, 이제 배포 가능한 jar 파일을 만들어보자. 아래 명령어를 실행하면 프로젝트를 패키징해서 결과물을 생성한다.


$ mvn package

[INFO] Scanning for projects...

[INFO]                                                                         

[INFO] ------------------------------------------------------------------------

[INFO] Building sample 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO] 

[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ sample ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] skip non existing resourceDirectory /Users/madvirus/sample/src/main/resources

[INFO] 

[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ sample ---

[INFO] Nothing to compile - all classes are up to date

[INFO] 

[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ sample ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] skip non existing resourceDirectory /Users/madvirus/sample/src/test/resources

[INFO] 

[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ sample ---

[INFO] Nothing to compile - all classes are up to date

[INFO] 

[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ sample ---

[INFO] Surefire report directory: /Users/madvirus/sample/target/surefire-reports


-------------------------------------------------------

 T E S T S

-------------------------------------------------------

Running net.madvirus.AppTest

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec


Results :


Tests run: 1, Failures: 0, Errors: 0, Skipped: 0


[INFO] 

[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ sample ---

[INFO] Building jar: /Users/madvirus/sample/target/sample-1.0-SNAPSHOT.jar

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 1.783 s

[INFO] Finished at: 2014-07-03T22:21:59+09:00

[INFO] Final Memory: 8M/156M

[INFO] ------------------------------------------------------------------------


mvn package가 성공적으로 실행되면, target 폴더에 프로젝트 이름과 버전에 따라 알맞은 이름을 갖는 jar 파일이 생성된다. 위 예제의 경우에는 sample-1.0-SNAPSHOT.jar 파일이 생성된 것을 확인할 수 있다.


POM 파일 기본

Maven 프로젝트를 생성하면 pom.xml 파일이 프로젝트 루트 폴더에 생성된다. 이 pom.xml 파일은 Project Object Model 정보를 담고 있는 파일로서, 이 파일에서 다루는 주요 설정 정보는 다음과 같다.

  • 프로젝트 정보 - 프로젝트의 이름, 개발자 목록, 라이센스 등의 정보를 기술
  • 빌드 설정 - 소스, 리소스, 라이프 사이클 별 실행할 플러그인 등 빌드와 관련된 설정을 기술
  • 빌드 환경 - 사용자 환경 별로 달라질 수 있는 프로파일 정보를 기술
  • POM 연관 정보 - 의존 프로젝트(모듈), 상위 프로젝트, 포함하고 있는 하위 모듈 등을 기술

archetype:create 골 실행시 maven-archetype-quickstart Archetype을 선택한 경우 생성되는 pom.xml 파일은 다음과 같다.

[기본으로 생성되는 pom.xml 파일]

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>


  <groupId>net.madvirus</groupId>

  <artifactId>sample</artifactId>

  <version>1.0-SNAPSHOT</version>

  <packaging>jar</packaging>


  <name>sample</name>

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


  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  </properties>


  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>3.8.1</version>

      <scope>test</scope>

    </dependency>

  </dependencies>

</project>


위 POM 파일에서 프로젝트 정보를 기술하는 태그는 다음과 같다.

  • <name> - 프로젝트 이름
  • <url> - 프로젝트 사이트 URL

POM 연관 정보는 프로젝트간 연관 정보를 기술하는데, 관련 태그는 다음과 같다.

  • <groupId> - 프로젝트의 그룹 ID 설정
  • <artifactId> - 프로젝트의 Artifact ID 설정
  • <version> - 버전 설정
  • <packaging> - 패키징 타입 설정. 위 코드의 경우 프로젝트의 결과 Artifact가 jar 파일로 생성됨을 의미한다. jar뿐만 아니라 웹 어플리케이션을 위한 war나 JEE를 위한 ear 등의 패키징 타입이 존재한다.
  • <dependencies> - 이 프로젝트에서 의존하는 다른 프로젝트 정보를 기술한다.
    • <dependency> - 의존하는 프로젝트 POM 정보를 기술
      • <groupId> - 의존하는 프로젝트의 그룹 ID
      • <artifactId> - 의존하는 프로젝트의 artifact ID
      • <version> - 의존하는 프로젝트의 버전
      • <scope> - 의존하는 범위를 설정

의존 설정

<dependency> 부분의 설정에 대해서 좀 더 살펴보도록 하자.

Maven을 사용하지 않을 경우 개발자들은 코드에서 필요로 하는 라이브러리를 각각 다운로드 받아야 한다. 예를 들어 아파치 commons DBCP 라이브러리를 사용하기 위해서는 DBCP뿐만 아니라 common pool 라이브러리도 다운로드 받아야 한다. 물론 commons logging을 비롯한 라이브러리도 모두 추가로 다운로드 받아 설치해 주어야 한다. 즉 코드에서 필요로 하는 라이브러리뿐만 아니라 그 라이브러리가 필요로 하는 또 다른 라이브러리도 직접 찾아서 설치해 주어야 한다.

하지만, Maven을 사용할 경우에는 코드에서 직접적으로 사용하는 모듈에 대한 의존만 추가해주면 된다. 예를 들어 commons-dbcp 모듈을 사용하고 싶은 경우 다음과 같은 <dependency> 코드만 추가해주면 된다.


<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.2.1</version>
</dependency>


그러면, Maven은 commons-dbcp 뿐만 아니라 commons-dbcp가 의존하는 라이브러리를 자동으로 처리해준다. 실제로 1.2.1 버전의 commons-dbcp 모듈의 pom.xml 파일을 보면 의존 부분이 다음과 같이 설정되어 확인할 수 있다.


  <dependencies>
    <dependency>
      <groupId>commons-collections</groupId>
      <artifactId>commons-collections</artifactId>
      <version>2.1</version>
    </dependency>
    <dependency>
      <groupId>commons-pool</groupId>
      <artifactId>commons-pool</artifactId>
      <version>1.2</version>
    </dependency>
    <dependency>
      <groupId>javax.sql</groupId>
      <artifactId>jdbc-stdext</artifactId>
      <version>2.0</version>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>xml-apis</groupId>
      <artifactId>xml-apis</artifactId>
      <version>2.0.2</version>
    </dependency>
    <dependency>
      <groupId>xerces</groupId>
      <artifactId>xerces</artifactId>
      <version>2.0.2</version>
    </dependency>
  </dependencies>


Maven은 commons-dbcp 모듈을 다운로드 받을 때 관련 POM 파일도 함께 다운로드 받는다. (다운로드 받은 파일은 로컬 리포지토리에 저장되는데 이에 대한 내용은 뒤에서 다시 설명하겠다.) 그리고 POM 파일에 명시한 의존 모듈을 함께 다운로드 받는다. 즉 commons-dbcp 1.2.1 버전의 경우 commons-collections 2.1 버전과 commons-pool 1.2 버전 등을 함께 다운로드 받는다. 이런 식으로 반복해서 다운로드 받은 모듈이 필요로 하는 모듈을 다운로드 받고 이들 모듈을 현재 프로젝트에서 사용할 클래스패스에 추가해준다.

따라서, 개발자는 일일이 필요한 모듈을 다운로드 받을 필요가 없으며, 현재 코드에서 직접적으로 필요로 하는 모듈에 대해서만 <dependency>로 추가해주면 된다. 나머지 의존은 모두 Maven이 알맞게 처리해준다.


search.maven.org 사이트에서 POM 정보 찾기

Maven을 사용할 때 자주 찾게 되는 사이트가 search.maven.org 이다. search.maven.org는 Maven 중앙 리포지토리에 등록된 POM 정보를 검색해주는 기능을 제공해준다. 이 사이트를 통해서 추가할 라이브러리의 <dependency> 설정 정보를 구할 수 있다.


의존의 scope: compile, runtime, provided, test

앞의 pom.xml 파일에서 <dependency> 부분을 보면 <scope>를 포함하고 있는 것과 그렇지 않은 것이 존재한다는 것을 알 수 있다. <scope>는 의존하는 모듈이 언제 사용되는 지를 설정할 때 사용되며, <scope>에 올 수 있는 값은 다음의 네 가지가 존재한다.

  • compile - 컴파일 할 때 필요. 테스트 및 런타임에도 클래스패스에 포함된다. <scope>를 설정하지 않을 경우 기본 값은 compile 이다.
  • runtime - 런타임에 필요. JDBC 드라이버 등이 예가 된다. 프로젝트의 코드를 컴파일 할 때는 필요하지 않지만, 실행할 때 필요하다는 것을 의미한다. 배포시 포함된다.
  • provided - 컴파일 할 때 필요하지만, 실제 런타임 때에는 컨테이너 같은 것에서 기본으로 제공되는 모듈임을 의미한다. 예를 들어 서블릿이나 JSP API 등이 이에 해당한다. 배포시 제외된다.
  • test - 테스트 코드를 컴파일 할 때 필요. Mock 테스트를 위한 모듈이 예이다. 테스트 시에 클래스패스에 포함되며, 배포시 제외된다.


원격 리포지토리와 로컬 리포지토리

Maven은 컴파일이나 패키징 등 작업을 실행할 때 필요한 플러그인이나 pom.xml 파일의 <dependency> 등에 설정한 모듈을 Maven 중앙 리포지토리에서 다운로드 받는다. 현재 중앙 리포지토리의 주소는 http://repo1.maven.org/maven2/ 이다.

원격 리포지토리에서 다운로드 받은 모듈은 로컬 리포지토리에 저장된다. 로컬 리포지토리는 [USER_HOME]/.m2/repository 폴더에 생성되며, 로컬 리포지토리에는 다음과 같은 형식의 폴더를 생성한 뒤 다운로드 받은 모듈을 저장한다.


[groupId]/[artifactId]/[version]


예를 들어 commons-dbcp 1.2.1 버전의 경우, 모듈 및 관련 POM 파일이 저장되는 폴더는 다음과 같다.


[USER_HOME]/.m2/repository/commons-dbcp/commons-dbcp/1.2.1


위 폴더에 저장되는 파일은 패키징 된 모듈 파일, pom 파일, 그리고 소스 코드 다운로드 옵션을 실행한 경우에는 소스 코드를 포함한 jar 파일이 포함된다.

일단 원격 리포지토리로부터 파일을 다운로드해서 로컬 리포지토리에 저장하면, 그 뒤로는 로컬 리포지토리에 저장된 파일을 사용하게 된다.

Maven 라이프사이클(Lifecycle)과 플러그인 실행

본 글의 서두에 Maven은 프로젝트의 라이프사이클 기반 프레임워크를 제공한다고 했다. 앞서 프로젝트를 생성한 뒤 컴파일하고(mvn compile), 테스트 하고(mvn test), 패키징 하는(mvn package) 과정을 정해진 명령어를 이용해서 실행했는데, 이때 compile, test, package는 모두 빌드 라이프사이클에 속하는 단계이다.

Maven은 clean, build (default), site의 세 가지 라이프사이클을 제공하고 있다. 각 라이프사이클은 순서를 갖는 단계(phase)로 구성된다. 또한, 각 단계별로 기본적으로 실행되는 플러그인(plugin) 골(goal)이 정의되어 있어서 각 단계마다 알맞은 작업이 실행된다. 아래 표는 디폴트 라이프사이클을 구성하고 있는 주요 실행 단계를 순서대로 정리한 것이다.

[표] 디폴트 라이프사이클의 주요 단계(phase)

 단계 설명  단계에 묶인 플러그인 실행
generate-sources 컴파일 과정에 포함될 소스를 생성한다. 예를 들어 DB 테이블과 매핑되는 자바 코드를 생성해주는 작업이 이 단계에서 실행된다.
process-sources 필터와 같은 작업을 소스 코드에 처리한다.  
generate-resources 패키지에 포함될 자원을 생성한다.   
process-resources 필터와 같은 작업을 자원 파일에 처리하고, 자원 파일을 클래스 출력 디렉토리에 복사한다. resources:resources 
compile 소스 코드를 컴파일해서 클래스 출력 폴더에 클래스를 생성한다. compiler:compile
generate-test-sources 테스트 소스 코드를 생성한다. 예를 들어 특정 클래스에서 자동으로 테스트 케이스를 만드는 작업이 이 단계에서 실행된다.
process-test-sources 필터와 같은 작업을 테스트 소스 코드에 처리한다. resources:testResources 
generate-test-resources 테스트를 위한 자원 파일을 생성한다.   
process-test-resources 필터와 같은 작업을 테스트 자원 파일에 처리하고, 테스트 자원 파일을 테스트 클래스 출력 폴더에 복사한다.  
test-compile 테스트 소스 코드를 컴파일해서 테스트 클래스 추력 폴더에 클래스를 생성한다. compiler:testCompile
test 테스트를 실행한다. surefire:test
package 컴파일 된 코드와 자원 파일들을 jar, war와 같은 배포 형식으로 패키징한다. 패키징에 따라 다름
jar - jar:jar
war - war:war
pom - site:attach-descriptor
ejb - ejb:ejb
install 로컬 리포지토리에 패키지를 복사한다. install:install
deploy 생성된 패키지 파일을 원격 리포지토리에 등록하여, 다른 프로젝트에서 사용할 수 있도록 한다. deploy:deploy

라이프사이클의 특정 단계를 실행하려면 다음과 같이 mvn [단계이름] 명령어를 실행하면 된다.


mvn test
mvn deploy


라이프사이클의 특정 단계를 실행하면 그 단계의 앞에 위치한 모든 단계가 실행된다. 예를 들어 test 단계를 실행하면 test 단계를 실행하기에 앞서 'generate-sources' 단계부터 'test-compile' 단계까지 각 단계를 순서대로 실행한다. 각 단계가 실행될 때는 각 단계에 묶인 골(goal)이 실행된다.

플러그인을 직접 실행할 수도 있다. mvn 명령어에 단계 대신 실행할 플러그인을 지정하면 된다.


mvn surefire:test


단, 플러그인 골을 직접 명시한 경우에는 해당 플러그인만 실행되기 때문에 라이프사이클의 단계가 실행되지는 않는다.


플러그인 골(Plugin Goal)

Maven에서 플러그인을 실행할 때에는 '플러그인이름:플러그인지원골'의 형식으로 실행할 기능을 선택한다. 예를 들어 compiler:compile은 'compiler'는 플러그인에서 'compile' 기능(goal)을 실행한다는 것을 뜻한다.


맺음말

이번 글에서는 Maven의 기본 사용법을 살펴봤다. Maven이 제공하는 의존 관리는 개발자를 jar 지옥(?)에서 구해준다는 것을 알 수 있었다. 또한, Maven은 표준화된 라이프사이클을 제공하고 있기 때문에 개발자가 컴파일-테스트-패키징 등의 과정을 손으로 정의하지 않아도 되며, 개발자는 Maven이 제공하는 단계 중 필요한 단계만 실행하면 된다. 그럼, 나머지 작업(컴파일, 테스트 실행, jar 파일 생성)은 모두 Maven이 처리해준다.

다음 글에서는 많이 사용되고 있는 개발툴인 이클립스에서 Maven 프로젝트를 import하는 방법과 컴파일러 버전을 명시하는 방법을 살펴보도록 하겠다.

관련 자료:





 

Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 쿠하하하 2009.05.29 15:49 신고  댓글주소  수정/삭제  댓글쓰기

    아.. 정말 찾던 정보예요~
    ㅠㅠ 감사합니다.
    담아가도 될까요???
    허락 후에 담아갈게요 ^^

  2. 지피지기 2010.01.14 11:06 신고  댓글주소  수정/삭제  댓글쓰기

    좋은글 감사합니다.
    허락하시면 담아가도 될까요?
    좋은 하루되세요

  3. 옴그루 2010.09.13 20:17 신고  댓글주소  수정/삭제  댓글쓰기

    도움이 많이 되었습니다.
    정말 감사합니다. ^^

  4. rootkim 2012.07.08 16:13 신고  댓글주소  수정/삭제  댓글쓰기

    공부하는 학생입니다.
    Maven에 대해서 환경을 만들어주는데 어려움을 많이 겪었는데,
    정말 많은 도움이 됐습니다. 감사합니다.

  5. 궁금 2014.01.09 16:01 신고  댓글주소  수정/삭제  댓글쓰기

    Path 환경변수 등록할때 맨 뒤에%PATH% 이건 왜 붙는거죠?

  6. 김승광 2014.02.05 16:21 신고  댓글주소  수정/삭제  댓글쓰기

    아마도 기존 환경변수 PATH 에 저장된 경로들에 신규 M2_HOME PATH를 더한(+) 다는 의미 인듯 합니다. 적어도 리눅스에서는요 .
    항상 감사하게 잘 읽고 있습니다.
    새해 복 많이 받으세요!

  7. 표희민 2014.04.01 07:34 신고  댓글주소  수정/삭제  댓글쓰기

    덕분에 도움 많이 되었습니다. 감사합니다!

  8. 고명재 2015.05.06 06:51 신고  댓글주소  수정/삭제  댓글쓰기

    window8에서도 똑같이 설정하면 되는건가요?
    같은 방법으로 했는데 명령프롬프트 창에 mvn -version 쓰면
    mvn은 내부 또는 외부 명령, 실행할수 있는 프로그램, 또는 배치 파일이 아닙니다.
    라는 에러메세지가 나와서요.

  9. 고명재 2015.05.08 03:15 신고  댓글주소  수정/삭제  댓글쓰기

    네, 설명해 주신대로 설정했는데도 같은 에러 메세지가 나와서요.
    eclipse에서의 다른 작동도 문제가 없고, 명령프롬프트 창에 java 또는 javac를 적을 경우에 잘 작동합니다.
    java version 1.7.0_79를 설치했는데요. 혹시 버전에 문제가 있는 것일까요?

    • 최범균 madvirus 2015.05.08 10:12 신고  댓글주소  수정/삭제

      PATH 환경 변수에 [메이븐설치폴더]\bin 이 추가되었는지 확인해보세요.
      java나 javac는 [JAVA설치폴더]\bin 폴더이고, mvn 명령어는 [메이븐설치폴더]\bin 폴더입니다.

  10. 고명재 2015.05.11 08:45 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요. 벌써 세번째 댓글이네요. JAVA_HOME 경로 설정에 문제가 또 생겼었는데. 잘 해결 됐습니다. 감사합니다. 앞으로도 좋은 정보 많이 부탁드릴게요.

  11. 일본외국인노동자 2017.03.30 14:36 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요 프론트쪽일하다가 서버쪽에서 API를 메이븐으로 해달라 어쩌구저쩌구 하나도 모르는거를 해달라고 해서 너무 힘들었는데 자바캔님 설명글듣고 칭찬도 듣고 잘 해결되서 너무나도 고마워서 댓글답니다. 이렇게 또 하나의 지식이 느는것같아서 기쁘네요 ㅋ
    좋은하루되세효 ^^