springmvc+mybatis

Language/JSP 2012. 11. 7. 11:10

이제 대충 스프링이 뭐하는 프레임워크인지 감을 잡았다면 개발에 필요한 라이브러리와 환경을 구축해보자. 혹시나 MyBatis와 커넥션풀에 대해 잘 모르는 사람이라도 일단 속는 셈치고 함께 설치해주는 것이 좋다. 이 두가지 라이브러리와 더불어 스프링 시큐리티가 포함되면 정말 금상첨화지만 일단 스프링 시큐리티까지 설치하면은 설명이 길어지므로 시큐리티는 차후에 사용 포스트를 작성하도록 하겠다.


먼저 개발환경 구축에 필요한 라이브러리 또는 프레임워크 목록은 위 URL에 버전과 함께 상세히 나열되어있다. 혹시나 이 라이브러리들의 의존 라이브러리들이 포함되지 않았을 수도 있으므로 안전하게 메이븐을 이용해 라이브러리를 설치하도록 하자. 메이븐이란 훌륭한 라이브러리 관리 기술이 있음에도 이를 귀찮다고 이용하지 않는다면 프로그래머의 자격이 없다.


메이븐을 아직 설치하지 않았다면 위의 URL을 통해 메이븐을 설치하길 바란다. 더욱이 상기의 개발환경을 기본으로 구축했다는 전제하에 쓰는 글이므로 진행 중에 오류나 이해가 가지 않는 부분이 생길 수도 있다.




먼저 MyBatis에 대해 잘 모르는 사람을 위해 이 라이브러리를 설명하고자 한다. 사실 꼭 MyBatis를 써야하는 이유는 없지만 분명한 사실은 MyBatis와 같은 라이브러리를 활용하여 데이터 퍼시스턴스(Data Persistence)계층을 효율적으로 관리해야 한다는 점은 이미 웹개발자들에 있어서 일반적인 상식이 됬기 때문이다.

위의 문장에서 데이터 퍼시스턴스는 간단히 DB에서 정보를 꺼내오는 역할을 담당하는 계층을 말한다. 현대의 비지니스 객체 모델은 프리젠테이션 계층, 비지니스 로직 계층, 퍼시스턴스 계층으로 나눌 수 있는데 프리젠테이션은 우리가 현재 보고 있는 페이지 또는 브라우져로 출력되는 페이지들을 말하며 비지니스 로직은 퍼시스턴스와 프리젠테이션 사이에서 조율하는 계층을 일컫는다.


실제로 웹 어플리케이션은 위와같은 구도로 돌아간다. 스프링을 사용한다면 사용자가 보낸 요청을 스프링 컨테이너가 가로챈 뒤에 처리하므로 위의 그림보다 조금 복잡하게 돌아가긴 하지만 원리는 동일하다. 그러므로 상기의 계층 구도는 웹 개발에 있어서 매우 일반적인 구성이라고 할 수 있겠다.

사실 우리가 반드시 위의 구도를 지켜가며 코드를 칠 필요는 없다. 필자도 스프링을 알기 전에는 필자 맘대로 계층을 분류하고 메서드를 만들어대고 패키지를 찍어댔었다. 그런 의미에서 당신도 위와 같이 복잡한 계층을 무시하고 마음대로 코드를 쳐댈 수도 있지만 굳이 많은 사람들이 위와같은 계층을 지키려 노력하며, 보이지 않는 약속을 하는 이유는 어디까지나 효율적인 분업이 가능하게 하기 위해서다.

뜬금없는 소리지만 로마 군대가 강력했던 이유는 효율적인 징병제와 어디를 가더라도 로마 군인이라면 이해할 수 있는 진지를 구축했다는 점인데 이런 시대를 가로지르는 진리는 어느 분야에서든 통하기 마련이다. 로마 군대를 비유로 계층별 분류의 가장 큰 이유를 꼽자면 과거 선배 웹프로그래머들의 많은 시행착오 끝에 나온 결과이며 이런 계층별 분류가 웹프로그래머들만의 강력한 진지라고 할 수 있기 때문이다.

그러므로 퍼시스턴스 계층을 분리하는 것을 당연스럽게 받아들이자. 실제로 MyBatis 개발진들이 발표한 결과로 퍼시스턴스 계층을 분리하면 약 30~40% 정도의 엄청난 양의 코드가 절약된다고 한다. 게다가 양만 줄어드는게 아니라 코드자체가 매우 직관적인 표현으로 변하여 가독성까지 높일 수 있다.


