Study Web Development

3월 7일

이전으로

Spring

8. MyBatis

SQL Session

Util
  1. ch05JDBC 프로젝트의 kr.spring.util 패키지를 복사하여 ch06MybatisSqlSession 패키지에 붙여넣기
DAO
  1. Window-Preferences-Validation에서 MyBatis XML Mapper Validator의 Build 항목을 선택 해제
  2. BoardMapper.xml<mapper> 태그 사이에 다음의 내용을 추가
	<!-- 총 레코드 수 -->
	<select id="getBoardCount" resultType="integer"> <!-- java.lang.Integer의 alias가 integer -->
		SELECT
			COUNT(*)
		FROM tboard
	</select>

	<!-- 글쓰기 -->
	<insert id="insertBoard" parameterType="boardVO">
		INSERT INTO tboard (
			num,
			name,
			title,
			passwd,
			content,
			reg_date)
		VALUES (
			tboard_seq.NEXTVAL,
			#{name}, <!-- SQL문에 자바빈 객체의 데이터를 바인딩시, #{프로퍼티명} 형식으로 프로퍼티의 값을 호출  -->
			#{title},
			#{passwd},
			#{content},
			SYSDATE)
	</insert>
	
	<!-- 글 상세 -->
	<select id="getBoard" resultType="boardVO" parameterType="integer">
		SELECT
			*
		FROM tboard
		WHERE num=#{num} <!-- SQL문에 자바빈/Map 객체가 아닌 데이터 하나만 바인딩시, #{변수명} 형식으로 값 호출 -->
	</select>
	
	<!-- 글 수정 -->
	<update id="updateBoard" parameterType="boardVO">
		UPDATE tboard
		SET
			name=#{name},
			title=#{title},
			content=#{content}
		WHERE num=#{num}
	</update>
	
	<!-- 글 삭제 -->
	<delete id="deleteBoard" parameterType="integer">
		DELETE FROM tboard
		WHERE num=#{num}
	</delete>
Controller
  1. BoardController 클래스에 다음의 메서드를 추가
	// 자바빈 초기화
	@ModelAttribute
	public BoardVO initCommand() {
		return new BoardVO();
	}
	
	// 글쓰기 폼
	@GetMapping("/insert.do")
	public String form() {
		return "insertForm";
	}

	// 글쓰기 처리
	@PostMapping("/insert.do")
	public String submit(@Valid BoardVO boardVO, BindingResult result) {
		// 유효성 검증 결과 오류가 있으면 폼 호출
		if(result.hasErrors()) {
			return form();
		}
		
		// 글쓰기
		boardService.insertBoard(boardVO);
		
		return "redirect:/list.do";
	}

	// 글 상세
	@RequestMapping("/detail.do")
	public ModelAndView detail(@RequestParam int num) {
		BoardVO board = boardService.getBoard(num);
		
		return new ModelAndView("selectDetail", "board", board); // ModelAndView에 저장할 데이터가 1건인 경우에만 생성자 방식 이용 가능
	}
	
	// 수정 폼
	@GetMapping("/update.do")
	public String formUpdate(@RequestParam int num, Model model) {
		model.addAttribute("boardVO", boardService.getBoard(num));
		
		return "updateForm";
	}

	// 글 수정 처리
	@PostMapping("/update.do")
	public String submitUpdate(@Valid BoardVO boardVO, BindingResult result) {
		// 유효성 검증 결과 오류가 있으면 폼을 호출
		if(result.hasErrors()) {
			return "updateForm";
		}
		
		// 비밀번호 일치 여부 검증
		// DB에 저장되어 있는 비밀번호 구하기
		BoardVO db_board = boardService.getBoard(boardVO.getNum());
		// DB에 저장되어 있는 비밀번호와 사용자가 입력한 비밀번호가 불일치하면 폼 호출
		if(!db_board.getPasswd().equals(boardVO.getPasswd())) {
			result.rejectValue("passwd", "invalidPassword");
			return "updateForm";
		}
		
		// 글 수정
		boardService.updateBoard(boardVO);
		
		return "redirect:/list.do";
	}
	
	// 글 삭제 폼
	@GetMapping("/delete.do")
	public String formDelete(@RequestParam int num, Model model) {
		BoardVO boardVO = new BoardVO();
		boardVO.setNum(num);
		
		model.addAttribute("boardVO", boardVO);
		
		return "deleteForm";
	}

	// 글 삭제 처리
	@PostMapping("/delete.do")
	public String submitDelete(@Valid BoardVO boardVO, BindingResult result) {
		// 유효성 검증 결과에 오류가 있으면 폼 호출
		// 비밀번호가 전송되었는지 여부만 검증
		if(result.hasFieldErrors("passwd")) {
			return "deleteForm";
		}
		
		// 비밀번호 일치 여부 검증
		// DB에 저장되어 있는 비밀번호 구하기
		BoardVO db_board = boardService.getBoard(boardVO.getNum());
		// DB에 저장되어 있는 비밀번호와 사용자가 입력한 비밀번호가 불일치하면 폼 호출
		if(!db_board.getPasswd().equals(boardVO.getPasswd())) {
			result.rejectValue("passwd", "invalidPassword");
			return "deleteForm";
		}
		
		// 글 삭제
		boardService.deleteBoard(boardVO.getNum());
		
		return "redirect:/list.do";
	}
