Maven Chapter6 Page 1 Table of Contents Table of Contents... 1 Revision History... 2 1. 내가꿈꾸는개발환경... 3 2. 메이븐설치및템플릿프로젝트생성... 3 3. 메이븐설정파일... 3 4. 메이븐라이프사이클 lifecycle... 3 5. 메이븐을이용한의존라이브러리관리... 3 6. 메이븐과이클립스통합... 3 6.1 메이븐 eclipse 플러그인적용및개발환경설정... 4 6.2 m2eclipse 플러그인활용하여빌드하기...23 7. 메이븐과데이터베이스통합... 37 8. 메이븐프로파일, 배포... 37 9. 리포팅기능을활용한문서관리... 37 10. 메이븐모듈 module... 37 11. 메이븐사내저장소설치및활용... 37 12. 표준 POM 파일생성및리팩토링... 37 13. 메이븐아키타입 archetype... 37 14. 새로운프로젝트를시작하면서..... 37
Maven Chapter6 Page 2 Revision History Name Date Reason For Changes Version
Maven Chapter6 Page 3 1. 내가꿈꾸는개발환경 2. 메이븐설치및템플릿프로젝트생성 3. 메이븐설정파일 4. 메이븐라이프사이클 lifecycle 5. 메이븐을이용한의존라이브러리관리 6. 메이븐과이클립스통합 프로젝트시작 5 일째 ( 소제목 ) 드디어개발시작이다. 위키북프로젝트를위한메이븐설정까지완료하였다. 이제이클립스통합개발환경에서프로젝트를시작하면된다. 기존에는이클립스에서프로젝트를만들고디렉토리를생성하면서프로젝트를시작했는데지금은메이븐기반의프로젝트를이미생성한상태이다. 그리고의존관계에있는라이브러리를이클립스클래스패스에추가해야하는데관련라이브러리가한디렉토리가아니라여러디렉토리에분산되어있다. 모든디렉토리를일일이수동으로추가해야한단말인가? 생각만해도끔찍하다. 좋은방법없을까? 해답을찾지못해답답해하다가구글검색을통해서해결방법을찾아보기로했다. 혹시나메이븐설정 파일을이용해서이클립스프로젝트로변환해주는플러그인이존재하지않을까? 라는기대감으로 maven
Maven Chapter6 Page 4 eclipse plugin 이라는키워드로검색을했다. 예상했던데로관련플러그인 1 이존재한다. 세상에는정말 똑똑한개발자가많단말이야. 를중얼거리면서이클립스플러그인을적용하기시작한다. 6.1 메이븐 eclipse 플러그인 2 적용및개발환경설정 이클립스는자바진영에서가장많이사용하는통합개발환경이며, 자바진영의많은오픈소스툴이나 프레임워크가이클립스와의통합을지원한다. 메이븐빌드툴의플러그인중에메이븐기반의프로젝트를 이클립스프로젝트로자동변환해주는플러그인 3 이있다. 메이븐빌드툴의설정파일인 pom.xml 파일을보면프로젝트와관련된소스디렉토리, 테스트소스디렉토리, 의존관계에있는라이브러리정보가모두포함되어있다. 따라서 pom.xml 파일의설정정보를바탕으로이클립스프로젝트로자동변환하는것이가능하다. 특히 pom.xml 파일에설정된의존관계에있는라이브러리정보는이클립스의.classpath 파일을자동생성하는데유용하게사용된다..classpath 파일이외에도.project, Web Tools Project( 이하 WTP) 의.settings 디렉토리와설정파일까지모두자동생성할수있다. 이절에서는위키북프로젝트에 eclipse 플러그인을적용하는과정을통하여 eclipse 플러그인활용 뿐만아니라메이븐플러그인을적용하는방법에대해서도다루도록하겠다. 6.1.1 메이븐플러그인적용 메이븐에서활용할수있는플러그인의대부분은다음두개의사이트에서목록을확인할수있다. 메이븐사이트 : http://maven.apache.org/plugins/index.html 1 메이븐 eclipse 플러그인 : http://maven.apache.org/plugins/maven-eclipse-plugin/ 2 이절에서다루는 eclipse 플러그인은메이븐에서제공하는 eclipse 메이븐플러그인이다. 이클립스 IDE 툴에서제공하는플러그인과혼동하지말기바란다. 이클립스에서메이븐을사용하기위한플러그인은 m2eclipse 라는이름으로다음절에서다룬다. 3 이책에서는통합개발환경으로이클립스만을다루고있다. 메이븐은이클립스외에도 Netbeans, IntelliJ 와같은다양한통합개발환경과통합할수있다.
Maven Chapter6 Page 5 모조 mojo 프로젝트 : http://mojo.codehaus.org/plugins.html 메이븐사이트에서제공하는플러그인은메이븐의가장핵심적인기능을담당하고있는플러그인으로써메이븐라이프사이클에포함되어활용되거나메이븐을이용하기위하여반드시필요한플러그인을제공하고있다. 모조프로젝트는수많은커뮤니티와개발자에의하여개발되고있는플러그인을관리하기위한목적으로생성된프로젝트이다. 모조프로젝트는메이븐플러그인개발을위한개발환경과개발가이드라인을제공하고있다. 따라서메이븐플러그인을개발하고자하는개발자는모조프로젝트에서제공하는문서를참고하여개발하는것이가능하다. 이와같이개발된메이븐플러그인은코드하우스 codehaus 저장소 (http://repository.codehaus.org) 를이용하여배포할수있도록지원하고있다. 메이븐에서제공하는플러그인을찾는방법은위두개의목록에서찾는방법도있지만메이븐플러그인이 많은관계로좋은방법은아니다. 가능하면구글과같은검색엔진에서 maven sql plugin, maven tomcat plugin 으로검색하면대부분의경우원하는플러그인을바로찾을수있다. 적용하고싶은플러그인을찾았다면먼저플러그인에서사용할수있는골 goal 목록과골중에서내가 원하는작업을지원하는골이있는지확인한다. 이절에서는프로젝트소스코드를컴파일할때사용하는 compiler 플러그인을메이븐에적용하는과정에대하여살펴보겠다. 메이븐사이트나모조프로젝트의플러그인목록페이지나검색을통하여 compiler 플러그인소개페이지에 접속한다.
Maven Chapter6 Page 6 그림 6-1 compiler 플러그인소개페이지 대부분의메이븐플러그인은그림 6-1 과같은구조로구성되어있다. 플러그인소개페이지에서플러그인에대한간단한소개, 사용가능한골과개요, 사용방법에관한내용이다. 이페이지에서내가원하는골이존재하지는확인하고, 만약일치한다면좌측메뉴의 Goals 와 Usage 를활용하여구체적인내용을확인할수있다. 모조프로젝트에서관리하는플러그인또한그림 6-1 과비슷한구조를가진다. 그림 6-1 의좌측메뉴에서 Goals 페이지에접근하면플러그인에서지원하는골목록을확인할수있으며, 각각의골은상세페이지로이동할수있다. 각골의상세페이지는골에대한설명과골에서설정할수있는 Required Parameters 와 Optional Parameters 에대한정보를제공하고있다. compiler 플러그인의 compile 골상세페이지를보면다음그림과같다.
Maven Chapter6 Page 7 그림 6-2 compiler:compile 골의상세페이지 메이븐플러그인은기본설정을그대로사용할수있지만프로젝트의요구사항에따라설정을변경하는것이가능하다. 각각의플러그인에대한활용방법은그림 6-1 의좌측메뉴의 Usage 와 Examples 를참고할수있으며, 설정할수있는모든정보는그림 6-2 와같은각골의상세페이지의 Required Parameters 와 Optional Parameters 를활용해설정할수있다. 메이븐에서플러그인을설정하려면 <build>/<plugins> 엘리먼트에메이븐플러그인에대한설정을해야 한다. compiler 플러그인에대한기본설정은다음과같다. <project> [...] <build> <plugins> <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <version>2.1</version> </plugin>
Maven Chapter6 Page 8 </plugins> [...] </build> [...] </project> 5 장에서의존관계를설정할때와같이사용하고자하는플러그인의 groupid, artifactid, version 을명시한다. 단, 메이븐사이트에서제공하는플러그인은별도의설정을하지않더라도사용가능하다. 2 장에서최상위 POM 을보면플러그인에대한설정이없음에도불구하고사용가능했었다 4. 이와같이설정을하지않더라도사용가능한이유는메이븐이플러그인을찾는방식때문이다. 메이븐은설정파일에없는플러그인을실행할경우기본으로 groupid 는 org.apache.maven.plugin, artifactid 는 maven-$nameplugin 을찾는다. 예를들어 mvn test:test 와같이존재하지않는 test 플러그인을실행하면다음과같은결과를볼수있다. 그림 6-3 mvn test:test 를실행할때의빌드결과 4 최상위 POM 을보면많은플러그인이 <pluginmanagement/> 엘리먼트에설정되어있다. <pluginmanagement/> 엘리먼트에설정되어있다고해서플러그인을사용하겠다고명시하는것은아니다. 메이븐플러그인을사용하려면 <plugins/> 엘리먼트에 <plugin/> 엘리먼트를추가함으로써가능하다. <pluginmanagement/> 엘리먼트에대한자세한내용은 12 장에서다루고있다.
Maven Chapter6 Page 9 그림 6-3 의빌드결과를보면 test 골을실행하기위하여 org.apache.maven.plugin:maven-test-plugin 이중앙저장소에존재하는지찾는다. 그런데 test 플러그인은중앙저장소에존재하지않는플러그인이기때문에빌드가실패한다. 메이븐빌드툴은기본적으로이와같은규칙으로플러그인을찾아실행한다. 따라서메이븐사이트에서제공하는플러그인은별도의설정을하지않더라도메이븐에서직접사용이가능하다. 메이븐라이프사이클의페이즈에연결되어있는플러그인모두메이븐사이트에서제공하는플러그인이기때문에별도의설정없이도사용이가능한것이다. 메이븐에별도의설정을하지않을경우각플러그인에서제공하는기본설정값을사용한다. 하지만플러그인을사용할때기본설정만으로충분한경우도있지만추가적인설정이필요한경우도자주발생한다. 각플러그인에추가할수있는옵션정보는해당플러그인상세페이지의 Optional Parameters( 그림 6-2 참조 ) 에서찾을수있다. Optional Parameters 를각플러그인에설정할필요가있는경우 <plugin/> 엘리먼트아래에 <configuration/> 엘리먼트를사용해기본설정을변경할수있다. 예를들어 compiler:compile 골을실행할때자바컴파일러에 source 인자와 target 인자 ( 기본값은모두 1.5 이다.)5를변경하고싶다면먼저 compiler:compile 골의상세페이지에서 Optional Parameters 를확인하고다음과같이설정한다. <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <version>2.1</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> 플러그인에전달할인자는 <configuration/> 엘리먼트하위에키 (key) 와값 (value) 형태로전달할수있다. 여기서키 (<source/>, <target/>) 는 Optional Parameters 에서제공하는 Name 값을사용하면된다. 각키에대한값은 Optional Parameters 에서제시하는데이터유형에맞추어서전달하면된다. 앞서살펴본 <source/> 와 <target/> 은데이터유형이 String 이기때문에 1.6 과같은형태로전달하는것이가능하다. 5 자바소스를컴파일하는시점에컴파일되는소스파일과클래스파일이동작하게될 JDK 버전을 동적으로전달할수있다. 자세한내용은 http://java.sun.com/javase/6/docs/technotes/tools/solaris/javac.html 문서를참고하기바란다.
Maven Chapter6 Page 10 Optional Parameters 의데이터유형에대하여살펴보면다음과같다. boolean: true 또는 false int: 숫자형태 ( 예 : 0, 1, 2) String: 일반문자형태 ( 예 : 1.5, R7) File: 디렉토리또는파일위치 ( 예 : d:\workspace\project\test.txt) List: 여러개의인자를전달하는경우. List 데이터형태를가지는대부분의인자이름은 projectnatures 와같은형태이다. 이와같은이름을가질경우플러그인을설정할때인자는다음 소스와같이상위엘리먼트는복수형, 하위엘리먼트는단수형으로여러개를가지는구조이다. <configuration> <projectnatures> <projectnature>org.eclipse.jdt.core.javanature</projectnature> <projectnature>org.eclipse.wst.common.modulecore.modulecorenature</projectnature> </projectnatures> </configuration> 위데이터유형에속하지않는 Map, Set, 배열형태는각골의상세페이지에서예제까지포함하고있으니이문서를참고하여설정하는것이가능하다. 메이븐플러그인은선택적으로설정하는인자가아니라반드시설정해야하는인자가있는경우도있다. 이정보는각플러그인의골상세페이지의 Required Parameters 에서확인할수있다. Required Parameters 에있는인자는기본값이존재하는경우설정하지않아도정상적으로동작하지만기본값이존재하지않는경우에는반드시설정해야한다. 지금까지살펴본것처럼하나의메이븐플러그인만제대로사용할수있다면다른플러그인또한같은 방법으로사용하는것이가능하다. 6.1.2 위키북프로젝트에 eclipse 플러그인적용 eclipse 플러그인은메이븐사이트에서제공하는플러그인이라별다른설정을하지않아도사용가능하다. eclipse 플러그인에서사용하는골은 clean 과 eclipse 이다. clean 골은 eclipse 골을실행해자동적으로
Maven Chapter6 Page 11 생성한이클립스프로젝트메타데이터파일 (.project,.classpath) 을삭제한다. 반면 eclipse 골은메타데이터 파일을생성한다. 위키북프로젝트에서 mvn eclipse:eclipse 를실행하면 pom.xml 파일의설정을활용하여.project 파일과.classpath 파일을자동생성한다. 위키북프로젝트를 eclipse 플러그인을활용해이클립스 프로젝트화하면이클립스의 import 기능을활용해가져오기하는것이가능하다. 이클립스로위키북프로젝트를가져오기전에메이븐 eclipse 플러그인을통하여생성되는.classpath 를 살펴보자. <dependency> <groupid>junit</groupid> <artifactid>junit</artifactid> <version>4.7</version> <scope>test</scope> </dependency> 예제 6-1 pom.xml 파일에서 JUnit 라이브러리를의존관계로설정한예제소스 예를들어 pom.xml 파일에 JUnit 라이브러리가예제 6-1 과같이의존관계에있다면.classpath 설정파일에 다음과같이추가된다. <classpathentry kind="var" path="m2_repo/junit/junit/4.7/junit-4.7.jar"/> 메이븐은프로젝트와의존관계에있는라이브러리를프로젝트에서관리하지않고로컬저장소에서관리한다. 따라서.classpath 에생성되는라이브러리의경로또한저장소를가리키도록생성된다. 단, 이클립스에프로젝트를가져오기한후 M2_REPO 변수를설정해야한다. 이클립스에서 M2_REPO 변수를설정하는과정은잠시후에살펴보기로하자. 라이브러리설정을제외한다른부분은이클립스에서소스폴더와빌드한결과물을관리하기위한경로 설정이다. 다음소스를보면알수있듯이 pom.xml 에설정된내용을바탕으로.classpath 가생성된다. <classpathentry kind="src" path="src/test/java" output="target/test-classes" including="**/*.java"/> <classpathentry kind="src" path="src/main/java" including="**/*.java"/> <classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/> <classpathentry kind="output" path="target/classes"/> 이제앞에서빌드한위키북프로젝트를이클립스로가져와보자. 이클립스의메뉴에서 File >> Import >> General >> Existing Projects into Workspace 를선택해 import 한다.
Maven Chapter6 Page 12 그림 6-4 이클립스의 import 화면 그림 6-5 위키북프로젝트를 import 하는화면 그림 6-5 에서 Browse 버튼을선택하면기본으로현재이클립스워크스페이스에존재하는프로젝트를 Import 할수있다. 만약다른디렉토리에있는프로젝트를 Import 하고자한다면 Browse 버튼을선택해 다른디렉토리를선택하면된다. 위키북프로젝트를가져오기한결과는그림 6-6 과같다.
Maven Chapter6 Page 13 그림 6-6 이클립스에가져오기한위키북프로젝트화면 위키북프로젝트를이클립스로가져오기하면그림 6-6 과같이에러가발생한다. 에러메시지는다음과같다. Unbound classpath variable: 'M2_REPO/aopalliance/aopalliance/1.0/aopalliance-1.0.jar' in project 'wikibook 이에러가발생한원인은메이븐 eclipse 플러그인설정을통하여위키북프로젝트와의존관계에있는모든 라이브러리가자동으로.classpath 파일에설정했는데 classpath variable 에 M2_REPO 가설정되어있지 않기때문이다. M2_REPO 설정은 Window >> Preferences >> Java >> Build Path >> Classpath Variables 에서추가할수 있다. M2_REPO 변수는메이븐의로컬저장소경로 (USER_HOME/.m2/repository) 를설정한다. 만약로컬 저장소의경로가변경되었다면변경한디렉토리경로를설정한다.
Maven Chapter6 Page 14 그림 6-7 이클립스에서 M2_REPO 를설정하는화면 설정방법은 Classpath Variables 메뉴에서 New 버튼클릭 >> Folder 버튼클릭한후 USER_HOME/.m2/repository 디렉토리를선택한다. 그림 6-7 과같이 M2_REPO 변수를추가하면위키북 프로젝트가에러없이다시빌드된다. 메이븐 eclipse 플러그인의기본설정으로위키북프로젝트를빌드한결과위키북프로젝트는이클립스의 Java Project 로생성된다. 위키북프로젝트는웹서비스를위한프로젝트이기때문에개발의편의성을위해이클립스하위프로젝트중의하나인 Web Tools Project( 이하 WTP) 를위한 Dynamic Web Project 로생성하고싶다. Dynamic Web Project 로생성하면 WTP 의기능을이용하여이클립스에서톰캣서버와같은서블릿컨테이너에바로배포할수있기때문이다. 메이븐 eclipse 플러그인에서 WTP 기반의 Dynamic Web Project 로생성하려면다음과같이설정한다. <?xml version="1.0" encoding="utf-8"?> <project> [...] <build> <plugins> <plugin> <artifactid>maven-eclipse-plugin</artifactid>
Maven Chapter6 Page 15 <version>2.8</version> <configuration> <wtpversion>2.0</wtpversion> <wtpcontextname>/</wtpcontextname> </configuration> </plugin> </plugins> </build>... </project> 예제 6-2 pom.xml 파일에 eclipse 플러그인을설정하는예제소스 예제 6-2 와같이위키북프로젝트에서사용할 wtpversion 과 wtpcontextname 을설정한다. 예제 6-2 설정을추가한후 mvn eclipse:clean eclipse:eclipse 를실행하면앞에서자동으로생성된.project,.classpath 파일을제거한후다시생성되며, wikibook 디렉토리아래에.settings 디렉토리가생성되면서 Dynamic Web Project 로생성된다. < 참고사항 > 예제 6-2 와같이설정후 eclipse 플러그인으로빌드를하면 Java compiler level does not match the version of the installed Java project facet. 에러가발생하는경우가있다. 이에러가발생하는이유는.settings/org.eclipse.wst.common.project.facet.core.xml 파일에설정되어있는자바 compiler 버전과 <installed facet="jst.java" version="1.4"/> 설정의 version 이일치하지않아서발생하는문제이다. 이문제를해결하기위하여 compiler 플러그인의 source 와 target 설정을다음과같이현재자바 compiler 버전과맞도록설정한다. <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <version>2.1</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </ 참고사항 >
Maven Chapter6 Page 16 위키북프로젝트를 Dynamic Web Project 로설정하는작업이완료되면다음은서블릿컨테이너를 설정하고배포해야한다. WTP 프로젝트를배포하려면먼저서블릿컨테이너를추가해야한다. 새서버추가는이클립스의 Window >> Preferences >> Server >> Runtime Environments 에서할수있다. WTP 에서기본으로제공하는서버는톰캣, IBM 웹스피어 Websphere, 제이보스 JBoss, Oracle OC4J 등다양한종류의서버를추가할수있다. 로컬에추가하고싶은서버를설치한다음이클립스에서해당서버를연결한다. 그림 6-8 이클립스톰캣서버를추가하는화면 그림 6-8 과같이서버를추가한다음 Window >> Show View >> Other >> Server >> Servers 로이동한 다음 오른쪽클릭 >> New >> Server 를선택한다. 이화면에서그림 6-8 에서추가한톰캣서버를 선택 ( 그림 6-9) 한다음앞에서생성한위키북프로젝트를서버에배포 ( 그림 6-10) 할수있다.
Maven Chapter6 Page 17 그림 6-9 설정할서버를선택하는화면 그림 6-10 위키북프로젝트를배포하는화면
Maven Chapter6 Page 18 6.1.3 위키북프로젝트개발시작 드디어이클립스에서위키북프로젝트를시작하기위한기반작업을완료했다. 다른업무를진행하면서짬짬이시간을냈지만프로젝트를시작한지 5 일동안소스코드한줄개발하지못했다. 지금까지메이븐을공부하고위키북프로젝트에대한빌드환경을만드느라다소느린듯하지만지금투자한시간이프로젝트를진행하면서더큰효과를만들어내리라는확신때문에불안하지않다. 솔직히메이븐에대한경험이없는상태에서덜컥도입하자고했기때문에앞으로무슨문제가발생할지알수가없어약간불안하기는하다. 아직위키북프로젝트에대한분석작업이끝나지않은상태라오늘부터본격적인개발을하기는힘들겠다. 오늘은스트럿츠 2, 스프링, 아이바티스에익숙하지않은개발자들이참고할만한샘플소스를만드는데남은 시간을할애해야겠다. 샘플소스를만들면서공통으로사용할만한소스도필요하다면추가해봐야겠다. 소스코드를추가하기전에지난번프로젝트에서유용하게사용했던 SpringSource Tool Suite( 이하 STS) 플러그인 6 을설치해야겠다. STS 이클립스플러그인설치를완료한다음위키북프로젝트가스프링 Nature 7 속성을가지도록설정했다. STS 설정을완료한다음스프링프레임워크설정파일을추가하고스프링프레임워크에대한샘플소스코드를만드는작업부터시작했다. 이작업을진행하던중스프링프레임워크의소스코드가어떤방식으로구현되어있는지궁금한부분이있어 F3 단축키를이용해소스코드에접근하려고했으나예상했듯이스프링프레임워크에대한소스코드를이클립스설정에추가하지않았으니소스코드가보이지않는것이당연하다. 스프링프레임워크소스코드를보려면지금까지그랬던것처럼스프링프레임워크사이트에접속, 소스 코드다운로드, 압축을풀어소스코드를위키북프로젝트에서참조가가능하도록설정해야한다. 이작업 때문에 20 분이나되는시간을허비했다. 물론 20 분사이에기반라이브러리작업은계속했지만병행해서 6 스프링소스 SpringSource 에서제공하는이클립스플러그인으로스프링프레임워크를사용하는프로젝트에서 사용하면스프링프레임워크설정파일을관리하는데유용하다. 이클립스 3.5 버전에대한 Update URL 은 http://www.springsource.com/update/e3.5 이다. 7 스프링 Nature 란이클립스에서프로젝트가스프링프레임워크기반의프로젝트라는것을인식하도록설정하는것을의미한다. 스프링 Nature 를설정할경우프로젝트내에존재하는스프링설정파일을자동으로인식한다. 설정방법은프로젝트오른쪽클릭 >> Spring Tools >> Add Spring Project Nature 를선택하면된다. 각프로젝트에대한 Nature 설정은해당프로젝트의.project 설정파일에서관리한다.
Maven Chapter6 Page 19 작업을하다보니업무효율이높지않다. 좀더효율적인방법없을까? 스프링프레임워크뿐만아니라다른 라이브러리소스를참고하고싶을때마다이짓을해야된다니생각만해도끔찍하다. 스프링프레임워크에대한기반작업을완료하고마지막으로단위테스트를진행하려는데스프링테스트 (spring-test) 라이브러리가의존관계에설정되어있지않아 pom.xml 파일에의존관계를추가한다. MvnRepository 사이트 8 에서검색을하려다 spring-orm 라이브러리에대한 dependency 설정을복사해통밥으로다음과같이설정했다. <dependency> <groupid>org.springframework</groupid> <artifactid>spring-test</artifactid> <version>${spring.verion}</version> </dependency> 스프링프레임워크의하위라이브러리이기때문에 groupid 와 version 은같은것이확실하고 artifactid 만 spring-orm 에서 spring-test 로바꾸고 mvn eclipse:clean eclipse:eclipse 로빌드를했더니역시나의예상이맞았다. 빌드가성공했다. 아직찍기실력이녹슬지않았다고자찬하면서단위테스트작업을진행했다. 단위테스트작업을하다가스프링소스코드를다시한번참조하려고 F3 를눌렀다. 헉!! 이게뭐지. 왜소스코드가아니라바이너리코드가보이는거야? 왜소스코드가보이지않는지.classpath 파일을열어확인해보니앞에서라이브러리에설정했던소스코드연결이사라져버렸다. 맞다. 메이븐 eclipse 플러그인을이용해다시빌드하면.classpath 파일이다시만들어지는구나. 그렇다면.project 에설정했던 Spring Nature 설정도초기화됐겠다. 이를어쩐다. 오늘은이두가지문제만해결해도좋을듯하다. 특히각라이브러리에대한소스코드첨부를자동으로설정할수있다면얼마나많은시간을절약할수있을까? 지금까지자주는아니지만오픈소스라이브러리에대한소스코드를확인하기귀찮아서그냥넘어간경우도많은데이기능을자동화할수있다면디버깅하는데도많은도움이될듯하다. 해결책을찾으려면먼저메이븐 eclipse 플러그인에서활용할수있는인자를찾아봐야겠다. eclipse:eclipse 골상세페이지의 Optional Parameters 를분석하던중내눈에확뜨이는 Name 이있었으니 downloadsources 와 downloadjavadocs 였다. 나는소스코드에대한참조만을바랬는데 Javadoc 문서까지자동화가가능하단말인가? 이두개설정값을보니 boolean 이라일단 eclipse 플러그인설정에이두개의설정값을 true 로설정하고 mvn eclipse:clean eclipse:eclipse 를실행한다. 8 http://mvnrepository.com/
Maven Chapter6 Page 20 <plugin> <artifactid>maven-eclipse-plugin</artifactid> <version>2.8</version> <configuration> <wtpversion>2.0</wtpversion> <wtpcontextname>/</wtpcontextname> <downloadsources>true</downloadsources> <downloadjavadocs>true</downloadjavadocs> </configuration> </plugin> 빌드를실행하니메이븐중앙저장소에서소스코드를다운받는다. 빌드가진행되는동안메이븐중앙저장소에접속해소스코드와자바독 Javadoc 도있는지확인해봤다. 그림 6-11 중앙저장소의 JUnit 과 struts2-core 라이브러리 역시예상한바와같이라이브러리파일뿐만아니라소스코드와자바독이포함되어있었다. 단, 모든라이브러리가소스코드와자바독을가지고있지않았다. 그림 6-11 을보면 struts-core 는바이너리코드, 소스코드, 자바독까지모두포함하고있지만, JUnit 은자바독을포함하고있지않다. 분명앞에서도메이븐중앙저장소에서라이브러리를찾아봤는데그때는관심이없어서제대로확인하지못했다.
Maven Chapter6 Page 21 빌드가완료되었다. 먼저.classpath 파일을열어봤더니내가기대했던데로소스코드가추가되어있다. <classpathentry kind="var" path="m2_repo/junit/junit/4.7/junit-4.7.jar" sourcepath="m2_repo/junit/junit/4.7/junit- 4.7-sources.jar"/> 이클립스위키북프로젝트를 F5 키를눌러새로고침을하고스프링 API 에접근했더니소스코드가열렸다. 메이븐을사용하면서기대하지도않았던기능을덤으로얻게된듯하여너무기쁘다. 그동안 앤트도편한데왜메이븐을적용하느냐? 고불평했던개발자에게은근히자랑해봐야겠다. 내가느꼈던감동만큼은아니더라도작은감동이라도받겠지. 두번째문제는작은문제이기는하지만프로젝트에처음합류하는개발자는문제의원인을찾는데많은 시간을허비할듯하다. 해결책을찾기위하여먼저위키북프로젝트에스프링 Nature 속성을추가하고.project 파일을열어추가할부분을찾아봤다. <projectdescription> [...] <buildspec> [...] <buildcommand> <name>org.springframework.ide.eclipse.core.springbuilder</name> </buildcommand> </buildspec> <natures> [...] <nature>org.springframework.ide.eclipse.core.springnature</nature> </natures> </projectdescription> 스프링 Nature 속성을추가했더니.project 파일의 <buildcommand/> 와 <nature/> 두개의설정이추가된것을확인했다. 이문제에대한해결방법또한메이븐 eclipse 플러그인의 eclipse 골상세페이지에서찾았다. Optional Parameters 를찾다보니설명부분에샘플예제까지스프링 Nature 로되어있어금방찾을수있었다.( 그림 6-12 참조 )
Maven Chapter6 Page 22 그림 6-12 eclipse 플러그인의상세페이지의 additionalbuildcommands 설정 이문제에대한해결방법은 additionalprojectnatures 와 additionalbuildcommands 를사용하면된다. 이두 Parameter 의샘플소스가스프링 Nature 로되어있어이소스를복사해설정을완료했다. <plugin> <artifactid>maven-eclipse-plugin</artifactid> <version>2.8</version> <configuration> <wtpversion>2.0</wtpversion> <wtpcontextname>/</wtpcontextname> <downloadsources>true</downloadsources> <downloadjavadocs>true</downloadjavadocs> <additionalbuildcommands> <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand> </additionalbuildcommands> <additionalprojectnatures> <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature> </additionalprojectnatures> </configuration> </plugin> mvn eclipse:clean eclipse:eclipse 를실행해빌드를진행하고새로고침을한결과예상한데로.project 에스프링 Nature 가추가되어있는것을확인할수있었다. 오늘샘플소스를만들고기반라이브러리까지만들고퇴근하려고했는데위두가지문제를해결하다보니 하루가지나가버렸다. 계획했던작업을완료하지는못했지만더큰소득을얻었다. 메이븐은알면알수록더 매력적이라는생각이든다. 오늘보다나은내일이되기를기대하면서퇴근한다.
Maven Chapter6 Page 23 6.2 m2eclipse 플러그인활용하여빌드하기 프로젝트시작 6 일째 ( 소제목 ) 오늘은어제목표로했던작업을완료하겠다는목표로오전내내기반라이브러리와샘플소스를만들었다. 샘플소스를만들면서추가적으로필요한라이브러리가있어의존관계설정을추가하고빌드하는과정을반복해서진행했다. 이클립스와명령프롬프트를번갈아사용하다보니괜찮은이클립스플러그인을찾게되었다. 이클립스가워낙많은플러그인을보유하고있어메이븐을지원하는플러그인은당연히있으리라생각하고찾아봤다. 역시있다. 이클립스를처음사용하기시작했을때괜찮은플러그인을찾아설치하던때를회상하면서메이븐플러그인설치를시작했다. < 참고사항 > 메이븐설정파일이변경될때마다매번빌드하기귀찮은팀은메이븐 eclipse 플러그인에서자동생성되는모든설정파일을버전관리시스템으로공유할수있다. 나또한, 이방법으로개발환경을공유할때도있다. 그러나이방법을사용할때개발자가개발자 PC 의절대경로를사용하면문제가발생할수있다. 따라서자동생성되는설정파일을공유하기보다는개발자가로컬에서빌드하도록하는것이바람직하다. </ 참고사항 > 프로젝트를진행하면서의존관계에있는라이브러리의버전이변경되거나새라이브러리가추가되는경우가자주있다. 이와같은상황이발생할때마다 mvn eclipse:clean eclipse:eclipse 를실행하고프로젝트를재빌드해야한다. 그러나이때마다명령프롬프트에서메이븐 eclipse 플러그인을재빌드하는작업은귀찮은작업이다. m2eclipse(http://m2eclipse.sonatype.org/) 플러그인을이용하면명령프롬프트로이동하지않더라도모든작업을이클립스내에서가능하다. 이절에서는지금까지생성한위키북프로젝트를 m2eclipse 플러그인을활용하여생성하고실행하는방법에대하여살펴보도록하겠다. 6.2.1 m2eclipse 플러그인설치 m2eclipse 플러그인을사용하려면먼저이클립스의 Help >> Install New Software 이동하여 m2eclipse 플러그인을설치한다. m2eclipse 플러그인의 update url 은 http://m2eclipse.sonatype.org/sites/m2e 이다.
Maven Chapter6 Page 24 그림 6-13 m2eclipse 플러그인을설치하는화면 6.2.2 프로젝트생성 m2eclipse 플러그인을설치하면이클립스에서메이븐프로젝트를생성하는것이가능하다. File >> New >> Project 로이동한후 Maven 메뉴로이동한후 Maven Project 를선택한다.
Maven Chapter6 Page 25 그림 6-14 메이븐프로젝트를생성하는화면 그림 6-14 를보면버전관리시스템에존재하는프로젝트를메이븐프로젝트로체크아웃하는기능 (Checkout Maven Projects from SCM) 부터여러개의모듈을관리할수있는기능 (Maven Module) 까지제공하고있다. 이절에서는위키북프로젝트를생성하기위하여 Maven Project 메뉴를선택하고 Next 버튼을선택한다. 그림 6-15 프로젝트생성경로를선택하는화면
Maven Chapter6 Page 26 그림 6-15 의기본설정은 Create a simple project(skip archetype selection) 이체크되어있지않은상태이다. 기본설정으로다음단계로넘어가면 2 장에서아키타입의대화식모드를이용하여프로젝트를생성하는과정과같다. 메이븐에서기본으로제공하는아키타입을이용하여프로젝트를생성할경우불필요한소스코드를제거하고 JUnit 의존관계설정을제거해야한다. 특히 maven-archetype-webapp 아키타입의경우소스폴더가자동으로생성되지않아추가적으로생성해야하는불편함이있다. 이같은불편함을없애고단순히메이븐기본디렉토리를포함하는프로젝트를생성하고싶다면그림 6-15 와같이 Create a simple project(skip archetype selection) 를체크한후 Next 버튼을누르고 프로젝트와관련한정보를입력한다. 그림 6-16 위키북프로젝트에대한기본정보를입력하는화면 그림 6-16 에서보는바와같이위키북프로젝트에서사용할 Group Id, Artifact Id, Version, Packaging 을 입력하고 Finish 버튼을눌러프로젝트를생성한다.
Maven Chapter6 Page 27 그림 6-17 m2eclipse 플러그인을활용하여생성한위키북프로젝트 m2eclipse 플러그인을기반으로프로젝트를생성할경우그림 6-17 에서보는바와같이기본디렉토리를 가지는템플릿프로젝트가생성된다. 위키북프로젝트의 pom.xml 파일을열어보면그림 6-17 에서입력한 정보를제외하고는아무런설정정보도추가되어있지않다. <project...> <modelversion>4.0.0</modelversion> <groupid>net.javajigi</groupid> <artifactid>wikibook</artifactid> <version>1.0-snapshot</version> <packaging>war</packaging> <name>wikibook</name> </project> 6.2.3 m2eclipse 플러그인저장소설정 m2eclipse 플러그인을설치하면그림 6-17 에서볼수있듯이 pom.xml 파일과프로젝트의좌측상단에 푸른색으로 M 자가표시된다. 이는 m2eclipse 플러그인이메이븐기본설정파일을인식한다는뜻이다. m2eclipse 플러그인을설치하면 M2_REPO Classpath Variables 를자동으로추가한다. m2eclipse 플러그인을설치한후 Window >> Perferences >> Java >> Build Path >> Classpath Variable 메뉴로 이동해보면그림 6-18 과같이 M2_REPO 가 non modifiable 로추가되어있는것을알수있다.
Maven Chapter6 Page 28 그림 6-18 m2eclipse 플러그인을설치한후의 M2_REPO 설정 M2_REPO 변수를 m2eclipse 플러그인이관리하고있기때문에수정할수없는상태로관리된다. 그림 6-18 에서확인할수있듯이 M2_REPO 값은기본로컬저장소인 USER_HOME/.m2/repository 값으로 설정된다. 만약로컬저장소를변경해서사용하고있다면다음과같이로컬저장소를변경해야한다. 먼저테스트를위하여 USER_HOME/.m2/settings.xml 파일의로컬저장소설정을다음과같이 D:\m2\repository 디렉토리로설정한다. <settings...> <localrepository>d:\m2\repository</localrepository> [...] </settings> 예제 6-3 로컬저장소를 D:\m2\repository 디렉토리로설정하는 settings.xml 파일 기본로컬저장소를사용하지않으면먼저 Window >> Perferences >> Maven >> User Settings 메뉴로 이동한후 Update Settings 버튼을클릭한다.
Maven Chapter6 Page 29 그림 6-19 m2eclipse 플러그인에서로컬저장소의경로를변경하는화면 Update Settings 버튼을클릭하면 Local Repository 의값이그림 6-19 와같이 D:\m2\repository 로변경된다. Update Settings 버튼을클릭할경우 Local Repository 의값이바로반영되지않는경우가있다. 이때는다른메뉴에접근한후다시 User Settings 메뉴로이동해보면 settings.xml 파일에설정한로컬저장소로반영되어있는것을확인할수있다. 로컬저장소의경로를변경할경우 Window >> Perferences >> Java >> Build Path >> Classpath Variable 메뉴에설정되어있는 M2_REPO 도변경해야한다. M2_REPO 의값을새로설정한로컬저장소로 변경하려면앞의과정을통하여로컬저장소를변경한후이클립스를재시작해야하면자동으로반영된다. 6.2.4 m2eclipse 를활용한메이븐실행 m2eclipse 를설치한다음 pom.xml 파일에서오른쪽클릭 >> Run As 로이동하면메이븐에서자주사용하는페이즈와골을실행할수있다. m2eclipse 를활용하여메이븐명령을실행하려면먼저 USER_HOME\.m2 디렉토리에 settings.xml 파일을생성해야한다. 루트엘리먼트 (<settings/>) 를가지는 settings.xml 파일을생성하거나 MAVEN_HOME\conf 디렉토리의 settings.xml 파일을복사한다.
Maven Chapter6 Page 30 그림 6-20 m2eclipse 에서실행가능한페이즈와골 그림 6-20 을보면 clean, install, package 등자주사용하는메이븐페이즈를실행할수있도록지원하고있다. 만약 Run As 메뉴에서기본으로제공하지않는페이즈나골을실행하려면그림 6-20 에서 Maven build.. 을실행한다. Maven build.. 을실행하면명령프롬프트에서메이븐을실행할때와똑같이특정플러그인의골을직접입력해실행할수있다. 그림 6-21 m2eclipse 로메이븐을빌드하는화면
Maven Chapter6 Page 31 이기능을활용하면명령프롬프트에서빌드할필요없이이클립스에서메이븐을빌드할수있다. 이클립스에서명령프롬프트로이동하지않아도되므로유용하다. 메이븐을빌드할때마다이전에빌드했던 eclipse:clean eclipse:eclipse 를입력하는것도귀찮은작업이 된다. 이클립스는이전에실행한모든명령들에대한이력을관리한다. m2eclipse 에서실행한결과는 Run >> Run History 메뉴나이클립스상단의단축아이콘으로접근할수있다. 그림 6-22 이전 m2eclipse 빌드이력을보는화면 < 참고사항 > 내가 m2eclipse 를즐겨사용할때는메이븐기반프로젝트를빌드하기위하여자주사용하는명령어를 등록해사용했다. 예를들어다음과같이명령어를등록해사용할수있다. wikibook for eclipse( 이클립스기반프로젝트로전환 ) : eclipse:clean eclipse:eclipse wikibook for build( 프로젝트빌드 ) : clean test 프로젝트의빌드상태에따라서는특정골을실행해야하는상황이발생할수있기때문에자주사용하는 페이즈와골조합을위와같이등록해사용하면유용하다. </ 참고사항 > 6.2.5 m2eclipse 를활용한설정파일및의존관계관리
Maven Chapter6 Page 32 m2eclipse 플러그인을활용할때유용하게사용할수있는기능이지금까지명령프롬프트상에서명령을 실행하고결과물을확인했던내용을이클립스에서명령어를몰라도좀더좋은 UI 를통해확인할수있다는 것이다. 메이븐기반프로젝트에서 pom.xml 파일을더블클릭하면 pom.xml 파일의소스코드가바로나타나지 않고 Overview 화면이기본으로열리며, 여러개의탭화면을가지는것을확인할수있다. 이각각의탭 중에서유용하게사용할수있는몇가지기능에대하여살펴보도록하겠다. 첫째, Dependencies 탭은해당프로젝트와의존관계에있는라이브러리를관리할수있도록지원한다. 5 장에서 http://mvnrepository.com/ 사이트에접속해라이브러리를검색하고추가하던작업을 m2eclipse 를활용해가능하다. 그림 6-23 Dependencies 탭에서 spring-core 라이브러리를추가하는화면 새로운라이브러리를추가하기위하여먼저 Add 버튼을누르고추가하고자하는라이브러리를검색하고해당라이브러리버전을선택한후 OK 버튼을누르면해당라이브러리가자동으로추가된다. 프로젝트를시작할때나진행중에새로운라이브러리를추가, 변경하는경우가발생한다면이기능을활용하면유용하다. Dependencies 탭우측에있는 Plugins 탭또한메이븐저장소에등록되어있는플러그인을검색해설정할 수있도록지원한다.
Maven Chapter6 Page 33 < 참고사항 > m2eclipse 플러그인을활용해프로젝트를생성하는경우기본으로메이븐 Nature 를가지는상태로프로젝트가생성된다. 프로젝트가메이븐 Nature 를가질경우그림 6-23 과같이의존관계를추가하거나 pom.xml 파일에의존관계를직접추가할경우프로젝트에대한빌드가실행되면서의존관계라이브러리를자동으로다운로드한다. 지금까지 pom.xml 설정파일에직접의존관계를추가하는경우 mvn eclipse:eclipse 를실행해.classpath 파일을다시생성해야했다. 하지만메이븐 Nature 를가질경우프로젝트에대한의존관계설정을자동화하기때문에유용하게사용할수있다. 메이븐 Nature 에대한추가및삭제는해당프로젝트오른쪽클릭 >> Maven 메뉴에서할수있다. 이와같이의존관계설정을자동화하는경우장점도있지만불필요한빌드횟수가많아지고, 개발 PC 의시스템사양이낮은경우에는빌드하는시점에이클립스가잠시동안멈추는현상이발생해개발흐름을깨트리는경우가종종있다. 프로젝트를진행해보면프로젝트초반에는의존관계가변경되는경우가많지만시간이지나면서변경이발생하는경우는많지않다. 따라서설정파일이변경되는시점에만 mvn eclipse:eclipse 를실행해변경된부분을반영하는것도좋은방법이다. </ 참고사항 > 둘째, Dependency Hierarchy 탭화면은 mvn dependency:tree 를실행했을때의결과와 mvn dependency:resolve 를실행했을때의결과화면을보여준다. 현재프로젝트의 Hierarchy 구조와 최종적으로의존관계에있는라이브러리를한눈에파악할수있다.
Maven Chapter6 Page 34 그림 6-24 m2eclipse Dependency Hierarchy 탭화면 셋째, Dependency Graph 탭화면은각각의라이브러리가어떤라이브러리와의존관계를가지는지한눈에 파악할수있도록보여준다. 그림 6-24 의 Hierarchy 구조보다의존관계를파악하는데유용하게사용할수 있다. 그림 6-25 m2eclipse Dependency Graph 탭화면 넷째, Plugins Effective POM 탭은 mvn help:effective-pom 을실행했을때볼수있는소스코드를확인할 수있는탭이다.
Maven Chapter6 Page 35 마지막으로소스코드를직접수정하려면마지막에있는 pom.xml 탭에서가능하다. < 참고사항 > 나는메이븐기반프로젝트를빌드할때 m2eclipse 를사용하지않는다. 메이븐을처음사용할때는정말유용하게사용했는데몇번삽질을했던경험이있기때문이다. 개발업무에바쁜시점에 m2eclipse 를이용하여프로젝트를빌드했는데갑자기빌드가되지않았다. 그래서몇시간을허비하면서해결방법을찾아봤는데도저히해결책을찾을수가없었다. 그러다혹시나해서명령프롬프트에서빌드를했는데정상적으로빌드가되었다. 빌드스크립트는아무런문제가없음에도불구하고문제점을찾으려고했으니문제점을찾을수없는것이당연한결과였다. 그렇게명령프롬프트를사용하면서한참이지나원인을찾아보니명령프롬프트에서사용하는메이븐플러그인의버전과 m2eclipse 가사용하는메이븐플러그인의버전이달라서발생하는문제라는것을알게되었다. 가끔나와같이명령프롬프트와 m2eclipse 의빌드환경이달라서고생을하는경우가있어서가능하면그이후로도명령프롬프트에서빌드를하고있다. 익숙해졌기때문인지명령프롬프트에서작업하더라도큰불편함을잘모르겠다. m2eclipse 를이용할때얻을수있는가장큰장점은 Dependency Hierarchy 탭과 Dependency Graph 탭에서제공하는검색기능이다. 프로젝트를진행하면할수록의존관계설정의복잡도또한증가하기때문에의존관계설정을한눈에파악하기힘들다. 특히문제가발생할경우해당라이브러리를찾아다른라이브러리와의관계를파악하기가쉽지않다. 내가최근에 m2eclipse 를활용해문제를해결한사례를공유해보겠다. 최근에진행하고있는프로젝트는스프링최신버전인 3.0.2.RELEASE 버전과스프링 Security 3.0.2. RELEASE 버전을사용하고있다. 이클립스에서개발을진행하는단계에서는아무런문제가발생하지않았다. 그런데개발서버에배포하기위하여메이븐을이용하여빌드하는순간 org.springframework.core.convert.support.propertytypedescriptor 클래스를찾을수없다는에러가발생했다. 에러내용을확인해보니 PropertyTypeDescriptor 클래스는 spring-core 3.0.2.RELEASE 버전에서추가된클래스였다. 분명히메이븐의의존성전이때문에다른버전의스프링프레임워크라이브러리가포함되었다는예측을하고 m2eclipse 의 Dependency Hierarchy 탭으로이동해 spring-core 로검색을했더니다음과같은결과를얻었다.
Maven Chapter6 Page 36 그림 6-26 Dependency Hierarchy 탭에서 spring-core 로검색한결과화면 그림 6-26 에서확인할수있듯이현재사용하고있는스프링버전은 3.0.2.RELEASE 인데 spring-core 라이브러리는 3.0.1.RELEASE 버전과의존관계를가지고있다. 원인을분석한결과스프링 Security 의 spring-security-core 3.0.2.RELEASE 버전이 spring-core 3.0.1.RELEASE 버전과의존관계를가지는상황이었다. 위상황은메이븐을사용할때종종발생하는상황이지만생각보다해결책을찾는것이쉽지않다. 이같은상황이발생하고해결책을찾지못해메이븐사용을포기하는경우도자주본다. 이같은상황이발생한다면메이븐의의존성전이때문에발생하는것이아닌지의심해보고 m2eclipse 의 Dependency Hierarchy 기능과 Dependency Graph 기능을활용해해결책을찾아보기바란다. 위문제에대한원인과해결책을이해하려면추가적으로알아야하는부분이있는관계로이책의 12 장에서다루도록하겠다. 이같은 m2eclipse 의활용때문에명령프롬프트에서대부분의작업을하지만프로젝트를진행할때 반드시 m2eclipse 를설치한다. </ 참고사항 > m2eclipse 를활용하면메이븐에익숙하지않은개발자라하더라도좀더쉽게접근할수있겠다. 같이일하는개발자에게소개해주면다들좋아라할듯하다. 특히여러개의화면을이동하면서작업하지않고이클립스에서모든작업을하고싶어하는개발자라면더욱유용하겠다. 내일그림 6-25 의 Dependency Graph 를한번보여줘야겠다. 다들신기해하면서눈의휘둥그레지겠지. 오늘은메이븐때문에투자한시간보다위키북프로젝트에더많은시간을투자할수있어좋았다. 이제기반환경도잡히고샘플소스도마련했으니내일은개발자에게메이븐과프레임워크에대한교육시키고좀더속도를내야겠다.
Maven Chapter6 Page 37 7. 메이븐과데이터베이스통합 8. 메이븐프로파일, 배포 9. 리포팅기능을활용한문서관리 10. 메이븐모듈 module 11. 메이븐사내저장소설치및활용 12. 표준 POM 파일생성및리팩토링 13. 메이븐아키타입 archetype 14. 새로운프로젝트를시작하면서..