잊지 않겠습니다.

* 사내 강의용으로 사용한 자료를 Blog에 공유합니다. Spring을 이용한 Web 개발에 대한 전반적인 내용에 대해서 다루고 있습니다.



Spring MVC의 구조

지금까지 Spring을 이용한 DB에 대한 접근법과 다루는 법에 대해서 알아보았습니다. 엄밀히 말하면 이 부분은 MVC pattern의 M에 해당되는 내용들입니다. Spring은 구조화된 MVC 구조를 제공하며, Layer 기반의 잘 정형화된 서비스 패턴을 제공합니다. Spring은 MVC를 기반으로 하는 Web Framework를 제공하고 이는 org.springframework.web 안에 제공되어 있습니다.
이제부터 사용할 package인 org.springframework.web에서는 C와 V에 대한 내용들을 다루고 있습니다.

Controller

간단하게 말해서, Controller는 URL과 상호동작하는 Class입니다.
/wpwoms/appuser/getshoplist 라는 URL이 호출되었을 때, Http Request가 연결되는 Class를 의미합니다.
기술적으로는 굉장히 어려운 영역입니다. 이는 Servlet container의 Http Request가 어떻게 해석이 되며, 이 해석된 Http Request에 따라 어떤 class의 어떤 method를 선택할 지에 대한 복잡한 연결을 계속해서 이어가야지 됩니다.
Controller는 기본적으로 다음과 같은 일을 합니다.
1. Servlet이 넘겨주는 HttpServletRequest를 처리한다.
2. Servlet으로 HttpServletResponse를 보내준다.
3. Cookie, Session 에 대한 동기화 작업을 지원한다.

View

View는 HTML 영역이라고 생각하시면 됩니다. 어찌보면 단순한 영역일수도 있지만... 이 부분이 어마어마한 노가다를 요구하는 부분입니다. ㅠ-ㅠ
View는 Controller가 보내주는 데이터를 Html로 표현하는 영역이라고 생각하면 됩니다.
MVC Model이 서로간에 하는 일을 간단히 표현하면 다음 그림과 같습니다.




Front Controller
기존 servlet application 작성시에, url에 각각의 servlet을 등록해서 사용하는 것을 알고 있습니다. 일반적인 MVC 구조의 Web Application은 Front Controller pattern이라고 해서, 가장 최 상단 Front Controller가 모든 Web의 Request를 처리합니다. 그리고, 처리된 Request에 따라 맞는 Controller를 찾아서 호출해주는 형식입니다.  Spring에서는 org.springframework.web.servlet.DispatcherServlet에서 FrontController를 담당합니다. 참고로, .NET에서는 ASP .NET MVC에서는 ControllerFactory가 이 일을 합니다.

Controller
org.springframework.web.servlet.DispatcherServlet에서 처리된 request가 전달되는 영역입니다. 여기에서 HTML의 경우, 화면에 보여줄 model을 생성 하고, 또는 REST API의 경우에는 보내질 객체를 결정하게 됩니다.

View
사용자, Client에게 전달될 내용입니다. Html이 될 수도 있고, JSON이 될 수도 있고, Excel File이 될 수도 있습니다.

model
MVC에서의 M과는 다른 개념입니다. 기존 MVC에서의 Model은 BL 또는 Persistance Layer의 각 model 또는 entity를 의미하지만, 이곳의 model은 View Model입니다. View에 표시되는 model은 Controller에서 작성이 되는 경우도 있고, Domain Model에서 넘겨온 값을 그대로 이용하는 경우도 있습니다. 기존에 Application의 데이터 흐름에서 이야기한 DTO, VO가 여기에 속하게 됩니다.


Spring MVC에서의 Request 처리 과정

Spring MVC는 Web Request를 다음과 같은 순서로 처리되게 됩니다. 



1. Request -> DispatcherServlet : Request가 처음 들어오게 됩니다.
2. DispatcherServlet -> Handler Mapping : DispatcherServlet은 Request를 분석하고 Mapping 중에서 Request와 동일한 Mapping을 찾아냅니다.
3. Handler Mapping -> DispatcherServlet : 찾아진 Handler Mapping을 DispatcherServlet에 전달해줍니다.
4. DispatcherServlet -> Controller : Handler Mapping에서 찾아진 Controller측에 Http Request를 전달해줍니다.
5. Controller -> DispatcherServlet : ModelAndView 객체를 보내줍니다. ModelAndView객체는 View의 이름과 View에 표시될 데이터를 가지고 있습니다.
6. DispatcherServlet -> View Resolver : View이름을 가지고 View를 처리하는 View Resolver에 ViewName을 전달합니다.
7. View Resolver -> DispatcherServlet : 이름에 맞는 View를 return 시켜줍니다.
8. DispatcherServlet -> View : View에 표시될 데이터를 가지고 있는 model을 보내줍니다.
9. View -> DispatcherServlet : model을 이용해서 View를 render 시키고, 그 결과를 DispatcherServlet에 보내줍니다.
10. DispatcherServlet -> Response : View로부터 받은 render된 결과를 Client에게 보내주게 됩니다.