View
  1. views 폴더에 새 JSP 파일 insertForm.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글쓰기</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css">
</head>
<body>
<div class="page-main">
	<h2>글쓰기</h2>
	<form:form modelAttribute="boardVO">
	<ul>
		<li>
			<form:label path="name">작성자</form:label>
			<form:input path="name"/>
			<form:errors path="name" cssClass="error-color"/>
		</li>
		<li>
			<form:label path="title">제목</form:label>
			<form:input path="title"/>
			<form:errors path="title" cssClass="error-color"/>
		</li>
		<li>
			<form:label path="passwd">비밀번호</form:label>
			<form:password path="passwd"/>
			<form:errors path="passwd" cssClass="error-color"/>
		</li>
		<li>
			<form:label path="content">내용</form:label>
			<form:textarea path="content"/>
			<form:errors path="content" cssClass="error-color"/>
		</li>
	</ul>
	<div class="align-center">
		<input type="submit" value="등록">
		<input type="button" value="홈으로" onclick="location.href = 'list.do';">
	</div>
	</form:form>
</div>
</body>
</html>
  1. views 폴더에 새 JSP 파일 selectDetail.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글 상세</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css">
</head>
<body>
<div class="page-main">
	<h2>${board.title}</h2>
	<p>
		글 번호 : ${board.num}<br>
		작성자 : ${board.name}<br>
		작성일 : ${board.reg_date}
	</p>
	<hr width="100%" size="1" noshade>
	<p>
		${board.content}
	</p>
	<hr width="100%" size="1" noshade>
	<div class="align-center">
		<input type="button" value="수정" onclick="location.href = 'update.do?num=${board.num}';">
		<input type="button" value="삭제" onclick="location.href = 'delete.do?num=${board.num}';">
		<input type="button" value="홈으로" onclick="location.href = 'list.do';">
	</div>
</div>
</body>
</html>
  1. views 폴더에 새 JSP 파일 updateForm.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글 수정</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css">
</head>
<body>
<div class="page-main">
	<h2></h2>
	<form:form action="update.do" modelAttribute="boardVO">
		<form:hidden path="num"/>
		<ul>
			<li>
				<form:label path="name">작성자</form:label>
				<form:input path="name"/>
				<form:errors path="name" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="title">제목</form:label>
				<form:input path="title"/>
				<form:errors path="title" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="passwd">비밀번호</form:label>
				<form:password path="passwd"/>
				<form:errors path="passwd" cssClass="error-color"/>
			</li>
			<li>
				<form:label path="content">내용</form:label>
				<form:textarea path="content"/>
				<form:errors path="content" cssClass="error-color"/>
			</li>
		</ul>
		<div class="align-center">
			<form:button>수정</form:button>
			<input type="button" value="홈으로" onclick="location.href = 'list.do';">
		</div>
	</form:form>