먼저 위의 그림과 같은 순서로 하나의 프로젝트를 만들어보자. 프로젝트를 만들었다면 초기에 pom.xml에 구성되있는 라이브러리들이 조금 낡았다는 생각이 들 것이다. 일단 pom.xml파일을 열어 현재 문서의 가장 상단에 있는 POM.XML의 설정을 위한 라이브러리 최신 버전에 있는 모든 라이브러리들을 설치하도록 하자. 라이브러리 교체는 직접 pom.xml을 수정해도 되고 이클립스의 플러그인 기능을 이용하여 수정해도 되는데 이 과정은 매우 쉬우므로 따로 설명하지는 않겠다.

라이브러리들을 최신버전으로 바꾸어 주었다면 먼저 MyBatis와 스프링을 연동시켜야 한다. MyBatis와 스프링이 연동되려면 2가지 XML 파일들이 필요한데 매퍼 설정파일과 매퍼 XML파일이 바로 그 것이다. 이름은 어떤 것으로 해도 상관없지만 현재과정을 따라가는 만큼 이 문서에서 제시된 파일명으로 통일하는 게 좋겠다.

먼저 두가지 XML파일 중에 매퍼 설정파일을 보도록 하자. MyBatis가 별도의 매퍼 설정파일을 필요로 하는 이유는 매퍼 설정을 통해 퍼시스턴스 계층(MySQL, Oracle 등)의 옵션을 세부적으로 조절할 수 있으며 DB의 테이블 관리를 위해 만들어진 자바빈 파일들을 MyBatis만의 타입으로 매핑시키고 SQL구문이 들어있는 매퍼 XML파일을 등록시킬 수 있기 때문이다. 아래 이미지처럼 프로젝트 패키지에 XML파일을 만들고 위의 DTD를 선언하도록 해보자.


XML파일 이름은 아무래도 mybatis의 설정파일이니 mybatis-config.xml 정도가 괜찮겠다. XML파일을 만들었다면 아래의 DTD를 선언하고 본격적으로 설정을 해주도록 하자.

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "HTTP://mybatis.org/dtd/mybatis-3-config.dtd">

설정에는 다양한 옵션이 존재하는데 옵션에 관한 부분만 해도 어마어마하므로 MyBatis 한글 레퍼런스 문서를 참조해가며 직접 구현해보는 것을 추천한다. 다행히 iBatis때부터 열성적인 한국 사용자들이 존재해서 그런지 MyBatis 프로젝트 페이지에 한글 번역 레퍼런스 문서가 당당히 존재하고 있다. 

잡담이지만 MyBatis는 다른 인기 프레임워크와 다르게 별도의 관련 서적이 없는데, 그 이유는 서적이 필요 없을 정도로 쉽고 간편하기 때문이라고 생각한다. 여하튼 필자의 설정방법은 그냥 예제 정도로만 인식하고 실제 개발에 착수할 때는 각각의 옵션이 어떤 역할을 하고 있는지 정확히 인식하고 사용하여야 한다.

mybatis-config.xml의 예제

MyBatis 한글 레퍼런스 문서와 상기 이미지를 참조해가며 <configuration> 요소를 완성시키도록 하자. 위의 <settings>요소만 채웠다해서 매퍼 설정파일이 완성됬다고 할 수는 없지만 중요한 것은 과정을 밟아가며 이해하는 것이므로 이 정도에서 다음 과정으로 넘어가도록 하자.

매퍼 설정파일의 <settings>요소를 작성하였다면 이젠 매퍼 XML파일을 만들 차례다. 매퍼 XML파일은 직접 데이터베이스에서 동작하는 SQL구문을 작성하는 공간인데 이 역시 MyBatis 한글 레퍼런스 문서에 자세한 설명이 있으니 꼭 한번 정독해보기를 권장한다.

개인적으로 매퍼 XML파일을 배치시키는 가장 좋은 방법은 매퍼 XML파일 하나로 모든 쿼리를 처리하는 것보다 테이블에 맞춰 잘게 자른 다음에 패키지 별로 분류 시키는 것이 유리하다. 만약 이런 패키지 분류에 대해 잘 모르겠다면 아래의 문서를 읽기를 권장한다. 패키지 분류는 매우 중요한 상식이므로 이런 분류법에 대해 잘 모른다면 문서를 읽는데 큰 어려움이 있을 것이다.

필자의 매퍼 XML파일 배치방법


현재까지의 과정을 잘 따라왔다면 상단의 이미지처럼 MyBatis 설정 파일들이 위치되었을 것이다. 상단의 이미지에서 users 패키지는 앞으로 우리가 users란 테이블을 만든 뒤 이 테이블을 이용해 테스트할 예정이므로 미리 선행으로 패키지를 분류해둔 것이다. users-sql.xml란 이름으로 매퍼 XML파일을 만들었다면 다음과 같은 DTD를 선언해 주도록 하자.

<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">

