지금까지 우리는 1개의 Project를 이용해서 간단한 Dao와 Service를 구성해봤습니다. 그렇지만, 실제 프로젝트에서는 여러개의 Project간에 연결이 되어 구성이 되는 것이 일반적입니다. 일반적으로 프로젝트를 구성한다면 약 3개이상의 Project가 구성이 되는것이 대부분입니다.
다음은 일반적인 Web Project의 구성입니다.
# Core / Common : Entity, Dao, Service를 갖는 jar project 입니다.
# PublicWeb (CustomWeb) : 사용자에게 보여질 web page입니다.
# PrivateWeb (AdminWeb) : 관리자용 web page입니다. 사용자에게 공개되는 page가 아닌, 개발자들이 유지보수를 위한 페이지로 만드는 경우가 많습니다.
# Resources : Web에 사용되는 java script 및 image resource, html tag 등을 관리하는 jar project 입니다.
이와 같이 구성이 된다면, 서로간에 build가 되는 순서 역시 변경이 되어야지 됩니다. Core/Common project가 먼저 build가 되고, Resource, PublicWeb, PrivateWeb 순으로 build가 되는 것이 일반적일 것입니다. 그런데, 지금까지 우리가 구성한 project는 pom.xml을 이용한 단일 project만이 지원이 되는 것이 사실입니다. 이런 단일 project가 아닌 multi project를 maven으로 관리하는 법에 대해서 알아보도록 하겠습니다.
maven에서 multi project를 관리하기 위해서는 parent-child pom 관계가 만들어져야지 됩니다. parent project는 child project에 대한 root project로 구성이 되게 됩니다. 또한 child의 child는 구성이 불가능합니다.
구성할 프로젝트는 다음과 같습니다.
Project | Group Id | ArtifactId | compile order | Description |
Parent Project | com.xyzlast.bookstore | bookstore | - | Root Project |
CommonBL | com.xyzlast.bookstore | common-bl | 1 | Business Logic 구성 Project (Entity, Dao, Service 구성) |
WebResource | com.xyzlast.bookstore | web-resources | 2 | Web Resource를 위치 - image, css, javascript에 대한 common library |
PublicWeb | com.xyzlast.bookstore | public-web | 3 | 사용자들이 방문할 web page |
AdminWeb | com.xyzlast.bookstore | admin-web | 3 | 관리자가 방문할 web page |
위 5개의 project는 서로간에 상호 연관성을 갖게 됩니다. 따라서, 위 표와 같이 compile order역시 지정이 가능해야지 됩니다.
이 예제는 새로운 workspace를 구성해서 살펴보는 것이 좋습니다. 기존 eclipse에서 export preferance기능을 이용해서 사용자 설정을 모두 export 시켜두시고 작업에 임하시는것이 좋습니다.
1. Parent Project의 생성
새로운 workspace folder에서 다음 명령어를 실행합니다.
mvn archetype:create -DgroupId=com.xyzlast.bookstore -DartifactId=bookstore
만들어진 bookstore folder안에 있는 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>com.xyzlast.bookstore</groupId>
<artifactId>bookstore</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>bookstore</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
이제 다시 eclipse를 실행후, workspace를 새로만든 workspace로 변경합니다.
그전까지 사용하던 설정을 다시 얻어와야지 되기 때문에 File > Import를 이용해서 preferance를 다시 얻어 설정합니다. 후에 eclipse를 종료 후, 다시 시작해주는것이 좋습니다.
File > Import를 이용해서 Existing Maven Projects 를 선택 후, bookstore를 import 시킵니다.
이제 Parent Project의 구성은 모두 마쳐졌습니다.
- Eclipse를 이용하는 방법
Eclipse에서 new maven project를 선택. Project type을 pom-root로 선택해서 신규 프로젝트를 선택, 생성합니다.
2. Child Project의 구성
child project를 구성하는 것은 eclipse에서 진행하도록 하겠습니다. build 순서에 따라 common-bl을 먼저 구성하도록 하겠습니다.
New Project를 선택해서, Maven Module을 선택합니다. (Maven Project가 아닙니다!)
archeType은 기존 project를 만든것과 동일하게 maven-archetype-quickstart를 선택해줍니다.
groupId 값 및 만들어질 package 이름을 정합니다. package 이름은 jar 이름이 됩니다. 그리고 버젼을 기억하기 쉬운 1.0.0으로 변경합니다.
Finish를 누르면 다음과 같이 Project가 만들어집니다.
이제 나머지 Project들을 모두 만들어줍니다. Resource의 경우에는 동일하게 maven-archetype-quickstart로 구성을 해주고, PublicWeb, PrivateWeb의 경우에는 maven-archetype-webapp 으로 구성을 해주세요. 모든 Project의 구성이 마쳐지면 다음과 같은 모습이 만들어집니다.
bookstore(root) project를 확인해보면 다음과 같은 Folder구조를 갖게 됩니다.
그리고 실제 폴더 구조 역시 Root Project에 하위 폴더가 만들어져서 Project가 구성되게 됩니다. Root Project의 pom.xml 을 한번 확인해보도록 하겠습니다. 기존까지는 없던 modules 항목에 다음과 같은 항목들이 추가 되어 있을것입니다.
<modules>
<module>common-bl</module>
<module>web-resources</module>
<module>public-web</module>
<module>private-web</module>
</modules>
modules 안에 있는 내용대로 build process가 진행되게 됩니다. 확인을 위해, command를 이용해서 mvn compile을 진행해보도록 하겠습니다.
이제 Project간에 서로간에 package를 copy 하는 과정을 추가하도록 하겠습니다. 먼저 Project는 common-bl과 web-resources는 서로간에 dependencies가 없고, public-web, private-web은 common-bl과 web-resources에 dependency를 가지게 됩니다. Root Project에 dependency를 갖는 project를 등록해서 각각의 Project에서 사용하도록 하겠습니다.
Root Project (BookStore Project)의 pom.xml를 열어, 다음과 같은 항목을 추가합니다.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.xyzlast.bookstore</groupId>
<artifactId>common-bl</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.xyzlast.bookstore</groupId>
<artifactId>web-resources</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</dependencyManagement>
이제 dependency를 가질 private-web과 public-web에 다음과 같은 dependency를 추가하도록 합니다.
<dependencies>
<dependency>
<artifactId>common-bl</artifactId>
<groupId>com.xyzlast.bookstore</groupId>
</dependency>
<dependency>
<artifactId>web-resources</artifactId>
<groupId>com.xyzlast.bookstore</groupId>
</dependency>
</dependencies>
버젼이 들어가지 않는것을 확인해주세요. 버젼정보은 root project에서 관리되는 버젼을 따라가게 됩니다.
추가 된 후에, pom.xml의 dependencies를 보면 다음과 같이 표시됩니다.
추가를 모두 마치고 나서 다시 maven에서 package를 진행해보도록 하겠습니다.
packaging 작업이 모두 마쳐진 후, private-web 또는 public-web의 target/private-web/WEB-INF/lib 에 보시면 작업한 common-bl과 web-resources가 jar 형태로 compile 되어서 copy 되어 있는 것을 확인할 수 있습니다.
3. Parent Project 설정
maven을 이용한 multi project를 구성을 하면, parent의 속성이 child project들에게 상속이 됩니다.
지금 구성은 특별히 고치지 않았다면 J2SE-1.5로 compile이 되도록 되어 있습니다. 이것을 java 1.7로 compile이 되도록 parent project를 수정해주도록 합니다. build의 PlugIn에 다음 항목을 추가하도록 하겠습니다.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>utf8</encoding>
</configuration>
</plugin>
추가후, eclipse에서 전체 project의 maven->update를 행하면, project의 build compiler가 변경됨을 알 수 있습니다. 이와 같이, Parent Project에 설정한 항목은 하위 Project에 전달되어 처리가 되게 됩니다. 또한, Parent Project에 dependency에 추가가 되면, Child Project 들에 모두 추가가 됩니다. junit 4.11를 Parent project에 추가하고, child Project에서는 모든 dependency를 제거시켜주세요. pom을 수정후, child project의 pom.xml의 dependency Hierarchy는 다음과 같이 표시가 됩니다.
common-bl, web-resource는 폴더 모양으로, 자신과 같은 Maven Module로 인식이 되고, junit은 물병모양(jar)로 인식되는 것을 확인해주세요.
4. Eclipse 설정
개발된 code를 이용해서 서로간에 개발을 하기 위해서 eclipse에 약간의 설정 변경이 필요합니다. common-bl과 web-resources를 참조하고 있는 public-web과 private-web의 project 설정을 변경해야지 됩니다. project의 property에서 java build path 항목에서 common-bl과 web-resources를 추가해주도록 합니다.
이제 Eclipse에서 public-web과 private-web은 common-bl의 객체에 대한 접근을 할 수 있습니다.
Nexus 서버를 이용한 사내 Common Jar의 이용
사내에서 개발을 하게 되면, 기존의 개발 Library들에 대한 재사용을 하게 됩니다. 그리고 몇몇 팀들은 이러한 Common Jar만 계속해서 기능을 업데이트시키고, 개발을 하는 팀이 생기게 됩니다. 대체적으로 기술지원팀이나 RND 팀이 이런 일을 맡게 되지요.
이렇게 개발된 Common Jar를 배포하기 위한 서버가 Nexus 서버입니다.
Nexus 서버는 우리가 지금까지 libarary를 등록하기 위해서 사용한 maven central repository와 동일한 기능을 제공합니다. 다만, 관리자가 추가로 등록한 jar를 pom을 통해서 관리를 할 수 있는 기능을 따로 제공하는 차이가 있습니다. 사내에서 사용되는 maven central repository라고 보시면 기능이 완전히 동일합니다.
다음 주소에 nexus 서버가 설치되어 있습니다.
nexus 서버의 이용은 매우 단순합니다. 기본적으로 pom.xml에 다음과 같은 설정을 추가하시면 nexus 서버를 사용하실 수 있습니다.
<repositories>
<repository>
<id>local</id>
<url>http://192.168.13.209:8080/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
nexus 서버를 이용하는 경우에는 우리가 사내에서 개발한 jar를 서로간에 공유해서 사용하는 것이 가능합니다. 그리고 maven central에서 제공하지 않는 jar를 등록해서 사용하는 것 역시 가능합니다. 대체적으로 oracle, mssql과 같이 3rd party에서 제공하는 jar를 사용하는 경우에는 nexus 서버를 이용해서 사내에서 공유해서 사용하는 것이 일반적입니다.
많은 것들을 등록해서 사용할 수 있지만, 제가 전에 즐거운 기다림 프로젝트를 하면서 외부 저장소가 필요했었던 jar들은 2개가 있었습니다. 아래 2개의 jar를 등록했으니, pom에 사내 nexus를 등록했을 때와, 등록하지 않았을때를 비교해보시길 바랍니다.
mssql jdbc driver
<dependency>
<groupId>com.microsoft.sqlserver.jdbc</groupId>
<artifactId>sqljdbc</artifactId>
<version>3.0</version>
</dependency>
java pns (iPhone push module)
<dependency>
<groupId>com.googlecode.javapns</groupId>
<artifactId>javapns-jdk16</artifactId>
<version>2.2</version>
</dependency>
Summary
maven을 이용한 multi project 설정과 nexus 서버를 이용한 jar 구성에 대해서 알아봤습니다. 바로 전 시간까지 구성하던 BookStore는 한개의 Project로만 구성이 되어있습니다. 그렇지만, 이는 실전에서는 쓰이지 못합니다.
오늘 보여드린 내용들이 결국은 실전에서 사용되는 구성이 됩니다. 우리가 곧 개발할 시스템의 경우에도 마찬가지고, 타팀에서 역시 마찬가지로 구성이 될 것이라고 생각합니다.
그 이유는 공통된 Business Logic이 존재하고, 이 Logic에 대한 접근 방법이 다른 Web 또는 Application이 여러개 존재할 수 있기 때문입니다. 이러한 다각도적인 접근방법에 있어서, 이러한 multi project 구성은 필수적입니다. 이번에 보여드린 구성은 가장 대표적인 구성입니다. Domain(Model) Layer에 대한 project와 Controller와 View에 대한 project. 그리고 여러개의 Controller/View에 대한 공통 static resource (css, javascript, image)에 대한 Project 구성은 아주 당연하게 사용되는 영역입니다. 일반적으로 모든 web은 3개의 project를 이용해서 구성된다고 생각하시면 좀 더 고민이 줄 수 있을 것 같습니다.