</div>
</body>
</html>
  1. views 폴더에 새 JSP 파일 deleteForm.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>글 삭제</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css">
</head>
<body>
<div class="page-main">
	<h2>글 삭제</h2>
	<form:form action="delete.do" modelAttribute="boardVO">
		<form:hidden path="num"/>
		<ul>
			<li>
				<form:label path="passwd">비밀번호</form:label>
				<form:password path="passwd"/>
				<form:errors path="passwd" cssClass="error-color"/>
			</li>
		</ul>
		<div class="align-center">
			<form:button>삭제</form:button>
			<input type="button" value="홈으로" onclick="location.href = 'list.do';">
		</div>
	</form:form>
</div>
</body>
</html>

Annotation

프로젝트 생성 및 설정
  1. C:\javaWork\workspace_spring에서 ch06MybatisSqlSession 폴더를 복사 붙여넣기 후 폴더명을 ch07MybatisAnnot으로 변경
  2. File-Import...에서 ch07MybatisAnnot 프로젝트 선택
  3. src/main/resources/config 폴더의 SqlMapConfig.xml 삭제
  4. src/main/webapp/WEB-INF/spring 폴더의 root-context.xml에서 MyBaits 설정 부분을 삭제
  5. kr.spring.board.dao 패키지의 모든 파일을 삭제
  6. root-context.xml<beans> 태그 사이에 다음의 내용을 추가
	<!-- MyBatis 설정 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="typeAliasesPackage" value="kr.spring.board.vo"/> <!-- alias를 부여하기 위해 자바빈이 있는 패키지를 스캔 -->
	</bean>
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="kr.spring.board.dao"/> <!-- Mapper를 등록하기 위해 DAO가 있는 패키지를 스캔 -->
	</bean>
DAO
  1. kr.spring.board.dao 패키지에 새 인터페이스 BoardMapper 생성
package kr.spring.board.dao;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import kr.spring.board.vo.BoardVO;

public interface BoardMapper { // 인터페이스명을 XML 파일명과 동일하게 하면 별도의 구현 클래스를 만들 필요 없이 MyBatis에서 처리
	// SQL문은 XML이나 어노테이션 중 한쪽에만 명시 가능
	public void insertBoard(BoardVO board);
	@Select("SELECT COUNT(*) FROM tboard") // (SQL문이 간단한 경우) 어노테이션에 SQL문 명시
	public int getBoardCount();
	// (SQL문이 복잡한 경우) XML에 SQL문 명시; XML에서 SQL문의 식별자는 DAO의 메서드명을 사용
	public List<BoardVO> getBoardList(Map<String, Object> map);
	@Select("SELECT * FROM tboard WHERE num=#{num}")
	public BoardVO getBoard(int num);
	@Update("UPDATE tboard SET name=#{name}, title=#{title}, content=#{content} WHERE num=#{num}")
	public void updateBoard(BoardVO board);
	@Delete("DELETE FROM tboard WHERE num=#{num}")
	public void deleteBoard(int num);
}
  1. 새 XML 파일 BoardMapper.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="kr.spring.board.dao.BoardMapper"> 
	<!-- 목록 -->
	<select id="getBoardList" resultType="boardVO" parameterType="map"> <!-- (SQL문이 복잡한 경우) XML에 SQL문 명시; XML에서 SQL문의 식별자는 DAO의 메서드명을 사용 -->
		SELECT 
			*
		FROM (SELECT 
				a.*,
				ROWNUM AS rnum
			FROM (SELECT 
					* 
				FROM tboard 
				ORDER BY reg_date DESC) a)
		<![CDATA[
		WHERE rnum>=#{start} AND rnum<=#{end}
		]]>
	</select>
	
	<!-- 글쓰기 -->
	<insert id="insertBoard" parameterType="boardVO">
		INSERT INTO tboard (
			num,
			name,
			title,
			passwd,
			content,
			reg_date)
		VALUES (
			tboard_seq.NEXTVAL,
			#{name},
			#{title},
			#{passwd},
			#{content},
			SYSDATE)
	</insert>
