Spring 의 가장 기본적인 특징 중 하나는 POJO이다. 옛날에 Java로 웹 어플리케이션을 만들기 위해서는 Servlet 클래스를 상속받아 구현하는 방식으로 직접 작성했으나 Spring을 이용하면 POJO만으로 웹 어플리케이션 작성이 가능하다

Servlet에 대한 작업은 Spring Framework가 알아서 처리해주고 개발자는 비즈니스 로직의 구현에 집중하게끔 한 것이다


Spring Servlet클래스들은 모두 추상화 라이브러리 형태로 포함되어 있다. 거기에 IoC AOP를 지원하는 컨테이너 프레임워크 라는 기능을 붙임으로써 강력한 프레임워크가 되었다


Spring Container는 객체의 생성과 관리를 담당하며 필요할 때 객체를 생성(Lazy Loading)하고 객체간의 의존관계를 관리한다. 이를 확장한 ApplicationContext는 트랜잭션 관리나 메시지 기반의 다국어 처리 등 다양한 기능을 제공한다. 스프링 컨테이너는 Bean 저장소에 해당하는 XML 설정을 참조하여 Bean의 생명주기를 관리한다.





 위의 그림은 Spring Framework의 구동 원리를 나타낸다.


(1)   웹 어플리케이션이 실행되면 Tomcat(WAS)에 의해 web.xml 이 로딩된다.


(2)   Web.xml이 등록되어 있는 ContextLoaderListener가 생성된다. 이는 ServletContextListener 인터페이스를 구현하고 있으며 ApplicationContext를 생성한다.


(3)   생성된 ContextLoaderListener root-context.xml을 로딩한다.


(4)   Root-context.xml 에 등록된 Spring Container가 구동된다. 이 때 개발자가 작성한 비즈니스 로직에 대한 부분과 DAO, VO 객체들이 생성된다.


(5)   클라이언트로부터 Web Application 요청이 들어온다.


(6)   첫 요청이 들어오면 DispatcherServlet(Servlet)이 생성된다. DispatcherServlet FrontController의 역할을 수행하며 전송받은 요청 메시지를 분석하여 알맞은 PageController에게 전달하고 응답을 어떻게 할지 결정한다. 이 때, servlet-content.xml 이 로딩되며, Controller 등이 매핑된다.


(7)   실질적인 작업은 PageController에서 일어나므로 이 클래스들을 HandlerMapping / ViewResolver 클래스라 한다. 이 작업은 ThreadPool 을 통해 할당된 유저 Thread 에서 처리된다.


(8)   요청은 매핑된 각 Controller로 전달되고 Request ModelAndView 형태의 Object 형식으로 DispatcherServlet 으로 전달한다.


(9)   DispatcherServlet 은 응답 결과값을 각 Model 오브젝트와 View page 를 통해 출력한다. 작업을 처리한 유저 Thread 를 다시 Thread Pool 에 반환한다.


(10) 다음 요청부터는 이전에 생성한 DAO, VO, Impl 클래스들과 협업한다.





Maven 은 Apache 재단에서 제작한 프로젝트로 Java 기반의 프로젝트 세팅에 있어서 매우 손쉽게 프로젝트 관리를 지원해주는 오픈소스 프로젝트이다. 


Maven 을 사용함으로써 얻을 수 있는 장점은 다음과 같다.


1. Library 세팅 및 관리의 용이성


2. 간소화된 빌드와 배포


3. 라이프사이클 각각에 대한 테스트 환경


4. 프로젝트 프로필 관리의 용이함


5. 프로젝트 세팅 통일성 유지



Maven 은 독자적인 LifeCycle 을 갖고 있으며, 프로젝트를 이 LifeCycle 에 따라 빌드하고 배포까지 진행할 수 있다. 

이는 Java 프로젝트에 있어서 동일한 구조의 통일성을 줄 수 있으며, 개발자는 좀 더 개발 자체에만 집중할 수 있는 환경이 된다.


Maven 은 다음 링크에서 설치할 수 있다.

https://maven.apache.org/download.cgi


Maven 은 POM(Project Object Model) 에 대한 정보를 담은 pom.xml 이라는 설정파일을 필요로하며, 이 설정파일을 토대로 프로젝트에 대한 정보를 수집하고 해석한다.


Pom.xml 은 다음과 같은 형태로 구성된다.