users-sql.xml의 예제

상단의 이미지는 필자가 작성한 매퍼 XML파일의 모습이다. <mapper>요소 안에 별다른 내용이 없는 이유는 아직 users 테이블도 만들지 않은 데다 마땅히 넣을 만한 SQL구문도 없으므로 향후 작성을 위해 가장 기본적인 형태만 유지한 것이다. 여기서 주의 할 점은 namespace 속성은 Java 코드에서 <mapper>요소를 구분하는데 쓰이는 중요 속성이므로 반드시 설정하도록 한다.(테이블 명과는 아무 관계가 없다. 다만 통일감을 위해 동일명으로 지었을 뿐이다.)


MyBatis의 두 설정파일은 위와 같은 의존관계를 갖고 있다. 매퍼설정파일은 하나 이상의 매퍼XML파일을 매핑할 수 있으며 스프링 컨텍스트 또한 하나 이상의 매퍼설정파일을 매핑할 수 있다. 이제 만들어 둔 users-sql.xml을 mybatis-config.xml에 매핑시켜보도록 하자. mybatis-config파일은 퍼시스턴스 계층의 세부옵션과 더불어 이처럼 세부적인 매퍼 XML파일들을 묶어주는 큰 역할을 담당하고 있다.

mybatis-config.xml파일에 user-sql.xml을 매핑시키는 예제

위의 예제처럼 설정했다면 이제 매퍼XML파일은 매퍼설정파일을 통해 스프링컨텍스트와 연동될 수 있게 되었다. 간단한 테스트를 위해 users테이블을 만들고 mybatis-config.xml파일을 스프링 컨텍스트와 연결시켜보자.

위의 예제와 같이 users란 테이블을 만들고 필드 또한 일치시키도록 한다. 그리고 스프링 컨텍스트 파일은 mybatis만 독자적으로 관리할 수 있게끔 mybatis-context.xml이란 새 컨텍스트 파일을 만들기로 하자. 모든 준비가 끝났다면 mybatis-context.xml에 커넥션풀을 활용한 dataSource 빈을 만들 차례다.

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/데이터베이스명" />
<property name="username" value="DB접속 아이디" />
<property name="password" value="DB접속 비밀번호" />
</bean>

위의 dataSource 빈은 apache에서 제공하는 커넥션풀을 이용하여 생성한 것이다. 커넥션풀이란 매번 접속 때마다 커넥션을 생성하는 게 아닌, 미리 일정량의 커넥션을 구현해 놓은 뒤 커넥션 요청이 올 때마다 이 커넥션을 제공하는 방식을 일컫는다. 커넥션풀은 단순히 좋아서 쓰는게 아니라 반드시 구현해야 하는 기술이다. 당신의 DB가 요청마다 커넥션을 생성하는데는 어느 정도 한계가 있으며 오라클 같이 DB를 만들어 파는 회사는 이런 커넥션 양에 값을 매기기도 한다.

물론 상업용 WAS(Web Application Server)같은 경우는 서버 단에서 DB 풀서비스를 제공해주기도 하지만 우리처럼 가난한 영세민이 사용하는 톰캣에서는 그런 기능을 기대할 수 없다. (그렇다고 톰캣을 폄하하는 것은 절대 아니다.) 우리는 커넥션풀 라이브러리를 적극 활용하여 현재 확보된 커넥션을 최대한 효율적으로 사용 함과 동시에 대량의 커넥션 요청에도 유연하게 대처할 수 있도록 반드시 커넥션풀을 이용해 dataSource를 구현해야만 한다.

여담이지만 오픈소스 커넥션풀에는 dbcp와 c3p0 두가지가 있다. 위의 예제에서는 dbcp를 이용하여 구현하였지만 둘 중에 어느 것을 활용한다 해도 상관은 없다. 어디까지나 선택은 독자의 몫이다.

위의 빈을 mybatis-context.xml에 입력한 다음 부족한 세부 설정을 맞추어서 자신의 DB와 연동시키도록 하자. 모든 설정을 끝마쳤다면 이제 당신은 커넥션 풀을 이용한 데이터베이스와 스프링 프로젝트의 연동에 성공한 셈이다. 이제 dataSource빈을 MyBatis에 주입시키기만 하면 끝이므로 다음과 같이 mybatis-context.xml파일에서 아래와 같은 빈을 만들어 보도록 하자.

<context:annotation-config />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:org/danzka/vodka/mybatis-config.xml" />
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory" />
</bean>