위 그림과 순서는 머리에 익혀두고 있어야지 됩니다. Spring이 우리에게 감춰버리는 부분이기 때문에, 개발을 할때에는 자주 쓰이는 부분이 아니지만 디버그나 문제가 발생했을 때, 어떤 영역에서의 문제인지 확인할 필요가 있을 때 사용되는 지식입니다. 


Maven을 이용한 Hello World Web App

maven을 이용해서 Simple web application을 작성하는 법을 간단히 알아보도록 하겠습니다. 이 프로젝트는 전반적인 프로젝트들의 뼈대가 될 것입니다. 

Maven Project를 선택해줍니다.



maven-archetype-webapp을 선택해줍니다.


groupId와 artifact Id를 넣어주고, Project를 생성합니다.





지금 상태는 기본적으로 JRE1.5를 기반으로 한 Project가 구성이 되어있고, web application으로 eclipse에서 인식도 못하는 상태입니다. 프로젝트를 좀 손을 봐줘야지 됩니다.

pom.xml을 수정해서 JRE1.7기반으로 변경합니다.

       <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>
        </configuration>
      </plugin>

Project에서 우클릭 > Property에 들어가서 Project Facets를 선택합니다.


Convert to faceted from... 을 클릭합니다. 

Dynamic Web Module과 JavaScript를 선택합니다.


하단에 나오는 Further configuration available 을 클릭합니다.

ContextRoot를 artifactId와 동일하게 설정하고, Context directory를 src/main/webapp 으로 수정하고, Generate web.xml deployment descriptor를 선택합니다. 



프로젝트가 다음 모습이 되는지 확인합니다.




다시 Project 우클릭 > Property에 들어가서, Deployment Assembly를 선택합니다.


Add를 눌러, Java Build Path Entities를 추가, Maven Dependencies를 추가합니다.

 


 /src/test/java를 제거합니다.
다음과 같이 Web Depolyment Assembly가 되어 있는지를 확인합니다.


Server에 추가 후, Hello World!가 나오는지 확인합니다.



이번에는 Tomcat이 아닌 jetty를 이용해서 실행해보도록 하겠습니다.
pom.xml > build > plugins 에 다음 항목을 추가합니다.

            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.0.1.v20130408</version>                
            </plugin>

추가후 mvn jetty:run 을 이용해서 jetty를 실행시켜주세요. 그리고 jetty는 이 버젼에 유의해서 사용해야지 됩니다. jetty 9.0.0 버전은 심각한 오류를 가지고 있기 때문에 절대로 사용해서는 안됩니다. 
jetty를 사용하는 경우에는 webapplication name이 없이, http://localhost:8080 으로만 접근이 가능합니다. 

Summary

maven을 이용해서 web application을 작성하는 법을 한번 알아봤습니다. maven으로 작업하는 경우에는 maven way 라고 하는 절대적인 폴더 위치를 비롯해서 프로젝트의 구성을 그대로 맞춰줘야지만 쉽게 사용할 수 있습니다. 물론, 위치들을 변경하는 방법역시 존재하지만 이와 같은 공통적인 방법을 통해서 구성하는 것이 좋습니다. 이 폴더의 구조에 대해서는 반드시 외우거나 숙지해주시길 바랍니다.


Posted by Y2K
,

15. Spring과 iBatis

Java 2013. 9. 11. 14:18

* 사내 강의용으로 사용한 자료를 Blog에 공유합니다. Spring을 이용한 Web 개발에 대한 전반적인 내용에 대해서 다루고 있습니다.



Spring에서 myBatis를 사용하기 위해서는 Hibernate는 Spring이 Hibernate에 대한 SessionFactory, DataSource를 제공하고 있는 것에 비해, 오히려 mybatis 측에서 Spring에 대한 library를 제공하고 있습니다. 

pom.xml에 다음과 같은 내용을 추가해주시길 바랍니다. 

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.1.1</version>
</dependency>

pom.xml에 적용후, command창에서 mvn dependency:tree 를 한번 실행시켜보시면 다음과 같은 결과를 볼 수 있습니다. 