<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Dummy</groupId>
<artifactId>Test</artifactId>
<version>1.0-SNAPSHOT</version>
    <dependencies>
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
    </dependencies>
</project>


설정의 항목들은 다음과 같다.


<project> : pom 파일의 root Element 로, pom 파일임을 validation 해준다.

<modelVersion> : POM 파일이 사용되는 버전을 나타낸다.

<groupId> : 프로젝트의 소속을 식별하는 ID 값이다.

<artifactId> : 프로젝트 빌드 결과로 나올 JAR 파일에 대한 대표이름이다.

<version> : 프로젝트 버전에 대한 정보를 기술한다. 개발용은 주로 SNAPSHOT 이라는 명칭을 붙여 버전별로 관리한다.

<packaging> : 프로젝트를 패키징할 방식을 지정한다. 주로 JAR나 톰캣에서 사용하는 WAR 형태로 패키징한다.

<name> : 프로젝트의 이름을 명시한다.

<url> : 프로젝트에 대한 정보를 참고할 수 있는 Reference 사이트가 기재된다.

<description> : 프로젝트에 대한 간략한 설명이 포함된다.


<dependencies> : 하위에 <dependency> 항목들을 포함하며 외부 라이브러리에 대한 의존성을 관리한다. https://mvnrepository.com/ 에서 Maven 에서 관리할 수 있는 Dependency 들을 참조할 수 있다.

<repositories> : 프로젝트에 대한 각종 dependency 들이 참조할 수 있는 원격 Repository 를 설정한다.

<profile> : 개발환경에 대한 프로필들을 관리한다.


프로젝트에 알맞게 Maven 설정을 하고나면, 해당 프로젝트를 Maven 의 라이프사이클 위에서 동작시킬 수 있다. 

다음은 주로 사용하는 Maven 커맨드 들의 목록이다.



- Maven 의 주요 커맨드 목록

 Maven 을 실행시키는 커맨드에는 몇가지 종류가 있다. IDE 등을 통해 코드를 작성하고 커맨드로 배포할 수 있다.


(1) mvn compile – pom.xml 이 있는 경로에서 프로젝트를 빌드하는 커맨드이다. Pom.xml 의 옵션에 따라 컴파일러의 버전도 선택이 가능하다.


(2) mvn test : test 클래스가 위치한junit의 단위 클래스를 통해 테스트하게 된다.


(3) mvn package : pom.xml 파일 내에 packaging 의 설정을 해놓은 경우, mvn package 커맨드로 패키징을 할 수 있다

 이 때, compile > test-compile > test > package 순으로 goal 이 실행된 다음 jar/war 파일이 target 디렉토리 내 에 생성된다 artifactId-version.packaging 의 명명규칙으로 배포되며 war 배포를 위해서는 maven-war-plugin 이 필요하다.


(4) mvn install : 압축한 jar 파일을 local repository에 등록하는goal로 일반적으로 package 이후 수반된다.


(5) mvn deploy : jar/war 파일을 remote repository 에 등록한다.



주로 프로젝트 환경 구축 시, Maven 커맨드를 IDE 의 빌드환경에 연동시켜서 한꺼번에 구동시키는 경우가 많다.

하지만, mvn 커맨드를 쉘에 입력해서 독자적으로 빌드도 가능하니 알아두도록 하자.




Spring framework 는 전세계적으로 손꼽힐정도로 우수한 Java Framework 이다.

개발 생산성을 위해 지원하는 강력한 기능들에 비해 경량의 프레임워크이고 많은 복잡하거나 귀찮은 부분들(특히 Servlet 처리와 같은 부분들)을 굉장히 효과적으로 프레임워크 단에서 처리해주어 개발자들에게 Business Logic 에만 신경쓸 수 있도록 지원한다. 


이러한 장점들 덕분에 스프링을 이용해서 만든 프로젝트들은 특유의 형식에 맞게 읽기 쉬운 코드로 되어 있으며 각 모듈들이 역할별로 잘 나뉘어 서비스 프로젝트에 있어서 최적의 구조를 갖는다.


다음은 Spring Framework 의 특징들에 대한 간략한 정리이다.


 - 경량(Light-weighted) : 특히 크기와 부하 측면에서 독립된 몇 개의 jar 파일로 구성되어있기 때문에 설치가 용이하며 POJO를 사용한다. EJB와 달리 Spring framework 자체의 부하는 무시해도 좋을 수준이다.