MyBatis를 처음 접한 사람이라면 위의 설정만으론 이해가 가지 않을 것이다. 자세한 설명을 위해 먼저 SqlSessionFactoryBean을보도록 하자. 이 빈은 mybatis의 SqlSessionFactory 객체를 스프링의 팩토리빈을 활용하여 생성시켜준다. 팩토리빈이란 다이나믹 프록시를 스프링에서 쉽게 구현할 수 있도록 한 것인데 자세한 것은 토비의 스프링 - 트랜잭션 부분을 보면서 심화학습하도록 하고 중요한 것은 이 빈이 SqlSessionFactory 빈을 만들어 준다는 것이다.

SqlSessionFactory 클래스는 데이터베이스 정보와 설정파일을 필요로 하는데 dataSource와 mybatis-config.xml파일을 각각 매핑시키면 된다. 여기서 주의할 점은 SqlSessionFactoryBean 클래스는 setConfigLocation란 메서드를 통해 해당 XML을 resource객체로 변환시키기 때문에 보통 경로설정 문제로 난처한 상황을 겪는 경우가 많다. 하지만 우리는 mybatis-config.xml파일을 클래스가 위치하는 폴더에 존재하기 때문에 'classpath:'를 통해 쉽게 설정파일을 가져올 수가 있게 되었다. 지금은 잘 느끼지 못하겠지만 이런 파일배치의 장점은 향후 JUnit을 이용한 테스트와 웹으로 직접 배포하는 테스트를 동시에 하려고 하는 과정에서 그 편리함을 깨닫게 될 것이다.

여기까지 완료되었다면 SqlSessionTemplate 클래스 생성자에 작성한 sqlSessionFactory를 주입시켜주면 되는데 <constructor-arg>라는 요소를 활용하여 해당 클래스의 생성자에 주입해주도록 하자. SqlSessionTemplate 클래스는 디테일한 설정을 위해 3가지 방법으로 생성자를 주입받을 수 있는데 위와 같이 단순히 sqlSessionFactory만 주입하면 기본설정을 따르게 된다는 사실을 기억해야 한다.

이렇게 mybatis-context.xml파일의 설정이 모두 끝났으므로 마지막으로 컨테이너가 인식할 수 있도록 web.xml에 만든 컨텍스트 파일을 등록시키기만 하면 된다. 상기의 이미지와 같이 입력하면 자동으로 컨테이너가 시작될 때 mybatis-context.xml 파일도 함께 읽어 들일 것이다.



이제 본격적으로 MyBatis의 기능을 이용해 보도록 하자. MyBatis를 이용하기 위해선 위에서 만든 SqlSessionFactory와 SqlSessionTemplate를 주입받아 직접적으로 MyBatis의 기능을 이용할 수 있는 클래스 파일을 만들어야 하는데 정말 감사하게도 mybatis는 스프링을 이용하는 유저를 위해 이런 역할을 담당하는 클래스를 만들어 두었다. 그 클래스는 바로 라이브러리 중 mybatis-spring-1.0.2.jar 파일에 들어있는 SqlSessionDaoSupport란 클래스인데 우리는 이 클래스를 상속받아 쓰거나 주입받아 쓰기만 하면 된다.

SqlSessionDaoSupport클래스의 주입부분

위의 소스 중에 설명도 없이 스리슬쩍 넘어간 부분이 있는데 바로 <context:annotation-config />란 설정이다. 이 설정을 해두면 코드에서 @Autowired를 활용하여 주입없이도 바로 xml 객체를 불러올 수 있게 된다. 아직 한번도 @Autowired를 사용한 기억이 없는데 왜 설정이 필요하냐면 바로 위의 이미지처럼 우리가 활용할 SqlSessionDaoSupport 클래스가 이 설정을 요구하기 때문이었다. 만약에 위의 설정이 없다면 우리는 직접 SqlSessionDaoSupport빈을 만들고 직접 주입시켜주어야만 한다. 대신 이 설정이 있다면 별도의 주입없이도 자연스럽게 필요한 객체를 불러들일 수 있게 된다.

1장의 내용은 여기까지로 하고 다음 장에서는 SqlSessionDaoSupport클래스를 활용하여 직접 users 테이블에서 데이터를 불러오고 테스트하는 방법을 다루도록 하겠다. 참고로 이 클래스를 이용하는 방법은 주입방법과 상속방법이 있는데 우리는 상속을 통한 방법으로 접근 하고자 한다. 더불어 스프링을 활용한 트랜잭션 설정까지 함께 다루도록 하겠다.


출처 - http://springmvc.egloos.com/492767

'Language > JSP' 카테고리의 다른 글

JSP pageEncoding속성, 케릭터셋(charset)  (0) 2013.02.13
mybatis[SqlSession]  (0) 2012.11.07
SiteMesh와 Freemarker  (0) 2012.11.02
Core of JSP  (0) 2012.11.02
Basic of JSP  (0) 2012.11.02
: