예제를 작성하기에 앞서서 스프링 MVC를 이용하는 프로젝트의 구성을 이해하는 일은 전체 데이터의 흐름을 보기 위해서이다. 브라우저에서 전송한 데이터를 스프링 MVC의 어떤 단계를 거쳐서 실행되는지를 이해한다면 문제가 발생했을 때 빠른 대처와 대안을 찾을 수 있기 때문이다.
일반적으로 웹 프로젝트는 3-tier 방식으로 구성한다.
- Presentation Tier(화면계층) : 화면에 보여주는 기술을 사용하는 영역이다. 책의 예제에서는 Servlet/JSP나 스프링 MVC가 담당하는 영역이 된다. Presentation Tier는 프로젝트의 성격에 맞춰 앱으로 제작하거나, CS(Client-Server)로 구성되는 경우도 있다. 이전 파트에서 학습한 스프링 MVC나 JSP를 이용한 화면 구성이 이에 속한다.
- Business Tier : 순수한 비즈니스 로직을 담고 있는 영역이다. 이 영역이 중요한 이유는 고객이 원하는 요구 사항을 반영하는 계층이기 때문이다. 이 영역의 설계는 고객의 요구 사항과 정확히 일치해야 한다. 이 영역은 주로 'xxxService'와 같은 이름으로 구성하고, 메서드의 이름 역시 고객들이 사용하는 용어를 그대로 사용하는 것이 좋다.
- Persistence Tier(영속 계층 혹은 데이터 계층) : 데이터를 어떤 방식으로 보관하고, 사용하는가에 대한 설계가 들어가는 계층이다. 일반적인 경우에는 데이터베이스를 많이 이용하지만, 경우에 따라서 네트워크 호출이나 원격 호출 등의 기술이 접목될 수 있다. 이 영역은 MyBatis 와 mybatis-spring 을 이용해서 구성했던 파트를 이용한다.
계층의 대한 설명을 스프링 MVC와 맞춰서 설명해 보면 다음과 같은 구조가 된다.
스프링 MVC 영역은 Presentation Tier를 구성하게 되는데, 각 영역은 사실 별도의 설정을 가지는 단위로 볼 수 있다. 이전 예제에서는 root-context.xml, servlet-context.xml 등의 설정 파일이 해당 영역의 설정을 담당하였다. 스프링 Core 영역은 흔히 POJO의 영역이다. 스프링의 의존성 주입을 이용해서 객체 간의 연관구조를 완성해서 사용한다. MyBatis의 영역은 현실적으로는 mybatis-spring을 이용해서 구성하는 영역이다. SQL에 대한 처리를 담당하는 구조이다.
* MyBatis와 mybatis-spring ???
스프링 프로젝트 팀은 스프링 3에서 마이바티스를 지원하고자 하였지만, 스프링 3이 완료되는 시점까지 완성하지 못하였다. 이후 마이바티스 커뮤니티 서브 프로젝트에서 마이바티스와 스프링 통합을 별도로 진행하였다. 이를 통해 스프링3과 마이바티스를 연동할 때, 스프링3에 마이바티스를 원활하게 통합시킬 수 있도록 지원하는 마이바티스-스프링 라이브러리를 제공하게 되었다. 마이바티스-스프링 라이브러리를 사용하면, 스프링은 필요한 마이바티스 객체를 쉽게 생성, 주입할 수 있는 편리한 방법을 제공받게 된다. 또한 스프링 트랜잭션을 통해 처리할 수 있으며 마이바티스에서 발생하는 예외를 스프링 DataAccessException 객체로 변환받아 처리할 수 있다.
1. 각 영역의 Naming Convention (명명 규칙)
프로젝트를 위와 같이 3-tier로 구성하는 가장 일반적인 이유는 '유지보수'의 필요성 때문이다. 각 영역은 독립적으로 설계되어 나중에 특정한 기술이 변하더라도 필요한 부분을 전자제품의 부품처럼 쉽게 교환할 수 있게 하자는 방식이다. 따라서 각 영역은 설계 당시부터 영역을 구분하고, 해당 연결 부위는 인터페이스를 이용해서 설계하는 것이 일반적인 구성방식이다. 프로젝트를 진행할 때에는 다음과 같은 네이밍 규칙을 가지고 작성한다.
- xxxController : 스프링 MVC에서 동작하는 Controller 클래스를 설계할 때 사용
- xxxService, xxxServiceImpl : 비즈니스 영역을 담당하는 인터페이스는 xxxService라는 방식을 사용하고, 인터페이스를 구현한 클래스는 xxxServiceImpl라는 이름을 사용
- xxxDAO, xxxRepository : DAO(Data-Access-Object)나 Repository 라는 이름으로 영역을 따로 구성하는 것이 보편적임. 다만 이 책의 예제는 별도의 DAO를 구성하는 대신에 MyBatis의 Mapper 인터페이스를 활용
- VO, DTO : VO와 DTO는 일반적으로 유사한 의미로 사용하는 용어로, 데이터를 담고 있는 객체를 의미한다는 공통점이 있음. 다만, VO의 경우는 주로 Read Only의 목적이 강하고, 데이터 자체도 Immutable하게 설계하는 것이 정석임. DTO는 주로 데이터 수집의 용도가 좀 더 강함. 예를 들어, 웹 화면에서 로그인하는 정보가 DTO로 처리하는 방식을 사용함. 이 책에서는 테이블과 관련된 데이터는 VO라는 이름을 사용하겠다.
1-1. 패키지의 Naming Convention
패키지의 구성은 프로젝트의 크기나 구성원들의 성향으로 결정한다. 예를 들어, 규모가 작은 프로젝트는 Controller 영역을 별도의 패키지로 설계하고, Service 영역 등을 하나의 패키지로 설계할 수 있다.
반면에, 프로젝트의 규모가 커져서 많은 Service 클래스와 Controller들이 혼재할 수 있다면 비즈니스를 단위별로 구분하고 다시 내부에서 Controller 패키지, Service 패키지 등으로 다시 나누는 방식을 이용한다.
2. 예제 프로젝트 구성
2-1. 'ex02' 라는 이름으로 Spring Legacy Project - Spring MVC Project 의 프로젝트를 만든다.
2-2. pom.xml에서 스프링과 Java 버전을 수정한다. 추가적인 라이브러리로는 spring-tx, spring-jdbc, spring-test를 추가한다.
2-3. MyBatis 관련 라이브러리도 추가한다. (HikariCP, MyBatis, mybatis-spring, Log4jdbc)
<!-- MyBatis -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.7.8</version>
</dependency>
<!-- http://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- Log4j -->
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
<version>1.16</version>
</dependency>
2-4. 테스트와 Lombok을 위해서 jUnit 버전을 변경하고, Lombok을 추가한다.
2-5. Servlet 3.1을 제대로 사용하기 위해서는 pom.xml에 있던 서블릿 2.5 버전을 3.0이상으로 수정한다.
(+ artifactId 에서 servlet-api 앞에 javax도 붙여주어야한다... 이거 때문에 삽질을........ ㅎ ㅏ)
2-6. Servlet 3.1 버전을 제대로 활용하고 JDK8의 기능을 활용하기 위해서 Maven 관련 Java 버전을 1.8로 수정한다.
2-7. 프로젝트 우클릭 Maven -> Update Project 실행
2-8. 마지막으로 Oracle JDBC Driver를 프로젝트의 Build Path에 추가하고, Deployment Assembly에도 추가한다.
2-9. 테이블 생성과 Dummy 데이터 생성
SQL Developer 를 이용해서 (전에 만들었던 계정인) book_ex 계정을 통해 테이블을 생성한다. 게시물은 각 게시물마다 고유의 번호가 필요하다. 오라클의 경우 시퀀스를 이용해서 이러한 작업을 처리한다.
2-9-1. sqldeveloper를 실행한뒤 아래와 같은 SQL문을 입력한 후 실행하고 commit 한다.
create sequence seq_board;
create table tbl_board (
bno number(10,0),
title varchar2(200) not null,
content varchar2(2000) not null,
writer varchar2(50) not null,
regdate date default sysdate,
updatedate date default sysdate
);
alter table tbl_board add constraint pk_board
primary key(bno);
insert into tbl_board(bno, title, content, writer)
values (seq_board.nextval, '테스트 제목', '테스트 내용', 'user00');
select * from tbl_board;
오라클의 경우, MYSQL과는 다르게 수동으로 commit을 처리해 주어야 한다.
3. 데이터 베이스 관련 설정 및 테스트
3-1. root-context.xml에는 mybatis-spring 네임스페이스를 추가하고, PART 1에서 작성한 DataSource의 설정과 MyBatis의 설정을 추가한다.
3-2. root-context.xml은 내부적으로 Log4jdbc를 이용하는 방식으로 구성되어 있으므로 전에 log4jdbc.log4j2.properties 파일을 추가한다.
3-3. 항상 jUnit 테스트 해보는것을 잊지 말자!
(이전 예제에서 만들었던 테스트코드로 jUnit을 실행시켜 보자)
'Spring > Spring' 카테고리의 다른 글
[12] 기본적인 웹 게시물 관리 - 비즈니스 계층 (0) | 2019.12.19 |
---|---|
[11] 기본적인 웹 게시물 관리 - 영속/비즈니스 계층의 CRUD 구현 (0) | 2019.12.18 |
[09] 스프링 MVC의 Controller 및 여러 예제 2 (0) | 2019.12.17 |
[08] 스프링 MVC의 Controller 및 여러 예제 (0) | 2019.12.17 |
[07] 스프링 MVC의 기본 구조 및 예제 실습 (0) | 2019.12.17 |