- IoC 패턴 : 객체 사이의 의존관계를 코드로 구현하지 않고 Framework에 의해 주입받는다.(Dependency Injection)


- AOP(Aspect Of Control) : 핵심 로직 개발 시 Transaction지원이나 Logging, Security 등 시스템 적 관심사에 신경쓸 필요가 없다.


- Transaction 관리 : Java Object 들에 대한 트랜잭션을 지원하지만 결코 J2EE 와 같은 환경에 얽매이지 않는다.


- Container : Application 객체의 Life cycle과 객체들 간 의존관계를 컨테이너 형태로 관리한다. Servlet Container와 Spring container의 차이점은 특정 WAS. 벤더에 종속적이지 않으면서 자유로운 확장이 가능하다는 것이다.


- Framework : 간단한 컴포넌트 만으로도 Application 구성이 가능하다. xml 설정 파일 상의 선언적인 구성도 가능하다.


- Integration : Container 구조 덕분에 다른 프레임워크들과 결합이 쉽다. 특히 IBATIS, Hibernate 등과의 결합은 공식과도 같다.


위와 같은 철학을 중심으로 유지하면서 최근의 Spring 은 새로운 개발 Trend 를 따라가고 있다.

다음과 같은 새로운 Feature 들이 버전별로 추가되었다. 아직 5는 제대로 써본적이 없지만, 좀 더 안정화되면 추가 정리해야할 것으로 생각된다.



Spring 3.0


Spring3.0 부터 Java5가 지원된다. 기존에 유지하던 하위호환성에 Generic 이나 가변인자(varargs) 등과 같은 개선사항이 추가된다.


(1) 전체 프레임워크를 하나의 spring.jar 파일로 제공하던 부분을 여러개의 jar 파일로 나누어 제공한다. 


(2) SPEL(Spring Expression Language)가 도입되었다.


(3) Rest API 에 대한 지원이 추가되었다.


(4) OXM(Object Xml Mapping) 기능이 추가되어 설정을 Xml 형태로 할 수 있게 지원한다.


(5) Java annotation 을 이용해서 DI 의 지원이 가능하다.



Spring 4.0


Spring 3.0 이 Java5+ 버전들에 대해 지원을 한다면 Spring 4.0 버전은 Java 8 의 특징들을 적용할 수 있게 지원한다.


(1) Starter Pack 이 생겨서 초보 개발자들에게 큰 진입장벽인 POM 설정을 도와준다.


(2) 기존에 사용하지 않지만 호환성을 위해 남겨져있던 Deprecated Package 들이 제거되었으며 Hibernate 3.6 이상, EhCache 2.1 이상, Groovy 1.8 이상, Joda-Time 2.0 이상 등 새로운 Dependency 들에 대해 지원한다.


(3) Java6, Java7, Java8 의 고유 기능들에 대해 지원한다. 람다식, Optional, Callback Interface 등의 기능을 Spring framework 레벨에서 사용할 수 있다.


(4) Java EE 6, 7 에 대해 고려되어 있다. JPA 2.0 과 Servlet 3.0 에 대한 지원이 포함되어 있다는 뜻이다.


(5) Groovy 를 이용한 Bean 설정이 가능하다. 자세한 사용법은 GroovyBeanDefinitionReader 문서를 참조하자.


(6) Core 컨테이너들의 기능 지원이 확대되어있다. 먼저 Repository 들이 좀 더 쉽게 Inject 될 수 있으며, 각종 Metadata Annotation 들을 이용한 Custom Annotation 작성이 가능하다. @Lazy 를 이용한 Lazy Injection 이나 @Order 을 통한 Ordered Interface, @Profile 을 통한 프로필 버전 관리가 쉬워졌다.


(7) Web 을 개발하기 위한 도구들이 생겼다. @RestController 같은 것들이 그것이다.


(8) Web Socket 이나 STOMP 등의 프로토콜을 같이 지원한다.


(9) 테스트 환경이 개선되었다. Framework 레벨에서 Mock 을 위한 ServletContext 를 별도로 지원한다.



Spring 5.0


Spring 5.0 은 JDK 8+, 9 등에 대해서 지원하며 Java8을 표준으로 사용한다. 


(1) 코어로직에 있어서 JDK 8의 특징들이 강화되었다.