기본적으로 mybatis-spring은 spring 3.1RELEASE를 가지고 개발된 jar입니다. 따라서, mybatis-spring을 참조하는 즉시, spring 3.1Release가 바로 추가가 됩니다. 그런데, 저희 프로젝트는 기본적으로 Spring 3.2RELEASE를 기반으로 구성되어 있습니다. 이런 경우 어떻게 해야지 될까요?
다행히도, Spring은 하위 호환성을 100% 맞추고 있습니다. 따라서, mybatis-spring에서 사용하고 있는 Spring 3.1 module을 모두 제거하고, Spring 3.2 RELEASE를 모두 사용하도록 maven의 dependency를 조절해줘야지 됩니다. maven에서 dependency 된 jar안에 포함된 다른 module을 제거하는 것은 다음과 같은 포멧으로 pom.xml을 수정해줘야지 됩니다.

이러한 경우에 pom.xml을 수정하는 방법은 2가지가 있습니다. 

1. 각 dependency에서 각 library들을 exclude 시켜주는 방법
2. dependencyManagement에서 각 library들의 version을 관리해주는 방법

개인적으로는 2번째의 방법이 좀 더 나은 것 같습니다. dependencyManagement를 이용해서 mybatis-spring의 dependency 충돌을 해결한 pom.xml의 일부입니다. 

   <repositories>
        <repository>
            <id>mybatis-snapshot</id>
            <name>MyBatis Snapshot Repository</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
        </repository>
    </repositories>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>3.2.1.RELEASE</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>3.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>3.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
                <version>3.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>3.2.1.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>3.2.1.RELEASE</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.22</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>2.2.2</version>
        </dependency>
    </dependencies>

이제 dependency를 다시한번 확인해보도록 하겠습니다. 

mybatis-spring에서 의존하고 있던 jar들은 모두 제거가 된 것을 알 수 있습니다. 그리고 Spring에 필요한 jar들이 모두 추가 됨을 볼 수 있습니다.

마지막으로 applicationContext.xml을 추가하도록 하겠습니다. myBatis는 기본적으로 spring에서 제공하는 DataSource를 그대로 이용할 수 있습니다. DataSource를 그대로 이용한다는 것은 TransactionManager를 이용한 @Transactional 역시 사용이 가능하다는 뜻입니다. 지금까지 해왔던 내용대로 설정을 할 수 있습니다. 다만 차이가 있다면 Spring을 사용하지 않고 myBatis를 이용할 때는 SqlSession을 SqlSessionFactory에서 직접 얻어오는 방식을 채택했습니다. 그렇지만, Spring을 이용하는 경우, mybatis-spring에서 제공하는 SqlSessionFactoryBean과 SqlSessionFactoryTemplage을 이용해서 작업을 한다는 차이 이외에는 테스트 코드 자체도 큰 차이가 없습니다.

다음은 applicationContext.xml 입니다. 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
  <context:property-placeholder location="classpath:spring.property" />
  <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
  </bean>
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:mybatis.xml" />
  </bean>
  <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg ref="sqlSessionFactory" />
  </bean>
  <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>
  <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

dataSource와 transactionManager는 JdbcTemplate을 사용할때와 완전히 동일합니다. 그리고 Hibernate에서 사용하던 LocalSessionFactoryBean 대신에 SqlSessionFactoryBean과 SqlSessionTemplate를 사용하는 차이만을 가지고 있습니다. 

이제 구성된 설정을 이용해서 각 Dao interface들을 얻어보도록 하겠습니다. 

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@Transactional
public class BookDaoTest {
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;
    private BookDao bookDao;
    
    @Before
    public void setUp() {
        assertThat(sqlSessionTemplate, is(not(nullValue())));
        bookDao = sqlSessionTemplate.getMapper(BookDao.class);
        bookDao.deleteAll();
        assertThat(bookDao.countAll(), is(0));
    }
    
    @Test
    public void add() {
        List<Book> books = getBooks();
        for(Book book : books) {
            bookDao.add(book);
        }
    }
    