</mapper>
Service
  1. BoardServiceImpl 클래스에서 BoardDAO, boardDAO를 각각 BoardMapper, boardMapper로 변경하고 BoardMapper 클래스를 import

Apache Tiles

https://tiles.apache.org/framework/index.html

  1. 새 Spring Legacy Project 생성하여 프로젝트명을 ch08Tiles, 최상위 패키지명을 kr.spring.tiles로 지정하고 Spring MVC Project 선택
  2. pom.xml에서 <properties> 태그 사이의 내용을 다음처럼 변경
		<java-version>1.8</java-version>
		<org.springframework-version>5.0.20.RELEASE</org.springframework-version>
  1. pom.xml에서 <dependencies> 태그 사이에 다음의 내용을 추가
		<!-- 라이브러리 추가 시작 -->
		<dependency>
			<groupId>org.apache.tiles</groupId>
			<artifactId>tiles-servlet</artifactId>
			<version>3.0.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.tiles</groupId>
			<artifactId>tiles-jsp</artifactId>
			<version>3.0.7</version>
		</dependency>
		<!-- 라이브러리 추가 끝 -->
  1. Java Build Path와 Project Facets에서 버전을 1.8로 변경
  2. src/main/webapp/WEB-INF/spring/appServlet에서 servlet-context.xml 열고 다음처럼 수정
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />
	
	<context:component-scan base-package="kr.spring.tiles.controller" />
	
	<beans:bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
		<beans:property name="definitions">
			<beans:list>
				<beans:value>/WEB-INF/tiles-def/tilesdef.xml</beans:value>
				
			</beans:list>
		</beans:property>
	</beans:bean>
	
	<!-- 기본 ViewResolver를 대체 -->
	<beans:bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
		<beans:property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView"/>
	</beans:bean>
</beans:beans>
  1. kr.spring.tiles 패키지 삭제
  2. src/main/webapp 폴더에 새 JSP 파일 index.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	response.sendRedirect(request.getContextPath() + "/index.do");
%>

Template

  1. WEB-INF 폴더에 하위 폴더로 views/template 생성하고 새 JSP 파일 header.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<h2 align="center">스프링 타일스 샘플</h2>
  1. template 폴더에 새 JSP 파일 menu.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<ul>
	<li><a href="index.do">main</a></li>
	<li><a href="company.do">회사 소개</a></li>
	<li><a href="product.do">제품 소개</a></li>
</ul>
  1. template 폴더에 새 JSP 파일 footer.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<div align="center" style="background-color: gold;">
	&copy; star shop
</div>
  1. template 폴더에 새 JSP 파일 body.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<b>main page body</b>
  1. template 폴더에 새 JSP 파일 layout.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><tiles:getAsString name="title"/></title>
</head>
<body>
	<table style="background-color: #a0a0a0; width: 800px;">
		<tr height="100">
			<td colspan="2" bgcolor="ffffff">
				<tiles:insertAttribute name="header"/>
			</td>
		</tr>
		<tr height="670" bgcolor="ffffff">
			<td width="15%" valign="top">
				<tiles:insertAttribute name="menu"/>
			</td>
			<td width="85%" align="center">
				<tiles:insertAttribute name="body"/>
			</td>
		</tr>
		<tr bgcolor="ffffff">
			<td colspan="2">
				<tiles:insertAttribute name="footer"/>
			</td>
		</tr>
	</table>
</body>
</html>

Definition

  1. src/main/webapp/WEB-INF 폴더에 하위 폴더로 tiles-def 생성하고 새 XML 파일 tilesdef.xml 생성
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">

<tiles-definitions>
	<definition name="index" template="/WEB-INF/views/template/layout.jsp">
		<put-attribute name="title" value="Spring Tiles Example"/>
		<put-attribute name="menu" value="/WEB-INF/views/template/menu.jsp"/>
		<put-attribute name="header" value="/WEB-INF/views/template/header.jsp"/>
		<put-attribute name="body" value="/WEB-INF/views/template/body.jsp"/>
		<put-attribute name="footer" value="/WEB-INF/views/template/footer.jsp"/>
	</definition>