(2) HTTP 메시지 코덱의 XML과 JSON 지원에 대한 구현이 Encoder 와 Decoder 의 사용을 통해 추상화 되었다.


(3) 웹에 대한 지원이 향상되었다. 특히 Protobuf 3.0 지원이 적용되었다.



개인적으로 Spring 의 꾸준한 발전은 기존의 탄탄한 철학 위에서 효율적으로 트렌드를 받아들이고 있는 것으로 생각된다. 아마도 앞으로도 꽤 오랜기간 장수하지 않을까..



 MyBatis 란 객체지향 언어인 Java 와 SQL Based 인 관계형 데이터베이스(RDBMS) 사이의 데이터를 다루는 방식의 괴리를 해결하기 위해 만들어진 Persistence Framework 의 일종이다.


 Java 에서 DB와의 Connection 을 위해 제공하는 JDBC 를 Wrapping 한 구조로 되어 있으며, 기존의 JDBC 에 비해 많은 장점들을 갖고 있다.


무엇보다 사용이 간단하고, 60% 정도의 생산성 향상이 있다고 한다.

또한 JDBC 사용시 매번 Query Statement 를 생성하는 구문을 작성해야 했던 것과 다르게 쿼리의 재사용과, 코드와의 분리가 좀 더 수월해졌기 때문에 유지 보수 측면에서도 이점을 갖는다.


 주로 mybatis-config.xml 과 같이 별도의 파일에 환경 설정을 분리시키며, 변수 형태로 DB 연결정보들을 관리한다.

간단한 설정 방법은 다음과 같다.



/* 설정 <pom.xml> */
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>



 Maven 을 사용한다면 위와 같이 먼저 pom.xml 에 MyBatis Dependency 를 기입해주어야 한다. 이후 다음과 같이 프로젝트별로 관리하는 개별 설정 파일에 내용을 기입해주면 된다.



/* 설정 <설정파일.xml> */

//Property 설정 분리
<properties resource="mybatis/config.properties">
<property name="username" value="jinsp"/>
<property name="password" value="epD@kef0"/>
</properties>


//커넥션 풀 사용
<dataSource type="POOLED">
//Database Driver
<property name="driver" value="${driver}"/>
//Database Url
<property name="url" value="${url}"/>
//Database UserName
<property name="username" value="${username}"/>
//Database Password
<property name="password" value="${password}"/>
</dataSource>



 이렇게 설정해준다면 MyBatis 의 SqlSessionFactory 를 통해 Connection 을 연결할 수 있다. MyBatis 의 사용을 위해서는 매퍼 파일(Mapper File) 이라 불리는 Xml 설정이 추가로 필요하다. 이는 다음과 같은 형태로 구성이 되어 있다.




<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="StudentRepository">
<select id="selectStudentList" resultType="student">
SELECT
`id` AS "studentId",
`name` AS "studentName"
FROM
student
</select>
</mapper>



 위의 Mapper 설정에 대한 설명을 간단히 하자면, 설정들이 StudentRepository 라는 @Repository 로 명시된 클래스에 매핑되며, 그 안에 학생들의 리스트를 조회하는 쿼리문인 selectStudentList 를 사용할 수 있게 설정되어있다는 뜻이다. selectStudentList 라는 Id 를 가진 SQL 문은 쿼리문의 결과(ResultType)를 Student 형태의 객체의 형태로 반환하며, 요소가 여러개일 경우 List 형태의 Collection 으로 반환한다.


위와 같이 설정을 하고, 위에 명시된 쿼리의 ID 를 SessionFactory 를 통해 불러와서 실행시켜주면 연동이 간단하게 끝난다.



 Maven 설정은 처음 배우기에 쉽지않고 진입장벽이 높지만, 어느정도 규모 있는 프로젝트를 하다보면 매우 유용하다. 최근에는 Gradle 이 떠오르고 있으나 기존의 많은 프로젝트들이 Maven 을 이용하고 있기 때문에 알아두는 것도 중요하다.


 큰 단위의 Java 프로젝트는 보통 복잡하며 여러 개의 모듈이 한 프로젝트를 구성하게 되는 경우도 많다.

