진짜 개발자
본문 바로가기

FrameWork/Spring MVC

SpringMVC - Spring Mvc, H2, JPA, MyBatis 연동 환경 구성하기

728x90
SpringMVC Test Project 만들기

1. 목표

이번 포스팅의 목표는 아래의 3가지 라이브러리를 연동, 이용할 수 있도록 Spring MVC를 설정하는 것입니다.

DB

H2, JPA, MyBatis

db를 사용하기 위해서 위의 3가지 라이브러리를 이용할 것입니다.

H2

경량 DB로 test환경에 적합합니다. SpringBoot이용시 손쉽게 웹콘솔에서 사용가능한 H2 DB 설정이 가능하지만, Spring MVC에서는 웹콘솔설정을 찾아보기 어려워 ServerMode로 실행하도록 설정할 것입니다.

JPA

JPA의 경우 개발자가 직접 CRUD를 작성하지 않아도 기본적인 CRUD를 제공합니다. 하지만 복잡한 검색 쿼리의 경우 JPA에서 작성하기 어려운 점이 있습니다.

MyBatis

복잡한 검색쿼리를 위해 MyBatis를 사용할 것 입니다. MyBatis의 경우 xml에 mapping될 쿼리를 따로 관리하므로써 조금더 수월한 query설정이 가능했었는데요, 저는 XML이 더 복잡하다고 느껴져 Java Config파일로 SQL을 맵핑해볼것입니다.

 

 

 

2. 프로젝트 생성, 설정 및 의존성설정

2.1 프로젝트 생성, 설정

maven Proejcet를 생성합니다.

 

아무런 설정을 선택하지 않고 다음으로 넘어갑니다.

 

groud id, artifact id를 적절히 입력후 프로젝트 생성을 완료합니다.

 

프로젝트 생성시 index.jsp 파일이 존재하는데, 내용에 오류가 있습니다. 우선 지웁니다. 또한 java source폴더가 존재하지 않으므로 생성해주겠습니다.

 

src/main/java라는 이름으로 source folder를 생성합니다. 이때, source folder로 생성하면 이미 존재하기 때문에 에러가 납니다. 현재 classpath에 등록이 되어있기 때문입니다. 따라서 source folder가 아닌 기본 folder로 생성을 해야 합니다.

 

 

2.2 의존성 설정

2.2.1 Servlet

spring mvc를 사용하기 위해서는 당연히 servlet 의존성을 추가해야합니다. spring MVC 는 servlet 기반의 웹프레임워크 이기 때문입니다.

 

 

2.2.2 Spring

spring mvc는 말그대로 spring mvc를 사용하기 위한 라이브러리설정입니다. IoC컨테이너와, DispatcherServlet을 이용하기 위해 필요합니다.

 

spring-jdbc의 경우 spring에서 db와 연결하기위한 api들이 담겨있는 라이브러리입니다. Spring JDBC를 사용하기 위해서는 DB Connection을 가져오는 DataSource를 먼저 Bean으로 등록해야 합니다. 다음의 링크가 참 잘설명된 글인것 같습니다.https://smallgiant.tistory.com/13

 

 

2.2.3 jackson

jackson은 json 라이브러리 입니다. SpringMVC의 @EnabelWebMvc 설정시, 해당 라이브러리가 클래스 패스에 존재하면 자동으로 HttpMessageConveter에 jacksonConverter를 등록해주기 때문에, @RequestBody, @ResponseBody어노테이션을 이용하여 json을 http body에 담아 클라이언트, 서버 간에 통신이 가능해집니다.

 

 

2.2.4 Lombok

lombok은 getter, setter, constructor, toString, hashCode, equals, Builder.. 등등을 어노테이션에 의해 생성할 수 있도록 해주는 라이브러리 입니다. 자세한 내용은 다음 링크를 참조해주세요. https://galid1.tistory.com/531

 

이클립스에서 lombok을 사용하기 위해서는 먼저 위의 라이브러리를 추가해야합니다.

 

https://projectlombok.org/download 로 이동해 lombok .jar를 다운 받습니다.

 

위 그림의 순서대로 설치를 진행하면 됩니다. 너무 빨리 끝나 이게 설치가 된거야? 싶으시면 설치가 된겁니다. eclipse가 켜져있다면 꼭 재시작 하셔야합니다.

 

 

2.2.5 H2

h2 db를 사용하기 위해 라이브러리 설정을 해야합니다.

 

그 후 h2 db를 서버모드로 사용하기 위해 h2 db를 다운받습니다. 197 라이브러리를 추가 했으므로 197을 다운 받습니다. 그 후 압축만 풀면 준비 끝입니다.

 

 

