IDE는 이클립스만 사용해보다가 최근에 Mac OS를 사용하면서 Intellij로 갈아타게 되었습니다. 물론 무엇을 쓰든 상관없었지만, 트렌드에 쓰잘대 없이 민감한 제가… 큰 마음먹고 한번 사용해보았습니다. 아직은 익숙하지가 않지만 간단하게 Intellij에서 스프링 mvc를 Mybatis 모듈과 연동하여 웹 어플리케이션을 구현해보는 시간을 리뷰해 보았습니다.

먼저, 꽤 저렴하지 않는 금전으로 Intellij Ultimate 1년 구독신청 하였기 때문에 해당 IDE로 실행을 하겠습니다.

Intellij를 사용하여 Spring-Mybatis 연동

스크린샷 2019-10-05 오전 12 41 42

미리 만들어놓은 프로젝트의 구조는 다음과 같습니다. 생각보다 복잡해서… 프로젝트 생성과정은 생략하였습니다. 빌드 도구로는 역시… 이클립스에서 사용해왔던 maven을 이용하여 pom.xml 파일에서 의존성 라이브러리들을 관리합니다.

스크린샷 2019-10-05 오전 12 41 51

위의 프로젝트 구조에서 database.properties 파일과 classes, views디렉토리를 제외하고는 Intellij에서 maven과 스프링 mvc로 프로젝트를 생성하여 보여주는 기본구조입니다.

스프링-Mybatis 모듈 연동을 구현하기 전에 간단하게 프로젝트 구조에 대해서 리뷰해보겠습니다.
웹 어플리케이션이 톰캣에서 동작할때 가장 먼저 web.xml파일을 참조하는데 설정내용은 이클립스와 크게 다르지 않습니다.

스프링 설정파일

web.xml 파일

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

dispatcher-servlet.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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- 아래 annotation-driven 태그는 HandlerMapping, HandlerAdapter를 Bean으로 등록하여 요청 url를 controller와 매칭시켜준다.-->
    <mvc:annotation-driven/>

    <mvc:resources mapping="/resources/**" location="/resources/"/>

  <!-- 특정 패키지안의 클래스들을 스캔하고, annotation을 확인 후 bean 인스턴스를 생성한다.-->
    <context:component-scan base-package="com.jun"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

기존의 이클립스와의 차이점은 context파일 명이 servlet-context.xml, root-context.xml 파일이 아니고 dispatcher-servlet.xml, applicationContext.xml 입니다.

dispatcher-servlet.xml파일에서 view를 검색하는 역할을 하는 ViewResolver를 빈으로 등록하고 js,css같은 정적파일들은 WAS가 처리하지 않고, WEB 서버에게 위임합니다. 스프링 mvc를 사용한다고 하면, 대표적으로 DispatcherServlet를 등록하고, 모든 요청을 받게 설정을 하는데 /resources/** 로 요청이 오면 /resources/로 매핑시켜주어서 바로 처리할 수 있도록 설정하였습니다.

이제 간단하게 요청 url에 특정 id 값을 보내면 Mybatis에서 sqlSession 객체를 이용하여 해당하는 값을 DB 테이블에서 검색하여 view 화면에서 보여주는 예제를 구현해보겠습니다.

이러한 작업을 위해서… 역시 설정들을 간단한?? 설정을 해주면 됩니다.
그전에 pom.xml에서 mybatis, mybatis-spring, mysql-connector-java 의존성 라이브러리들을 pom.xml에 작성하여 해당 dependency들을 받아와야 됩니다.

mybatis는 sql 명령어를 관리해주는 편리한 라이브러리이고, 유지보수성이나 효율성이 기존에 jdbc에서 사용해왔던 방식보다 훨씬 뛰어납니다.

<!-- MyBatis, MyBatis-Spring, Spring-JDBC -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

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

            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.1.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

mybatis와 mybatis를 연동하는 스프링 그리고 스프링과 jdbc를 연결하는 라이브러리입니다.

mybatis는 필연적으로 데이터베이스를 이용하는 sql문을 설정하는 라이브러리이기에 데이터베이스 개발환경에 꼭 필요하고 스프링 jdbc와 그를 연결하는 mybatis-spring 라이브러리가 필수적입니다.

아래의 그림이 설명이 잘돼어있는거 같아서 참고하였습니다.

스크린샷 2019-10-05 오전 12 42 05

이제 applicationContext.xml파일에서 데이터베이스 관련 설정을 해보겠습니다.

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns\="[http://www.springframework.org/schema/beans](http://www.springframework.org/schema/beans)"  
xmlns:xsi\="[http://www.w3.org/2001/XMLSchema-instance](http://www.w3.org/2001/XMLSchema-instance)"  
xmlns:context\="[http://www.springframework.org/schema/context](http://www.springframework.org/schema/context)"  
xsi:schemaLocation\="[http://www.springframework.org/schema/beans](http://www.springframework.org/schema/beans)  
[http://www.springframework.org/schema/beans/spring-beans.xsd](http://www.springframework.org/schema/beans/spring-beans.xsd)  
[http://www.springframework.org/schema/context](http://www.springframework.org/schema/context)  
[http://www.springframework.org/schema/context/spring-context.xsd](http://www.springframework.org/schema/context/spring-context.xsd)"\>  

<context:property-placeholder location\="/WEB-INF/database.properties"/>  
<!--<context:component-scan base-package="com.jun"/>-->  

<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
<property name="url" value="${jdbc.url}"/>  
<property name="username" value="${jdbc.username}"/>  
<property name="password" value="${jdbc.password}"/>  
</bean>-->  

<bean id\="dataSource" class\="org.springframework.jdbc.datasource.DriverManagerDataSource"\>  
<property name\="driverClassName" value\="com.mysql.jdbc.Driver"/>  
<property name\="url" value\="${jdbc.url}"/>  
<property name\="username" value\="${jdbc.username}"/>  
<property name\="password" value\="${jdbc.password}"/>  
</bean\>  
<!-- Mysql <-> Mybatis를 연결해주는 객체 -->  
<bean id\="sqlSessionFactory" class\="org.mybatis.spring.SqlSessionFactoryBean"\>  
<property name\="dataSource" ref\="dataSource"/>  
<property name\="configLocation" value\="classpath:/mybatis-config.xml"/>  
<property name\="mapperLocations" value\="classpath:/mappers/\*.xml"/>  
</bean\>  

<bean id\="sqlSession" class\="org.mybatis.spring.SqlSessionTemplate"\>  
<constructor-arg ref\="sqlSessionFactory"\></constructor-arg\>  
</bean\>  
</beans\>

DB url, username, password 같은 정보는 보안상 따로 파일을 만들어서 변수를 사용하여 입력하는게 좋은 방법입니다.
<context:property-placeholder location="/WEB-INF/database.properties"/> 태그로 database.properties 파일을 해당 xml파일로 import를 하여 dataSource 빈에 property에 변수를 값으로 넣어줍니다.

sqlSessionFactory 빈에는 mybatis 설정파일과 sql문을 관리하는 mapper xml파일의 경로와 데이터베이스 연결정보들을 가지고 있는 dataSource 객체를 property 값으로 가지고 있습니다.

mybatis-config.xml, member-config.xml 파일은 src/main/resources 디렉토리 밑에 생성하여 만든 설정파일로써 해당경로를 클래스패스로 인식하기 때문에 값을 넣어줄때 classpath:를 써줘야 인식합니다. 안그러면 에러가 발생합니다.

sqlSessionFactory는 데이터베이스 연결과 sql문 실행에 대한 모든 것을 가진 가장 중요한 객체입니다.

여기까지 스프링 웹 어플리케이션에서 DB를 연결하기 위한 설정하는 방법입니다.
이제 자바코드를 이용하여 해당 웹 어플리케이션을 구현해보겠습니다.

  1. Controller
package com.jun.controller;

import com.jun.dto.MemberDto;
import com.jun.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {


    @Autowired
    private MemberService memberService;

    @RequestMapping("/home")
    public String home(){

        return "homepage";
    }

    @RequestMapping("/index")
    public String index(){

        return "index";
    }

    @RequestMapping("/loginForm")
    public String loginForm(){

        return "loginForm";
    }
    //해당 url/id 값으로 요청이 들어오면 loginResultView 메소드 실행
    @RequestMapping("/loginResultView/{id}")
    public String loginTestResult(@PathVariable String id, Model model){

        MemberDto dto = memberService.selectMember(id);

        model.addAttribute("member", dto);

        return "loginResultView";
    }
}
  1. DTO
package com.jun.dto;

public class MemberDto {

    private String id;
    private String name;


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  1. DAO
package com.jun.dao;

import com.jun.dto.MemberDto;
import com.jun.mapper.MemberMapper;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class MemberDao {

    @Autowired
    private SqlSession sqlSession;

    public MemberDto selectMember(final String id){

        MemberMapper mapper = sqlSession.getMapper(MemberMapper.class);

        MemberDto memberDto = mapper.selectMember(id);

        return  memberDto;
    }
}
  1. service
package com.jun.service;

import com.jun.dto.MemberDto;

public interface MemberService {
    public MemberDto selectMember(String id);
}
package com.jun.service;

import com.jun.dao.MemberDao;
import com.jun.dto.MemberDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MemberServiceImpl implements MemberService {

    @Autowired
    private MemberDao memberDao;

    public MemberDto selectMember(String id) {

        MemberDto memberDto = memberDao.selectMember(id);

        return memberDto;
    }
}

sql문에서 테이블에서 select로 단일조회하여 저장할 때도 사용하는 용도로 작성한 파일입니다.

  1. mapper
package com.jun.mapper;

import com.jun.dto.MemberDto;

public interface MemberMapper {
    MemberDto selectMember(String id);
}

sqlSession 객체에서 해당 interface를 구현하여 MemberMapper 객체를 이용하여
member-mapper.xml파일에 정의되어 있는 sql파일을 실행하는 책임을 가지고 있습니다.

  1. mapper-mapper.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="com.jun.mapper.MemberMapper">
    <select id="selectMember" parameterType="String" resultType="memberDto">
        SELECT name, id from TEST1 WHERE id =#{id}
    </select>
</mapper>

접근하고자 하는 테이블의 sql 명령어들을 정의한 xml 파일입니다.

  1. mapper-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <typeAliases>
        <typeAlias alias="memberDto" type="com.jun.dto.MemberDto"/>
    </typeAliases>
</configuration>

mybatis-config.xml 파일은 Mybatis에 별도의 설정들을 정의합니다.
member-mapper.xml에서 정의된 sql문의 리턴타입을 dto로 사용할 경우에 태그를 사용하면 풀 패키지명 없이 간단하게 memberDto를 리턴타입으로 사용할 수 있습니다.

mysql을 실행하여 임의로 해당 테이블을 dto(Member)와 같은 타입으로 셍상히였습니다.
간단한 spring-mybatis 예제이기 때문에 따로 password는 암호화하여 넣지는 않았습니다.

스크린샷 2019-10-05 오전 12 42 19

위의 코드들을 작성했으면 이제 database에서 해당 값을 가져오는지 실행결과를 보겠습니다.

스크린샷 2019-10-05 오전 12 51 27

대충 작성하였지만 스프링 부트를 배우기 전에 다시한번 복습한다는 생각으로 mybatis-spring 연동예제를 구현해보았습니다. 처음에는 eclipse와 환경도 다르고 library 가져오는 방법도 약간 달라서 어려움이 있었지만… 역시 코딩은 삽질이 답인거 같네요. 제 부족한 점을 다시한번 짚어볼 수 있는 유익한 시간이였습니다.

+ Recent posts