    @Test
    public void getAll() {
        List<Book> books = getBooks();
        for(Book book : books) {
            bookDao.add(book);
        }
        List<Book> allBooks = bookDao.getAll();
        for(Book book : allBooks) {
            System.out.println(book);
        }
    }

기존에는 각각의 session에서 commit를 실행시켜줬지만, 이제는 @Transactional을 이용한 세련된 Transaction을 하고 있는 것을 볼 수 있습니다. 사용법 역시 큰 차이가 있지 않으며 Spring과 interface를 조합한 사용 계층에서의 큰 변경 없이 코드의 기술을 완전히 변경을 시킬 수 있는 것을 알 수 있습니다. 
코딩하는 연습을 하는 시간을 갖겠습니다. 나머지 코드들을 모두 작성해주세요. 


매우 간편한 설정 및 사용의 편의성. mybatis가 현업에서 가장 많이 사용되고 있는 이유가 보이시나요? 이렇게 쉬울수는 없다. 라는 느낌이 맞을 정도입니다. 


Summary

지금까지 구성된 bookstore를 myBatis-spring을 이용해서 구성해주세요. 



Posted by Y2K
,

* 사내 강의용으로 사용한 자료를 Blog에 공유합니다. Spring을 이용한 Web 개발에 대한 전반적인 내용에 대해서 다루고 있습니다.



지금까지 우리는 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는 구성이 불가능합니다. 

구성할 프로젝트는 다음과 같습니다. 

ProjectGroup IdArtifactIdcompile orderDescription
Parent Projectcom.xyzlast.bookstorebookstore-Root Project
CommonBLcom.xyzlast.bookstorecommon-bl1Business Logic 구성 Project (Entity, Dao, Service 구성)
WebResourcecom.xyzlast.bookstoreweb-resources2Web Resource를 위치 - image, css, javascript에 대한 common library
PublicWebcom.xyzlast.bookstorepublic-web3사용자들이 방문할 web page
AdminWebcom.xyzlast.bookstoreadmin-web3관리자가 방문할 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를 진행해보도록 하겠습니다. 

mvn clean 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를 이용해서 구성된다고 생각하시면 좀 더 고민이 줄 수 있을 것 같습니다. 





Posted by Y2K
,

4. 개발환경의 구성

Java 2013. 9. 6. 13:52

* 사내 강의용으로 사용한 자료를 Blog에 공유합니다. Spring을 이용한 Web 개발에 대한 전반적인 내용에 대해서 다루고 있습니다.



이번 장에서는 개발 환경을 구성해보도록 하겠습니다.

Edit

java sdk 설치

java sdk를 다운받아 설치합니다. windows에서는 oracle home page 및 google 검색을 통해 손쉽게 설치가 가능합니다. 하지만, linux에서는 조금 다른 문제가 있는데요. linux는 기본적으로 open jdk가 설치되어 있습니다. oracle에서 제공한 것이 아닌, jdk 표준 규약에 따른 open source로 구성된 jdk가 이미 설치가 되어 있습니다. 그런데 이 open jdk가 성능이 oracle 것에 비하여 떨어집니다.. 다음과 같은 절차를 통해서 open jdk를 삭제하고 oracle java를 설치하는 것이 좋습니다.

sudo apt-get purge openjdk-\* icedtea-\* icedtea6-\*
deb http://ppa.launchpad.net/webupd8team/java
apt-get install oracle-jdk7-installer
apt-get install oracle-java7-installer 
sudo ln -s /usr/lib/jni/libswt-* -t ~/.swt/lib/linux/x86/
sudo ln -s /usr/lib/jni/libswt-* -t ~/.swt/lib/linux/x86_64/

그리고, JAVA_HOME을 등록합니다. linux의 경우에는

sudo vi /etc/profile 

을 실행해서, JAVA_HOME을 처리해야지 됩니다.
 JAVA_HOME="/usr/lib/jvm/java-7-sun" 

을 설정해주는 것으로 java 설치가 모두 마쳐집니다. 
개발의 편의성을 위해서 path를 설정해주는것이 좋습니다. 
command 창에서 java -version을 실행시켜 java version을 확인합니다.


maven의 설치

먼저 maven에 대한 간단한 소개부터 하도록 하겠습니다.

Maven이란 Apache Software Foundation에서 개발되고 있는 소프트웨어 프로젝트 관리툴입니다.
Maven은 Project Object Model (POM) 이라는 것에 기초를 두어 프로젝트의 빌드, 테스트, 도큐멘테이션, 성과물의 배치등, 프로젝트의 라이프사이클 전체를 관리합니다. 프로젝트의 빌드툴인 Ant와 달리, Maven은 프로젝트 관리툴로서 프로젝트에 관련한 여러가지 정보를 POM에 집약해, POM의 정보에 기초를 두어 프로젝트 전체를 관리합니다.

Maven의 주 기능은 다음과 같습니다.

  1. 프로젝트 라이브러리 관리
  2. 프로젝트 정보의 전달 (사이트의 작성, 배치나 유니트테스트의 레포트등)
  3. 프로젝트 작성부터 컴파일, 테스트, 패키지, 배치등의 프로젝트 프로젝트 라이프사이클에 포함되는 각 태스크의 지원이 가능합니다..

또, Maven은 소프트웨어 프로젝트의 관리 툴임과 동시에 이해툴로서 있습니다.
Maven의 제1목적은 개발자가 단기간에 프로젝트를 이해할 수 있도록 도움을 주는 것입니다. 그를 위해 Maven 에서는

  1. 빌드프로세스를 간단히 한다
  2. 통일한 빌드시스템을 제공한다.
  3. 양질의 프로젝트 정보를 제공한다.
  4. 개발의 가이드 라인을 지원한다.
  5. 신기술에 대해서는 투과적인 이행을 고려하여 넣는다.

과 같은 일을 하고 있습니다. 이런것들에 의해 Maven을 이용한 프로젝트는 어떠한 것이라도 빌드방법이 동일하다거나 디렉토리 구성이 거의 같아서 전체를 파악하기 쉽다등의 장점이 있습니다.
Maven의 구성은 작은 코어와 대량의 플러그인으로 되어 있습니다. 그리고 플러그인이나 라이브러는 필요에 따라서 자동적으로 다운로드가 행해집니다. 이 구조에 의해서 Maven이나 플러그인이 버전업할 때 신기술에 대해 투과적 이행이 가능합니다.
Maven은 당초 Jakarta Turbine의 프로젝트를 위해 작성되었습니다. 복수의 서브프로젝트로 구성된 Jakarta Turbine의 빌드 프로세스를 단순화 하기위해 작성되어졌던 것이 개별의 프로젝트로 독립한 것입니다.


그럼 maven의 설치를 해보도록 하겠습니다. maven은 http://maven.apache.com 에서 배포가 되고 있으며, 최신 버젼인 3.0.4를 다운받아 원하는 위치에 압축을 풀면 기본 설치는 완료됩니다. 사용을 편하게 하기 위해서, MAVEN_HOME을 다음과 같이 등록을 합니다.





또한 maven을 자주 사용하기 때문에 MAVEN_HOME\bin 을 path에 등록하면 maven 설치는 완료됩니다. 
명령어 창에 다음 명령어를 실행시켜, maven의 설치가 완료됨을 확인하도록 합니다.





maven은 추가 library를 관리하기 위해서 local repository를 이용하게 되는데, local repository는 기본적으로 사용자 directory에 .m 폴더를 만들어서 사용하게 됩니다. 기본 설정이 windows에서는 사용자 폴더 안에 위치하게 되어 관리가 힘들게 됩니다. windows 환경에서는 변경이 필요합니다. 
MAVEN_HOME\conf\settings.xml 파일을 에서 repository 항목을 자신이 편한 위치로 변경하면 됩니다.

이제 기본적인 maven 설정은 모두 완료되었습니다.


eclipse & eclipse plug in의 설치

eclipse 의 설치는 매우 간단하게 처리가 가능합니다. 그냥 다운 받아서 workspace를 지정후, 실행하면 됩니다. 
기본적으로 모든 project는 spring과 maven을 이용해서 구성이 되기 때문에, maven과 spring plug in은 설치하는 것이 도움이 됩니다. 
maven과 spring plug in을 설치하도록 합니다. 
help > Eclipse marketplace 에 들어가서 spring으로 검색을 합니다.






STS를 찾아 설치를 완료합니다.

maven 역시 같이 검색을 해서 다음 plug-in을 설치합니다.



maven plugin은 기본적으로 maven 3.0.4를 포함하고 있습니다. 먼저 설치한 maven의 설정을 따라가기 위해서 maven의 설정을 수정해줄 필요가 있습니다. 
windows > preferences 에 들어가서 maven 항목을 확인합니다. installation 에서 설치된 maven 위치로 설정하면 eclipse의 설정은 모두 마쳐집니다.





mysql 설치

mysql은 open source database로, 정부 표준 프레임워크에서 인정된 DB입니다. 개발용 DB로 사용할 수 있을정도로 가볍고, 빠른 속도를 자랑합니다.
그리고, 이번 강의는 모두 mysql 기준으로 행해지기 때문에, mysql을 설치해주시길 바랍니다.



유용한 eclipse plug in

개인적으로 유용하다고 생각되는 eclipse plug in들입니다. 입맛대로 골라서 사용해주시면 됩니다.

  1. Easy Shell : 필수 입니다. 이게 없으면 maven을 사용하기가 매우 힘듭니다.
  2. Color and theme : 색상 변경을 쉽게 해주는 plug in입니다.
  3. dbBear : db client ui입니다.
  4. amaterasUML
  5. moreUnit

Hello World의 실행

먼저, eclipse 에서 새로운 프로젝트를 하나 생성합니다. 
기존의 eclipse에서 새로운 프로젝트를 만드는 법을 사용하지 않고, maven을 이용한 application으로 작성합니다.





maven-archtype-quickstart를 선택하고, project를 작성합니다. 작성된 project의 파일구조는 다음과 같습니다. (resource folder는 존재하지 않을수 있습니다.)





각 Folder가 의미하는 것은 다음과 같습니다. 이와 같은 Folder 구조에 매우 익숙해질 필요가 있습니다. 이는 maven을 이용한 Project의 기본 Folder 구조입니다.

srcsource code가 위치합니다.
src/main개발 code가 위치합니다.
src/test테스트 code가 위치합니다.
src/main/javajava code가 위치합니다. ClassLoader가 접근하는 root위치입니다.
src/main/resourcejava code이외의 파일들을 관리할 때 사용됩니다.
src/test/javaUnit Test code가 위치합니다.
src/test/resourceUnit Test code에서 사용되는 파일들을 관리할 때 사용됩니다.
targetcompile된 파일들이 위치하고, test의 결과가 문서화되는 폴더입니다.
target/classessrc/main에 있는 파일들이 compile된 class 파일들이 위치합니다. 그리고, resource안에 있는 파일들이 copy됩니다.
target/test-classessrc/test에 있는 파일들이 compile된 class파일들이 위치합니다.
target/generated-sourcesAspectJ에 의해서 새롭게 생성된 main code들이 위치합니다.
target/generated-test-sourcesAspectJ에 의해서 새롭게 생성된 test code들이 위치합니다.
target/surefiretest에 대한 xml문서 등을 만드는데 사용되는 surefire jar가 임시로 위치합니다.
target/surefire-reportstest에 대한 결과를 txt파일과 xml파일로 제공합니다.

이 폴더 구조는 maven의 명령어를 실행시킬 때마다 동적으로 생성 또는 삭제가 되지만 위의 구조는 기본구조이기 때문에 변하지 않습니다. 위 구조를 반드시 숙지하시길 바랍니다.

Easy Shell을 이용해서, Console 창을 하나 실행합니다.

mvn compile 

을 실행 시키면, hello world project가 compile이 되는 것을 볼 수 있습니다.





pom.xml 파일을 한번 열어보도록 하겠습니다. maven은 POM에 기초하여 프로젝트의 빌드, 테스트, 도큐멘테이션, 성과물의 배치등, 프로젝트의 라이프사이클 전체를 관리를 한다고 했습니다. 그럼 maven에서 과연 어떤 정보들을 관리하고 있는지 한번 알아보도록 하겠습니다.

mvn site

를 실행시켜보시길 바랍니다.

무언가 maven에서 열심히 작업을 하고 있습니다. 그리고 Easy Shell을 이용해서 target/site 안의 index.html 파일을 브라우져로 열어보시길 바랍니다. 
index.html의 좌측을 보시면 pom.xml에 담길수 있는 모든 정보들이 보이는 것을 알 수 있습니다.

pom.xml에 담길수 있는 정보들은 다음과 같습니다.

DocumentDescription
About이 Project에 대한 간략한 서술을 적습니다.
Project Team팀 맴버에 대한 정보를 담습니다. email과 같은 연락 수단역시 이곳에 담겨집니다.
Dependency Information만약에 이 project를 다른 maven project에서 연결해서 사용할 때, pom.xml에 설정할 정볼르 담습니다.
Project Plugins이 Project를 compile 할때, 사용된 maven plug in에 대한 정보를 담습니다.
Continuous Integration이 Project가 관리되는 CI의 URL을 적습니다.
Issue Tracking이 Project가 관리되는 Issue Tracker의 주소를 적습니다.
Source Repository이 Project가 관리되는 svn의 정보를 적습니다.
Project License이 Project의 license를 기록합니다.
Plugin Management이 project가 Build될 때, 사용된 maven plug in에 대한 버젼 정보등 상세 정보를 기록 합니다.
Distribution Management이 Project의 배포 서버를 적습니다.
Project SummaryProject의 버젼 정보 및 GroupId, ArticleId 등을 기록합니다.
Mailing ListsProject에 대한 Mailing list를 적습니다.
DependenciesProject가 참조하는 library들에 대한 정보가 기록됩니다.

엄청나게 많은 정보가 pom.xml에 기록됨을 알 수 있습니다. 어찌보면 project의 상세 명세서와 동일하다고 할 수 있습니다. 여기서 가장 유용하게 쓰이는 것은 Dependencies에 대한 정보입니다.

http://mvnrepository.com/ 에 방문해보시길 바랍니다. 이 사이트는 maven을 통해서 배포가 되는 라이브러리들이 위치한 사이트입니다. 우리가 maven에 특정 library를 등록하고 저장을 하면, maven은 자동으로 파일을 다운받아서 우리가 만든 프로젝트에 include 시킵니다.

지금 프로젝트에서는 junit 3.8.1이 사용되고 있지만, 이를 junit 4.11로 변경해보도록 하겠습니다. pom.xml에서 junit 3.8.1 부분을 찾아, version을 4.11로 바꿔주시고, pom.xml 파일을 저장해주세요. 저장을 하기 전에는 junit 3.8.1이 maven dependency에 들어있었지만, 저장 후, 바로 junit 4.11로 바뀌는 것을 알 수 있습니다.



maven을 이용하기 전에 어떤 jar를 다운받아서 project에 포함시키는 여러 작업들이 이제는 아무런 필요가 없습니다. 이건 모두 maven이 대신 해주게 되니까요. 그리고, maven에서 repository path를 설정해줬던 path에 한번 가서 파일을 봐보시길 바랍니다. 그곳에 파일들이 모두 위치하고 있는 것을 알 수 있습니다. 이것이 maven을 이용한 dependency 관리입니다.






자, 이젠 maven을 이용한 project 관리를 한번 봐보시도록 하겠습니다. 지금 보면 project의 java version이 1.5로 되어 있는 것을 알 수 있습니다. 이것을 pom.xml 파일을 변경하는 것으로 1.7로 변경하도록 합시다. pom.xml 파일에 다음 내용을 기록합니다.

그리고 project의 우클릭후, maven > update project를 선택해줍시다. 그럼, project가 JDK 1.5에서 1.7로 변경되어 있는 것을 알 수 있습니다.

간단한 코드를 짜보도록 하겠습니다. 
실제 개발 코드는 모두 src/main에 위치해야지 됩니다. 안에 HelloWorld 객체를 만들고, 두개의 method를 추가해줍니다.