</tiles-definitions>
  1. tilesdef.xml<tiles-definitions> 태그 사이에 다음의 내용을 추가
	<definition name="company" extends="index"> <!-- 식별자가 index인 definition 태그를 상속 -->
		<put-attribute name="body" value="/WEB-INF/views/company.jsp"/> <!-- 필요한 부분만 재정의 -->
	</definition>
	
	<definition name="product" extends="index">
		<put-attribute name="body" value="/WEB-INF/views/product.jsp"/>
	</definition>

Controller

  1. 새 패키지 kr.spring.tiles.controller 생성 후 새 클래스 IndexController 생성
package kr.spring.tiles.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {
	@RequestMapping("/index.do")
	public String process() {
		// Tiles 설정을 호출; JSP 파일이 아니라 tilesdef.xml의 <definition> 태그 식별자를 반환
		return "index";
	}
}
  1. 새 클래스 CompanyController 생성
package kr.spring.tiles.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CompanyController {
	@RequestMapping("/company.do")
	public String process() {
		// Tiles 설정 호출
		return "company";
	}
}
  1. 새 클래스 ProductController 생성
package kr.spring.tiles.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ProductController {
	@RequestMapping("/product.do")
	public String process() {
		// Tiles 설정 호출
		return "product";
	}
}

Views

  1. views 폴더에 새 JSP 파일 company.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<b>우리 회사에 오신 것을 환영합니다!</b>
  1. views 폴더에 새 JSP 파일 product.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<b>우수한 제품을 소개합니다.</b>

10. springPage

프로젝트 설정

  1. File-Import...에서 ch09springPage 프로젝트 선택
XML
  1. pom.xml에서 <dependencies> 태그 사이에 다음의 내용을 추가
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.5</version>
		</dependency>
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.3</version>
		</dependency>
  1. src/main/webapp/WEB-INF/spring/appServlet에서 servlet-context.xml 열고 다음처럼 수정
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- 팝업 창 등, Tiles를 이용하지 않고 JSP를 직접 호출해야 하는 경우에 사용되는 ViewResolver -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
		<beans:property name="order" value="2"/>
	</beans:bean>
	
	<context:component-scan base-package="kr.spring.**.controller" /> <!-- 하위 패키지는 **로 호출 가능 -->
	
	<beans:bean id="tilesConfigurer"
	   class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
		<beans:property name="definitions">
			<beans:list>
				<beans:value>/WEB-INF/tiles-def/main.xml</beans:value>
			</beans:list>
		</beans:property>	
	</beans:bean>
	
	<beans:bean id="viewResolver"
	   class="org.springframework.web.servlet.view.UrlBasedViewResolver">
		<beans:property name="viewClass" 
		   value="org.springframework.web.servlet.view.tiles3.TilesView"/>
		<beans:property name="order" value="1"/>
	</beans:bean>
	
	<!-- 파일 다운로드시에 사용되는 ViewResolver -->
	<beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="0"/>
	
	<!-- 파일 업로드 -->
	<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<beans:property name="maxUploadSize" value="52428800"/> <!-- 50MB -->
		<beans:property name="defaultEncoding" value="UTF-8"/>
	</beans:bean>
	
	<!-- messagSource 지정 -->
	<beans:bean id="messageSource"
	   class="org.springframework.context.support.ResourceBundleMessageSource">
		<beans:property name="basenames">
			<beans:list>
				<beans:value>messages.validation</beans:value>
			</beans:list>
		</beans:property>	
	</beans:bean>
	
</beans:beans>
CSS
  1. src/main/webapp/resources/css 폴더의 style.css를 열고 다음처럼 수정
@CHARSET "UTF-8";

/* 레이아웃 */
div#main {
	width: 1024px;
	margin: 0 auto;
	font-size: 10pt;
	font-family: '맑은 고딕';
}
div#main_header {
	margin-bottom: 0 10px;
	padding: 0 10px 0 0;
}
div#main_menu {
	float: left;
	width: 17%;
	min-height: 400px;
}
div#main_body {
	float: right;
	width: 78%;
	padding: 5px 5px 30px 5px;
}
div#main_footer {
	clear: both;
	width: 100%;
	background-color: gold;
}