2.2.6 hibernate

자바진영의 orm 기술인 JPA의 구현 프레임워크 라이브러리입니다.

 

 

2.2.7 mybatis

mybatis는 mybatis를 이용해 db를 제어할 수 있도록 하기 위한 라이브러리입니다.

mybatis-spring은 spring과 mybatis를 연동할 수 있도록하는 라이브러리입니다.

 

그림출처 - https://meaownworld.tistory.com/28

 

pom.xml에 정의된 전체 의존성에대한 코드입니다.

 

 

3. SpringMVC 설정

3.1 DispatcherServlet 설정

DispatcherServlet을 등록하기 위해 web.xml로 이동합니다.

 

위와 같이 작성합니다. DispatcherSerlvet을 등록하며 /app/*경로를 매핑합니다. contextClass로는 AnnotationConfigWebApplicationContext를 가지도록하며 설정파일은 com.galid.study.WebConfig class를 지정하도록 하겠습니다.

 

Context의 설정파일을 생성하기 위해 앞서서 xml에 정의한 경로에 WebConfig 클래스를 생성합니다.

 

WebConfig에 위와 같이 작성합니다.

@Configuration은 설정파일임을 알려주며,

@EnableWebMvc의 경우 xml파일에 <mvc:annotation-driven/> 를 입력한것과 동일한 효과를 줍니다. 즉 어노테이션 기반의 SpringMVC 웹 제작에 도움이 되는 Bean들을 자동으로 등록해주는 설정입니다.

@ComponentScan(basePackageClasses = WebConfig.class)는 basePackageClasses에 적힌 class의 위치를 기반으로 모든 @Component(@Service, @Controller, @Repository)어노테이션을 달고 있는 class를 bean으로 등록하도록 합니다.

또한 WebMvcConfigurer를 구현하여 보다 쉬운 설정을 할 수 있도록 합니다.

 

 

3.2 Controller

Controller와, Service를 생성하여 mvc가 제대로 동작하는지, IoC Container가 제대로 주입이 되었는지 확인해보겠습니다.

 

controller 패키지, HelloController 클래스, service 패키지, HelloService 클래스를 각각 그림과 같이 생성합니다.

 

HelloController 클래스에는 위와 같이 작성합니다. 먼저 @GetMapping("/hello")를 통해 사용자가 /hello로 요청을 할때 매핑될 핸들러임을 알려주었습니다.

hello()메소드에서는 HelloService를 IoC Container로부터 가져와 service의 getName()을 콘솔에 찍도록 했습니다. 마지막으로 /views/hello.jsp 를 사용자에게 응답하도록 했습니다.

 

HelloService의 코드입니다.

 

서버를 실행하고 요청을 보냅니다.

 

 

3.3 ViewResolver

이번엔 ViewResolver입니다. View를 렌더링해주는 역할을 합니다. 이것을 통해서 Controller에서 return해줄 view 값을 간단히 할 수 있습니다.

 

WebConfig 클래스에 위의 메소드를 추가합니다.

 

controller의 return값이 간단해진것을 볼 수 있습니다.

 

 

3.4 RestController, Lombok 테스트

앞서서 @EnableWebMvc어노테이션을 사용한다면 의존성을 추가함에따라 HttpMessageConverter가 자동으로 등록된다고 말씀드렸습니다. jackson 의존성을 추가했으므로 body에 json을 실어서 요청, 응답이 가능한지 보도록 하겠습니다.

 

테스트를 위해 dto를 생성해야합니다. 우선 dto패키지를 만들고 TestDto 클래스를 생성합니다. 그후 name, age 필드를 추가합니다. 또한 앞서서 간단히 설명드린 Lombok을 사용해볼것입니다. @Getter, @Setter을 이용해 name, age에 대한 getter, setter 메소드가 자동생성되며, @ToString을 통해 toString()메소드가 자동생성됩니다.

 

HelloController 클래스에 위의 메소드를 추가합니다. testDto의 필드들에 매핑되는 json을 body에 실어서 /test 경로로 post요청을 하면 그것을 자동으로 TestDto객체로 매핑되며 toString()를 return 하도록 했습니다.

 

post요청 테스트를 위해 PostMan을 이용하도록 하겠습니다. PostMan은 http 요청테스트를 돕는 tool입니다. 자세한 내용은 검색을 통해 알아보시길 바랍니다.

성공입니다. jackson의존성을 통해 자동으로 httpMessageConverter가 등록이 되었고 그를통해 body에 담긴 json 데이터를 다룰 수 있게 되었습니다.

 

 

 

4. DB 설정 (hibernate, h2, mybatis)

4.1 hibernate와 H2 설정

hibernate와 h2 db를 연동해보겠습니다.

 

4.1.1 H2 db 서버 사용

hibernate를 설정하기 전에 h2 db를 서버모드로 실행하는 것을 살펴보겠습니다. 앞서 다운로드 받고 압축을 푼 경로로 이동한 뒤, bin디렉토리를 엽니다. 그 후 window의 경우는 h2.bat, 리눅스의 경우 h2.sh를 실행합니다.

 

다음과 같이 자동으로 콘솔창이 열립니다. Generic H2(Server)를 선택한뒤 나머지 설정은 그대로 둔 뒤 연결을 클릭합니다.

 

성공적으로 h2 db를 서버모드로 실행중입니다. 이제 hibernate 설정을 한 뒤 연동을 해보겠습니다.

 

4.1.2 Hibernate 설정

hibernate는 resources/META-INF/persistence.xml 경로의 파일을 자동으로 인식하여 persistence 파일로 사용합니다. 따라서 위처럼 폴더를 생성하고 persistence.xml 파일을 생성합니다.

 

그 후 위와같이 작성합니다. persistence-unit name은 EntityManagerFactory에서 사용할 persistence를 구분하기 위한 id값입니다. 그 후 properties 태그 안에 db연결에 필요한 속성들을 입력하면 됩니다.

driver

org.h2.Driver

url

앞서서 h2 콘솔에 접속하기 전에 나타난 url을 그대로 입력하면 됩니다.

user , password

마찬가지 입니다.

dialect

hibernate에서 제공하는 방언기능 입니다. mysql, oracle, postgresql 등등의 언어로 자동으로 변환하여 사용이 됩니다.

hbm2ddl.auto

ddl 즉 테이블을 정의하는 sql을 자동으로 실행 해줍니다.

 

hibernate 사용을 위해 필요한 bean들을 등록합니다. 3가지가 필요합니다.

EntityManager

JPA의 대부분의 기능을 제공하는 객체입니다. (CRUD)

EntityManagerFactory

EntityManager를 생성할 수 있는 객체입니다.

EntityTransaction

Transaction 관리를 위한 객체입니다. JPA를 이용해 데이터를 변경할때에는 항상 Transaction안에서 변경해주어야합니다. 그렇지 않으면, 예외를 발생시킵니다.

 

 

위의 설정정보를 WebConfig에 Import합니다.

 

 

hibernate 설정을 완료한 뒤의 프로젝트 구조입니다. 먼저 보여드리고 시작하겠습니다.

 

HelloController를 위와 같이 작성합니다. @AllArgsConstructor는 말씀드렸듯이, Lombok의 api로 객체에 존재하는 모든 필드값을 가지는 생성자를 생성합니다. 이 때 생성자에 부여된 매개변수들은 @Autowired가 자동으로 붙게 되므로 별도의 @Autowired 코드 없이도 자동으로 객체를 주입받을 수 있습니다.

 

StudentDto는 클라이언트측과 데이터를 주고 받기위한 클래스입니다. 앞으로 작성할 Hibernate에서 사용되는 Entity와 코드상으로 거의 비슷하지만 다른 역할을 하기 때문에 별도로 작성을 해주어야 합니다. 이따가 설명드리겠습니다.

Lombok을 이용해서, getter, setter, Builder패턴, 생성자를 구현했고, 별도로 hibernate를 통해 저장하기 위해 entity로 변경하는 메소드를 가지고 있습니다.

 

이번에는 Entity 클래스입니다. entity 클래스는 DB의 테이블과 매핑되는 클래스입니다. 즉, 이 클래스를 마치 테이블 처럼 사용할 수 있습니다.

@Entity

db의 table과 매핑될 entity 클래스임을 알립니다.

@Table

db에서 매핑될 테이블의 이름을 직접 지정합니다.

@Id

해당 필드가 table의 pk임을 나타냅니다.

@GeneratedValue

pk의 생성방식을 나타냅니다. default값으로 AUTO를 가지고있는데 이는 auto_increment와 같은 역할을 합니다.

 

hibernate를 통해 db에 접근하는 dao역할을 하는 클래스입니다. 간단히 데이터를 저장하는 코드를 추가했습니다.

 

Service 클래스입니다. Controller에서는 역할 분리를 위해 직접적으로 dao클래스에 의존하지 않습니다. 따라서 service에서 dao를 통해 데이터 접근 로직 및 추가 로직을 처리하고, Controller에서는 그 Service를 이용합니다.

 

서버를 실행시키고, PostMan을 이용해 POST방식으로 데이터를 전송합니다. 응답으로 객체가 온것을 보아 성공된것을 알 수 있습니다.

 

데이터가 들어가 있는것을 볼 수 있습니다.

 

 

4.2 Mybatis 설정(Java config)

mybatis를 이용해 DB의 connection을 얻기 위해서SqlSessionFactory가 필요합니다. mybatis-config.xml을 만들고 SqlSessionFactoryBuilder를 통해 설정하는 방법이 있지만 JavaConfig를 통해 진행하겠습니다.

 

mybatis과 spring 연동에 대한 기본 정보들은 다음 링크에서 얻으면 좋습니다. http://www.mybatis.org/spring/ko/index.html

 

우선 위 그림과 같이 패키지와 클래스를 생성합니다.

 

4.2.1 MyBatisConfig

상단의 어노테이션들부터 설명드리고 Bean들에 대해 설명드리겠습니다.

어노테이션


@Configuration

해당 클래스가 설정파일 클래스임을 나타냅니다.

@MapperScan

xml파일을 이용해 mapper클래스를 작성하는 것을 대신하여 java class로 mapper class를 만든것을 자동으로 scan하도록 하는 어노테이션입니다. 앞서 생성한 mapper패키지를 대상으로 지정합니다.

 

Bean


DataSource

우선, Mybatis의 TransactionManager에서 사용할 DataSource를 당연히 bean으로 등록해주어야 합니다. DataSource의 구현체로 DriverManagerDataSource를 사용했는데, 이 구현체는 pooling을 하지 않습니다. 따라서 새로운 connection을 그때그때 생성하기 때문에 성능이 좋지 못합니다. 우리는 테스트 환경이기 때문에 이것을 사용합니다. 성능 향상을 원하신다면 BasicDataSource 구현체를 사용하시길 바랍니다.

SqlSession

sqlSession에는 SQL 명령어를 실행하기 위한 모든 메소드를 가지고 있습니다. 따라서 직접 SqlSession을 이용해서도 SQL쿼리를 질의할 수도 있습니다.

 

SqlSessionFactoryBean

Mybatis에서는 JdbcTemplate대신에 Connection 객체를 통한 질의를 하기 위해 SqlSession을 사용합니다. 이 때 SqlSession을 생성하기 위해 SqlSessionFactory를 사용합니다. 또 이 SqlSessionFactory를 MyBatis에서는 SqlSessionFactoryBuilder를 통해 생성하는데요, Spring 연동모듈에서는 SqlSessionFactoryBean이 대신 사용됩니다. SqlSessionFactory는 DataSource를 기본적으로 필요로 합니다.

(Spring 연동모듈은 mybatis-spring 라이브러리입니다. 즉, mybatis와 spring을 간편히 연동할 수 있도록 제공되는 라이브러리 입니다.)

 

SqlSessionTemplate

sqlSessionTemplate은 내부적으로 SqlSession을 구현합니다. 즉, SqlSessionTemplate는 SqlSession을 대체하는 역할을 합니다. SqlSessionTemplate의 장점은 쓰레드에 안전하고 여러개의 Dao, mapper에서 공유가 가능하다는 것 입니다.

 

마지막으로 WebConfig클래스에 MyBatisConfig 클래스를 Import 합니다.

 

 

4.2.2 StudentMapper 인터페이스

mapper는 반드시 구현체 Class가 아닌 Interface로 작성을 해야합니다. 원래 Mapper를 사용하기 위해서는 해당 Mapper Interface를 Bean으로 등록해야합니다. 하지만 MyBatisConfig 클래스에서 @MapperScan어노테이션을 부여했으므로 자동으로 scan하여 bean으로 등록을 합니다.

 

앞서 생성한 MyBatisConfig 클래스에 지정한 scan 경로에 StudentMapper 인터페이스와 그 구현체 Class를 생성합니다.

 

interface에 위와같이 작성합니다. @Select 어노테이션은 Mapper xml에 작성할 내용을 대신하게 됩니다.

 

구현 클래스에서는 Mapper를 Spring으로부터 주입을 받아 그것을 다시 호출합니다. StudentMapper 에는 mybatis에서 설정정보를 토대로 구현객체를 생성한 것을 주입받게 됩니다.

 

StudentService 클래스에 이제 mybatis를 이용해 데이터를 조회하는 코드를 추가합니다.

 

Controller에 핸들러를 추가합니다.

 

 

 

5. 최종테스트


Postman을 이용해 a, b 데이터를 넣고 list를 호출합니다. 성공입니다 !

 

최종 프로젝트 구조입니다.