 1public class HelloWorld {
 2    public String sayHello(String name) {
 3        return "Hello " + name;
 4    }
 5    public String sayHi(String name) {
 7        return "Hi " + name;
 8    }
 9}

그리고 테스트 코드를 작성합니다. 테스트 코드에 대해서는 다음 시간에 깊게 들어갈 예정이니 지금은 그냥 만들어주시기만 하면 됩니다. 테스트 코드는 모두 src/test에 위치해야지 됩니다. 그리고, 반드시 객체의 이름은 Test로 끝나야지 됩니다. 규칙을 만들어주기 편하게 하기 위해서 more unit의 기능을 이용하도록 합시다.

1public class HelloWorldTest {
2    @Test3    public void test() {
4        System.out.println("test running");
5    }
6}

그리고 console창에서 다음 명령어를 실행해보세요.

mvn test

maven이 test를 행하는 것을 알 수 있습니다. maven은 기본적으로 compile, test, package, install 이라는 phase를 갖습니다. 이 phase는 서로간에 종속적입니다.
compile > test > package > install 이라는 과정을 반드시 거치게 되지요. package를 할 때는 반드시 compile과 test를 거친 이후에 package phase가 실행이 되는 구조입니다. 따라서, test code를 잘 다듬지 못하면 배포 자체를 못하게 될 때도 있습니다.



Summary

maven을 이용한 test project를 만들어봤습니다. maven의 folder구조는 잘 숙지를 하고 계셔야지 됩니다. maven의 많은 plug in들은 이 folder구조가 유지되는 것을 전제로 움직입니다.


Posted by Y2K
,

maven에서 제공하는 maven-archetype-webapp 의 경우, 최신 eclipse인 JUNO와 tomcat7에서 동작하지 않는 문제가 있다. 

기본적으로, java 버젼을 1.4로, jst.web 버젼을 2.4로 잡아버리기 때문에 발생하는 문제인데, 이를 해결하기 위해서는 m2eclipse와 같은 eclipse plug-in을 이용하는 방법이 주로 추천되고 있다. 


maven을 오래 사용한 것은 아니지만, 일단 eclipse plugin을 사용하는 것보다는 console을 이용하는 것이 좀 더 나아보인다. test, deploy 등의 작업을 좀 더 편하게 할 수 있고, m2eclipse를 사용하더라도 손으로 하나하나 다시 설정을 잡아줘야지 되는 불편함이 존재하기 때문에, pom 자체를 이용해서 이를 수정해주는 것이 더 나아보이기 때문이다. 


단계는 다음과 같다. (자바세상의 빌드를 이끄는 메이븐 을 보면서 공부를 해서... 예시는 책에 나온 wikibook을 사용한다.)


1. web app의 skeleton code를 다음 maven command를 이용해서 작성한다.


mvn archetype:generate -DgroupId=com.xyzlast -DartifactId=wikibook -DarchetypeArtifactId=maven-archetype-webapp


작성된 project의 pom 파일은 다음과 같다.


<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.xyzlast</groupId>

  <artifactId>wikibook</artifactId>

  <packaging>war</packaging>

  <version>1.0-SNAPSHOT</version>

  <name>wikibook Maven Webapp</name>

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

  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>3.8.1</version>

      <scope>test</scope>

    </dependency>

  </dependencies>

  <build>

    <finalName>wikibook</finalName>