/* 메뉴 */
div#main_menu ul {
	list-style: none;
}
div#main_menu ul li {
	margin-bottom: 5px;
}

/* 본문 */
.page-main {
	width: 98%;
	margin: 0 auto;
}
.result-display {
	width: 400px;
	height: 200px;
	/* 정중앙에 div를 배치하기 위한 설정 */
	position: absolute;
    top: 50%;
  	left: 50%;
  	transform: translate(-50%, -50%);
    /* 테두리 */
	border: 1px solid #000;
	/* 하위 요소를 수직으로 쌓을 수 있는 공간을 만듦 */
	display: flex;
	/* 세로 정렬 */
  	align-items: center;
  	/* 가로 정렬 */
  	justify-content: center;
}
.align-right {
	text-align: right;
}
.align-center {
	text-align: center;
}

/* 목록 */
table {
	width: 100%;
	border: 1px solid #000;
	border-collapse: collapse;
}
table td, table th {
	border: 1px solid #000;
	padding: 5px;
}

/* 등록, 수정 폼 */
form {
	width: 500px;
	margin: 0 auto;
	border: 1px solid #000;
	padding: 10px 10px 10px 30px;
}
ul {
	list-style: none;
}
label {
	width: 100px;
	float: left;
}
.error-color {
	color: red;
}
Tiles
Template
  1. src/main/webapp/WEB-INF/views 폴더에 하위 폴더로 template 폴더 생성하고 새 JSP 파일 header.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- 상단 시작 -->
<h2 class="align-center">Star Homepage</h2>
<div class="align-right">
	<c:if test="${!empty user_num && !empty user_photo}">
		<img src="${pageContext.request.contextPath}/member/photoView.do" width="25" height="25" class="my-photo">
	</c:if>
	<c:if test="${!empty user_num && empty user_photo}">
		<img src="${pageContext.request.contextPath}/resources/images/face.png" width="25" height="25" class="my-photo">
	</c:if>
	<c:if test="${!empty user_num}">
		[<span>${user_id}</span>]
		<a href="${pageContext.request.contextPath}/member/logout.do">로그아웃</a>
	</c:if>
	<c:if test="${empty user_num}">
		<a href="${pageContext.request.contextPath}/member/registerUser.do">회원 가입</a>
		<a href="${pageContext.request.contextPath}/member/login.do">로그인</a>
	</c:if>
	<c:if test="${!empty user_num && user_auth==2}">
		<a href="${pageContext.request.contextPath}/member/myPage.do">MY 페이지</a>
	</c:if>
	<a href="${pageContext.request.contextPath}/main/main.do">홈으로</a>
</div>
<!-- 상단 끝 -->
  1. template 폴더에 새 JSP 파일 left.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- 왼쪽 메뉴 시작 -->
<ul>
	<li><a href="${pageContext.request.contextPath}/board/list.do">게시판</a></li>
	<c:if test="${!empty user_num && user_auth==3}">
	<li><a href="${pageContext.request.contextPath}/member/admin_list.do">회원 관리</a></li>
	</c:if>
</ul>
<!-- 왼쪽 메뉴 끝 -->
  1. template 폴더에 새 JSP 파일 footer.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 하단 시작 -->
<div class="align-center">
	&copy; springPage
</div>
<!-- 하단 끝 -->
  1. template 폴더에 새 JSP 파일 layout.jsp 생성
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><tiles:getAsString name="title"/></title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/css/style.css">
</head>
<body>
<div id="main">
	<div id="main_header">
		<tiles:insertAttribute name="header"/>
	</div>
	<div id="main_menu">
		<tiles:insertAttribute name="left"/>
	</div>
	<div id="main_body">
		<tiles:insertAttribute name="body"/>
	</div>
	<div id="main_footer">
		<tiles:insertAttribute name="footer"/>
	</div>
</div>
</body>
</html>

Main

JSP
  1. src/main/webappindex.jsp를 다음처럼 수정
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
	response.sendRedirect(request.getContextPath()+"/main/main.do");
%>

다음으로