여러 프로젝트 간의 설정 및 환경을 일치시키고 유지하는건 상당히 복잡한 일이 될 수 있는데, Maven 을 활용하면 이를 굉장히 편리하게 구성할 수 있다.

 예를들어 중복된 설정을 상위 프로젝트에서 Global 하게 관리함으로써 프로젝트의 구성을 단단하게 유지시켜 줄 수 있는 것이다.


 이를 위해 Maven은 POM 상속이라는 개념을 제공하여 설정의 중복을 줄이고 해당 모듈에 필요한 설정만을 갖출 수 있게 한다. 이 때 실제 프로젝트 자체는 완전히 개별적인 형태를 취하지만 단지 하나의 POM 파일로 묶어줄 뿐이다. 

아래의 예시를 참고해보자.



<!-- 부모 프로젝트(project) 에서의 설정(pom.xml) -->

    <groupId>com.demo.project</groupId>
    <artifactId>project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>project-module</module>
        <module>project_api</module>
    </modules>



 최상위 POM.xml 파일의 <packaging> 태그는 반드시 pom 으로 설정되어 있어야 하고, 하위 모듈들은 <modules> 태그 하의 <module> 로 묶여서 설정되어 있어야 한다. 


그리고, 이 설정 순으로 dependency 가 생기게 된다. 정확히는 메이븐의 빌드 순서가 된다. (만약 상위 모듈에 dependency 를 갖고있다면 하위 모듈이 먼저 빌드되어선 안된다.) 하위 프로젝트들은 다음과 같이 상위 프로젝트를 <parent> 태그를 통해 기술하고 있어야 한다.




<!-- 자식 프로젝트(project-module, project-api) 에서의 설정(module/pom.xml, api/pom.xml) -->

    <parent>
        <groupId>com.demo.project</groupId>
        <artifactId>project</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>



 하위 프로젝트들은 상위 프로젝트의 POM에서 기술된 설정들을 자유롭게 이용할 수 있고, 상위 프로젝트의 dependency 정보가 기본적으로 include 되어 진다. 이는 Effective POM 을 보면 확인해볼 수 있다.


 구성이 끝나면 최상위 프로젝트의 POM 을 빌드함으로써 전체 프로젝트를 빌드할 수 있다. 메이븐에서 다중 모듈 빌드는 각 하위 모듈들의 빌드 결과물이 의존관계에 있는 모듈에서 그대로 쓰이게 된다.




 Spring boot는 일반적으로 사용되는 Spring Project와 몇가지 차이점이 있다.


 일단 프로젝트의 목적 자체의 차이가 조금 있는데, Spring boot의 경우 웹 컨테이너(Tomcat)를 내장하고 있고 최소한의 설정으로 쉽게 Spring Application 을 만들기 위한 목적으로 설계된 프레임워크 내의 플랫폼이라 할 수 있다.

 그렇기 때문에 Spring boot로 Set up 할 경우 편리하게 Dependency 문제가 해결되고, 빠르게 웹 어플리케이션을 만들 수 있는 장점이 있다. 심지어 starter-pack 이라는 dependency 를 통해 아주 간단하게 웹 어플리케이션을 만들 수 있다.


 반면 Spring-boot 위에서 동작하기 때문에 확장성 등의 고려에 있어서 모든 부분을 직접 설정해주어야 하는 Spring Project 가 더 이점이 있다고 할 수 있다.

 아직까지는 비즈니스 영역에 있어서 Spring Project 가 사용되고 있지만 점차적으로 Spring-boot 가 사용될 것으로 보인다.


 Spring boot 는 또한 최근에 발생한 기술이기 때문에 여러가지 버전 호환 문제가 아직 존재한다.

Java 버전으로는6부터 지원을 하지만 Spring boot 버전에 따라서 특히 REST나 JPA의이용을위해 Spring boot 1.4 이상의 버전을 필요로 한다.


 이 때 Spring boot의 버전에 따라 내장 톰캣의 버전에 차이가 생기게 된다. 가령 Spring boot 1.2.4 이상의 버전에서는 내장 Tomcat8 이 사용되고 그 이하 버전에서는 Tomcat7 이 사용된다.


 그렇기 때문에 각 버전간 호환을 맞춰주는 수고로움이 들게 된다. 그렇지 않으면 Tomcat의 버전별 LifeCycle 에러를 맞보게 된다.

 Spring boot는 기본으로 설정된 Embed 톰캣 사용 설정을 하지 않게 명시하여 외장 톰캣을 사용할 수도 있다.



- 내용 계속 추가 예정인 포스팅입니다. - 

+ Recent posts