  </build>

</project>


2. 먼저, 사용하는 java compiler의 버젼은 1.7을 사용하고 있기 때문에 compiler의 버젼을 넣어준다.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>

이 상태에서 mvn eclipse:eclipse를 이용해서 eclipse용 설정을 생성하게 되면, 다음과 같은 문제가 발생하게 된다.
* M2_REPO/junit/junit/4.11/junit-4.11.jar will not be exported or published. Runtime ClassNotFoundExceptions may result. 
* Project Facets가 정상적으로 맞지 않는 문제(최신 자바 1.7만 설정이 된 경우)

3. 사용되는 jar 파일들을 WEB-INF/libs 에 위치하게 하기 위해서 다음과 같은 설정을 추가한다. 또한, javadoc과 source를 보기 위한 설정 역시 추가한다.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<projectNameTemplate>[artifactId]</projectNameTemplate>
<wtpapplicationxml>true</wtpapplicationxml>
<wtpversion>2.0</wtpversion>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<useProjectReferences>true</useProjectReferences>
<workspace>..</workspace>
</configuration>
</plugin>


4. 이 상태에서 mvn eclipse:eclipse를 실행하면, .setting/org.eclipse.wst.common.project.facet.core.xml 파일의 내용은 다음과 같다.

<faceted-project>
  <fixed facet="jst.java"/>
  <fixed facet="jst.web"/>
  <installed facet="jst.web" version="2.4"/>
  <installed facet="jst.java" version="1.4"/>
</faceted-project>

여기서 eclipse로 import하기 전에 text 파일을 고쳐주면 문제가 해결되긴 하지만, 자동화를 위해서 다음과 같은 파일을 작성한다.

java_1.7_web_3.0.xml
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
     <fixed facet="jst.web"/>
     <fixed facet="java"/>
     <fixed facet="wst.jsdt.web"/>
     <installed facet="java" version="1.7"/>
     <installed facet="jst.web" version="3.0"/>
     <installed facet="jst.jsf" version="2.0"/>
     <installed facet="wst.jsdt.web" version="1.0"/>
</faceted-project>

또한, 생성된 skeleton project의 web.xml은 web app version 2.5의 것을 사용하고 있기 때문에 이것을 3.0으로 넣어줄 기본 web.xml 파일을 작성한다.

web_3.0_default.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                             http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
         id="WebApp_ID" version="3.0">

<display-name>wikibook</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

작성된 2개의 파일을 MAVEN_HOME의 app-conf Directory에 카피한다.

5. maven-eclipse-plugin 정보에 다음과 같은 추가 설정을 한다.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<projectNameTemplate>[artifactId]</projectNameTemplate>
<wtpapplicationxml>true</wtpapplicationxml>
<wtpversion>2.0</wtpversion>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<useProjectReferences>true</useProjectReferences>
<workspace>..</workspace>
<additionalConfig>
<file>
<name>.settings/org.eclipse.wst.common.project.facet.core.xml</name>
<location>file:///${MAVEN_HOME}/app-conf/java_1.7_web_3.0.xml</location>
</file>
<file>
<name>src/main/webapp/WEB-INF/web.xml</name>
<location>file:///${MAVEN_HOME}/app-conf/web_3.0_default.xml</location>
</file>
</additionalConfig>
</configuration>
</plugin>

추가 설정의 내용은 단순하다. MAVEN_HOME에 위치한 facet 파일과 web.xml을 이용해서 eclipse plugin에 의해 생성되는 파일을 대치해버리는 것이다. 

최종적인 pom.xml파일 내용은 다음과 같다. (JUnit 4를 사용하기 위해서, JUnit버젼 역시 3.8.1에서 4.11로 변경하였다.)

<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.xyzlast</groupId>
<artifactId>wikibook</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>wikibook Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>servlet-api</artifactId>
<version>6.0.35</version>
</dependency>
</dependencies>
<build>
<finalName>wikibook</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<projectNameTemplate>[artifactId]</projectNameTemplate>
<wtpapplicationxml>true</wtpapplicationxml>
<wtpversion>2.0</wtpversion>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
<useProjectReferences>true</useProjectReferences>
<workspace>..</workspace>
<additionalConfig>
<file>
<name>.settings/org.eclipse.wst.common.project.facet.core.xml</name>
<location>file:///${MAVEN_HOME}/app-conf/java_1.7_web_3.0.xml</location>
</file>
<file>
<name>src/main/webapp/WEB-INF/web.xml</name>
<location>file:///${MAVEN_HOME}/app-conf/web_3.0_default.xml</location>
</file>
</additionalConfig>
</configuration>
</plugin>
</plugins>
</build>
</project>


6. 이제 console에서 mvn eclipse:eclipse를 실행한다. 
실행후, eclipse에서 Import를 이용해서 project를 load 한다. 결과는 다음과 같다.



test에 사용되는 junit부분 warning이고, 이 것은 무시 가능하다. delete로 지워버려도 된다.


이제 Tomcat을 구성하고, Tomcat에서 project를 추가하면 다음과 같은 페이지를 보는 것이 가능하다. 



Posted by Y2K
,