관리 메뉴

거니의 velog

231122_SPRING 2 (1-2) 본문

대덕인재개발원_웹기반 애플리케이션

231122_SPRING 2 (1-2)

Unlimited00 2023. 11. 22. 08:34
package kr.or.ddit.controller.board;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/board")
public class BoardController {

	/*
	 * [ 3장 : 컨트롤러 요청 매핑 ]
	 * 
	 * 		1. 요청 경로 매핑
	 * 
	 * 			- @RequestMapping의 value 속성에 요청 경로를 설정한다.
	 * 			- 요청 경로는 반드시 설정해야 하는 필수 정보이다.
	 * 			- 속성이 하나일 때는 속성명을 생략할 수 있다. (default는 value)
	 * 			- 컨트롤러의 클래스 레벨과 메서드 레벨로 지정할 수 있다.
	 * 			- 클래스 레벨로 요청 경로를 지정하면 메서드 레벨에서 지정한 경로의 기본 경로로 취급된다.
	 * 			- 클래스 레벨의 요청 경로에 메서드 레벨의 요청 경로를 덧붙인 형태가 최종 경로가 된다.
	 */
	
	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	
	@RequestMapping(value = "/register")
	public void registerForm() {
		log.info("registerForm() 실행...!");
	}
	
	@RequestMapping(value = "/modify")
	public void modifyForm() {
		log.info("modifyForm() 실행...!");
	}
	
	@RequestMapping(value = "/list")
	public void list() {
		log.info("list() 실행...!");
	}
	
	/*
	 * 		2. 경로 패턴 매핑
	 * 
	 * 			- 요청 경로를 동적으로 표현이 가능한 경로 패턴을 지정할 수 있다.
	 * 			- URL 경로 상의 변하는 값을 경로 변수로 취급한다.
	 * 			- 경로 변수에 해당하는 값을 파라미터 변수에 설정할 수 있다.
	 */
	
	@RequestMapping(value = "/read/{boardNo}")
	public String read(@PathVariable("boardNo") int boardNo) {
		log.info("read() 실행...!");
		log.info("경로 상의 포함된 boardNo : " + boardNo);
		return "board/read";
	}
	
	/*
	 *		3. HTTP 메서드 매핑
	 *
	 *			- method 속성을 사용하여 HTTP 메서드를 매핑 조건으로 지정할 수 있다.
	 *			- 화면으로 응답하는 경우에는 HTTP 메서드로 GET방식과 POST방식 두 가지를 사용할 수 있다.
	 */
	
	// HTTP 메서드 매핑 실행 페이지
	
	@RequestMapping(value = "/formHome", method = RequestMethod.GET)
	public String formHome() {
		log.info("formHome() 실행...!");
		return "formHome";
	}
	
	// register 경로에 GET 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.GET)
	public String registerFormHttp() {
		log.info("registerFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// register 경로에 POST 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.POST)
	public String registerHttp() {
		log.info("registerHttp() 실행...!");
		return "success";
	}
	
	// modify 경로에  GET 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.GET)
	public String modifyFormHttp() {
		log.info("modifyFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// modify 경로에 POST 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.POST)
	public String modifyHttp() {
		log.info("modifyHttp() 실행...!");
		return "success";
	}
	
	// remove 경로에 POST 방식
	@RequestMapping(value = "/http/remove", method = RequestMethod.POST)
	public String removeHttp() {
		log.info("removeHttp() 실행...!");
		return "success";
	}
	
	// list 경로에 GET 방식
	@RequestMapping(value = "/http/list", method = RequestMethod.GET)
	public String listHttp() {
		log.info("listHttp() 실행...!");
		return "success";
	}
	
	/*
	 * 		4. Params 매핑
	 * 
	 * 			- 요청 파라미터를 매핑 조건으로 지정하는 경우에는 params 속성을 사용한다.
	 * 			- 버튼이나 링크에 따라 호출할 메서드를 바꿔야 할 때 사용한다.
	 * 
	 * 			** Params 매핑 테스트 페이지
	 * 				> board/list.jsp
	 * 				> board/modify.jsp
	 * 				> board/read.jsp
	 * 				> board/register.jsp
	 * 				> board/remove.jsp
	 */
	
	// /board/get 경로, GET 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "register")
	public String registerFormParamsGet() {
		log.info("registerFormParamsGet() 실행...!");
		return "board/register";
	}
	
	// /board/post 경로, POST 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "register")
	public String registerParamsPost() {
		log.info("registerParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "modify")
	public String modifyFormParamsGet() {
		log.info("modifyFormParamsGet() 실행...!");
		return "board/modify";
	}
	
	// /board/post 경로, POST 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "modify")
	public String modifyParamsPost() {
		log.info("modifyParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "remove")
	public String removeFormParamsGet() {
		log.info("removeFormParamsGet() 실행...!");
		return "board/remove";
	}
	
	// /board/post 경로, POST 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "remove")
	public String removeParamsPost() {
		log.info("removeParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/list 경로, GET 방식, "list" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "list")
	public String listParamsGet() {
		log.info("listParamsGet() 실행...!");
		return "board/list";
	}
	
	// /board/read 경로, GET 방식, "read" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "read")
	public String readParamsGet() {
		log.info("readParamsGet() 실행...!");
		return "board/read";
	}
	
	/*
	 * 		5. Headers 매핑
	 * 
	 * 			- 요청 헤더를 매핑 조건으로 지정하는 경우에는 headers 속성을 사용한다.
	 */
	
	// Headers 매핑을 테스트할 페이지
	@RequestMapping(value = "/ajaxHome", method = RequestMethod.GET)
	public String ajaxHome() {
		log.info("ajaxHome() 실행...!");
		return "ajaxHome";
	}
	
}

[ajaxHome.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AjaxHome</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h3>AJAX HOME</h3>

		<hr />
		
		<form action="" method="get">
			boardNo : <input type="text" name="boardNo" id="boardNo" /><br />
			title : <input type="text" name="title" id="title" /><br />
			content : <textarea rows="20" cols="50" name="content" id="content"></textarea><br />
			writer : <input type="text" name="writer" id="writer" /><br />
			<input type="button" id="btn" value="전송" />
		</form>
		
		<br />
		
		<div>
			<h3>Headers 매핑</h3>
			<button id="putBtn" type="button">MODIFY(PUT)</button>
			<button id="putHeaderBtn" type="button">MODIFY(PUT With Header)</button>
		</div>
	</body>
	
	<script type="text/javascript">
		$(function(){
			var putBtn = $("#putBtn");				// 버튼 putBtn Element
			var putHeaderBtn = $("#putHeaderBtn");	// 버튼 putHeaderBtn Element
			
			putBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				// 비동기 처리
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// 강력한 equals
						// 값과 타입과 hash까지 일치하는지를 검증
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putHeaderBtn.on("click", function(){
				
			});
		});
	</script>
	
</html>

[Board.java]

package kr.or.ddit.vo;

import java.util.Date;

public class Board {

	private int boardNo;
	private String title;
	private String content;
	private String writer;
	private Date regDate;
	
	public int getBoardNo() {
		return boardNo;
	}
	public void setBoardNo(int boardNo) {
		this.boardNo = boardNo;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public Date getRegDate() {
		return regDate;
	}
	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}
	
	@Override
	public String toString() {
		return "Board [boardNo=" + boardNo + ", title=" + title + ", content=" + content + ", writer=" + writer + "]";
	}
	
}
package kr.or.ddit.controller.board;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.vo.Board;

@Controller
@RequestMapping("/board")
public class BoardController {

	/*
	 * [ 3장 : 컨트롤러 요청 매핑 ]
	 * 
	 * 		1. 요청 경로 매핑
	 * 
	 * 			- @RequestMapping의 value 속성에 요청 경로를 설정한다.
	 * 			- 요청 경로는 반드시 설정해야 하는 필수 정보이다.
	 * 			- 속성이 하나일 때는 속성명을 생략할 수 있다. (default는 value)
	 * 			- 컨트롤러의 클래스 레벨과 메서드 레벨로 지정할 수 있다.
	 * 			- 클래스 레벨로 요청 경로를 지정하면 메서드 레벨에서 지정한 경로의 기본 경로로 취급된다.
	 * 			- 클래스 레벨의 요청 경로에 메서드 레벨의 요청 경로를 덧붙인 형태가 최종 경로가 된다.
	 */
	
	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	
	@RequestMapping(value = "/register")
	public void registerForm() {
		log.info("registerForm() 실행...!");
	}
	
	@RequestMapping(value = "/modify")
	public void modifyForm() {
		log.info("modifyForm() 실행...!");
	}
	
	@RequestMapping(value = "/list")
	public void list() {
		log.info("list() 실행...!");
	}
	
	/*
	 * 		2. 경로 패턴 매핑
	 * 
	 * 			- 요청 경로를 동적으로 표현이 가능한 경로 패턴을 지정할 수 있다.
	 * 			- URL 경로 상의 변하는 값을 경로 변수로 취급한다.
	 * 			- 경로 변수에 해당하는 값을 파라미터 변수에 설정할 수 있다.
	 */
	
	@RequestMapping(value = "/read/{boardNo}")
	public String read(@PathVariable("boardNo") int boardNo) {
		log.info("read() 실행...!");
		log.info("경로 상의 포함된 boardNo : " + boardNo);
		return "board/read";
	}
	
	/*
	 *		3. HTTP 메서드 매핑
	 *
	 *			- method 속성을 사용하여 HTTP 메서드를 매핑 조건으로 지정할 수 있다.
	 *			- 화면으로 응답하는 경우에는 HTTP 메서드로 GET방식과 POST방식 두 가지를 사용할 수 있다.
	 */
	
	// HTTP 메서드 매핑 실행 페이지
	
	@RequestMapping(value = "/formHome", method = RequestMethod.GET)
	public String formHome() {
		log.info("formHome() 실행...!");
		return "formHome";
	}
	
	// register 경로에 GET 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.GET)
	public String registerFormHttp() {
		log.info("registerFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// register 경로에 POST 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.POST)
	public String registerHttp() {
		log.info("registerHttp() 실행...!");
		return "success";
	}
	
	// modify 경로에  GET 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.GET)
	public String modifyFormHttp() {
		log.info("modifyFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// modify 경로에 POST 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.POST)
	public String modifyHttp() {
		log.info("modifyHttp() 실행...!");
		return "success";
	}
	
	// remove 경로에 POST 방식
	@RequestMapping(value = "/http/remove", method = RequestMethod.POST)
	public String removeHttp() {
		log.info("removeHttp() 실행...!");
		return "success";
	}
	
	// list 경로에 GET 방식
	@RequestMapping(value = "/http/list", method = RequestMethod.GET)
	public String listHttp() {
		log.info("listHttp() 실행...!");
		return "success";
	}
	
	/*
	 * 		4. Params 매핑
	 * 
	 * 			- 요청 파라미터를 매핑 조건으로 지정하는 경우에는 params 속성을 사용한다.
	 * 			- 버튼이나 링크에 따라 호출할 메서드를 바꿔야 할 때 사용한다.
	 * 
	 * 			** Params 매핑 테스트 페이지
	 * 				> board/list.jsp
	 * 				> board/modify.jsp
	 * 				> board/read.jsp
	 * 				> board/register.jsp
	 * 				> board/remove.jsp
	 */
	
	// /board/get 경로, GET 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "register")
	public String registerFormParamsGet() {
		log.info("registerFormParamsGet() 실행...!");
		return "board/register";
	}
	
	// /board/post 경로, POST 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "register")
	public String registerParamsPost() {
		log.info("registerParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "modify")
	public String modifyFormParamsGet() {
		log.info("modifyFormParamsGet() 실행...!");
		return "board/modify";
	}
	
	// /board/post 경로, POST 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "modify")
	public String modifyParamsPost() {
		log.info("modifyParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "remove")
	public String removeFormParamsGet() {
		log.info("removeFormParamsGet() 실행...!");
		return "board/remove";
	}
	
	// /board/post 경로, POST 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "remove")
	public String removeParamsPost() {
		log.info("removeParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/list 경로, GET 방식, "list" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "list")
	public String listParamsGet() {
		log.info("listParamsGet() 실행...!");
		return "board/list";
	}
	
	// /board/read 경로, GET 방식, "read" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "read")
	public String readParamsGet() {
		log.info("readParamsGet() 실행...!");
		return "board/read";
	}
	
	/*
	 * 		5. Headers 매핑
	 * 
	 * 			- 요청 헤더를 매핑 조건으로 지정하는 경우에는 headers 속성을 사용한다.
	 */
	
	// Headers 매핑을 테스트할 페이지
	@RequestMapping(value = "/ajaxHome", method = RequestMethod.GET)
	public String ajaxHome() {
		log.info("ajaxHome() 실행...!");
		return "ajaxHome";
	}
	
	// Headers 매핑이지만, headers 설정을 하지 않고 요청
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT)
	public ResponseEntity<String> modifyPut(@PathVariable("boardNo") int boardNo,
			Board board) {
		log.info("modifyPut() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
	}
	
}

- http://localhost/board/ajaxHome


[pom.xml] 에 추가...

		<!-- json 데이터 바인딩을 위한 의존 라이브러리 -->	
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.5</version>
		</dependency>

	// Headers 매핑이지만, headers 설정을 하지 않고 요청
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT)
	public ResponseEntity<String> modifyPut(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board) {
		log.info("modifyPut() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
	}


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AjaxHome</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h3>AJAX HOME</h3>

		<hr />
		
		<form action="" method="get">
			boardNo : <input type="text" name="boardNo" id="boardNo" /><br />
			title : <input type="text" name="title" id="title" /><br />
			content : <textarea rows="20" cols="50" name="content" id="content"></textarea><br />
			writer : <input type="text" name="writer" id="writer" /><br />
			<input type="button" id="btn" value="전송" />
		</form>
		
		<br />
		
		<div>
			<h3>Headers 매핑</h3>
			<button id="putBtn" type="button">MODIFY(PUT)</button>
			<button id="putHeaderBtn" type="button">MODIFY(PUT With Header)</button>
		</div>
	</body>
	
	<script type="text/javascript">
		$(function(){
			var putBtn = $("#putBtn");				// 버튼 putBtn Element
			var putHeaderBtn = $("#putHeaderBtn");	// 버튼 putHeaderBtn Element
			
			putBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				// 비동기 처리
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// 강력한 equals
						// 값과 타입과 hash까지 일치하는지를 검증
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putHeaderBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					headers : {
						"X-HTTP-Method-Override" : "PUT"
					},
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
		});
	</script>
	
</html>
package kr.or.ddit.controller.board;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.vo.Board;

@Controller
@RequestMapping("/board")
public class BoardController {

	/*
	 * [ 3장 : 컨트롤러 요청 매핑 ]
	 * 
	 * 		1. 요청 경로 매핑
	 * 
	 * 			- @RequestMapping의 value 속성에 요청 경로를 설정한다.
	 * 			- 요청 경로는 반드시 설정해야 하는 필수 정보이다.
	 * 			- 속성이 하나일 때는 속성명을 생략할 수 있다. (default는 value)
	 * 			- 컨트롤러의 클래스 레벨과 메서드 레벨로 지정할 수 있다.
	 * 			- 클래스 레벨로 요청 경로를 지정하면 메서드 레벨에서 지정한 경로의 기본 경로로 취급된다.
	 * 			- 클래스 레벨의 요청 경로에 메서드 레벨의 요청 경로를 덧붙인 형태가 최종 경로가 된다.
	 */
	
	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	
	@RequestMapping(value = "/register")
	public void registerForm() {
		log.info("registerForm() 실행...!");
	}
	
	@RequestMapping(value = "/modify")
	public void modifyForm() {
		log.info("modifyForm() 실행...!");
	}
	
	@RequestMapping(value = "/list")
	public void list() {
		log.info("list() 실행...!");
	}
	
	/*
	 * 		2. 경로 패턴 매핑
	 * 
	 * 			- 요청 경로를 동적으로 표현이 가능한 경로 패턴을 지정할 수 있다.
	 * 			- URL 경로 상의 변하는 값을 경로 변수로 취급한다.
	 * 			- 경로 변수에 해당하는 값을 파라미터 변수에 설정할 수 있다.
	 */
	
	@RequestMapping(value = "/read/{boardNo}")
	public String read(@PathVariable("boardNo") int boardNo) {
		log.info("read() 실행...!");
		log.info("경로 상의 포함된 boardNo : " + boardNo);
		return "board/read";
	}
	
	/*
	 *		3. HTTP 메서드 매핑
	 *
	 *			- method 속성을 사용하여 HTTP 메서드를 매핑 조건으로 지정할 수 있다.
	 *			- 화면으로 응답하는 경우에는 HTTP 메서드로 GET방식과 POST방식 두 가지를 사용할 수 있다.
	 */
	
	// HTTP 메서드 매핑 실행 페이지
	
	@RequestMapping(value = "/formHome", method = RequestMethod.GET)
	public String formHome() {
		log.info("formHome() 실행...!");
		return "formHome";
	}
	
	// register 경로에 GET 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.GET)
	public String registerFormHttp() {
		log.info("registerFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// register 경로에 POST 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.POST)
	public String registerHttp() {
		log.info("registerHttp() 실행...!");
		return "success";
	}
	
	// modify 경로에  GET 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.GET)
	public String modifyFormHttp() {
		log.info("modifyFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// modify 경로에 POST 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.POST)
	public String modifyHttp() {
		log.info("modifyHttp() 실행...!");
		return "success";
	}
	
	// remove 경로에 POST 방식
	@RequestMapping(value = "/http/remove", method = RequestMethod.POST)
	public String removeHttp() {
		log.info("removeHttp() 실행...!");
		return "success";
	}
	
	// list 경로에 GET 방식
	@RequestMapping(value = "/http/list", method = RequestMethod.GET)
	public String listHttp() {
		log.info("listHttp() 실행...!");
		return "success";
	}
	
	/*
	 * 		4. Params 매핑
	 * 
	 * 			- 요청 파라미터를 매핑 조건으로 지정하는 경우에는 params 속성을 사용한다.
	 * 			- 버튼이나 링크에 따라 호출할 메서드를 바꿔야 할 때 사용한다.
	 * 
	 * 			** Params 매핑 테스트 페이지
	 * 				> board/list.jsp
	 * 				> board/modify.jsp
	 * 				> board/read.jsp
	 * 				> board/register.jsp
	 * 				> board/remove.jsp
	 */
	
	// /board/get 경로, GET 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "register")
	public String registerFormParamsGet() {
		log.info("registerFormParamsGet() 실행...!");
		return "board/register";
	}
	
	// /board/post 경로, POST 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "register")
	public String registerParamsPost() {
		log.info("registerParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "modify")
	public String modifyFormParamsGet() {
		log.info("modifyFormParamsGet() 실행...!");
		return "board/modify";
	}
	
	// /board/post 경로, POST 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "modify")
	public String modifyParamsPost() {
		log.info("modifyParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "remove")
	public String removeFormParamsGet() {
		log.info("removeFormParamsGet() 실행...!");
		return "board/remove";
	}
	
	// /board/post 경로, POST 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "remove")
	public String removeParamsPost() {
		log.info("removeParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/list 경로, GET 방식, "list" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "list")
	public String listParamsGet() {
		log.info("listParamsGet() 실행...!");
		return "board/list";
	}
	
	// /board/read 경로, GET 방식, "read" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "read")
	public String readParamsGet() {
		log.info("readParamsGet() 실행...!");
		return "board/read";
	}
	
	/*
	 * 		5. Headers 매핑
	 * 
	 * 			- 요청 헤더를 매핑 조건으로 지정하는 경우에는 headers 속성을 사용한다.
	 */
	
	// Headers 매핑을 테스트할 페이지
	@RequestMapping(value = "/ajaxHome", method = RequestMethod.GET)
	public String ajaxHome() {
		log.info("ajaxHome() 실행...!");
		return "ajaxHome";
	}
	
	// Headers 매핑이지만, headers 설정을 하지 않고 요청
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT)
	public ResponseEntity<String> modifyPut(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board) {
		
		log.info("modifyPut() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
	}
	
	// headers 속성에 설정되어 있는 header 정보를 매핑으로 요청
	// header 속성에 'X-HTTP-Method-Override=PUT' 정보가 들어 있는 요청은 이곳으로 들어옴
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, headers = "X-HTTP-Method-Override=PUT")
	public ResponseEntity<String> modifyByHeader(@PathVariable int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByHeader() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
}

- http://localhost/board/ajaxHome


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AjaxHome</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h3>AJAX HOME</h3>

		<hr />
		
		<form action="" method="get">
			boardNo : <input type="text" name="boardNo" id="boardNo" /><br />
			title : <input type="text" name="title" id="title" /><br />
			content : <textarea rows="20" cols="50" name="content" id="content"></textarea><br />
			writer : <input type="text" name="writer" id="writer" /><br />
			<input type="button" id="btn" value="전송" />
		</form>
		
		<br />
		
		<div>
		
			<h3>Headers 매핑</h3>
			<button id="putBtn" type="button">MODIFY(PUT)</button>
			<button id="putHeaderBtn" type="button">MODIFY(PUT With Header)</button>
			
			<br />
			
			<h3>Content Type 매핑</h3>
			<button id="postBtn" type="button">MODIFY(POST)</button>
			<button id="putJsonBtn" type="button">MODIFY(PUT JSON)</button>
			<button id="putXMLBtn" type="button">MODIFY(PUT XML)</button>
			
		</div>
	</body>
	
	<script type="text/javascript">
		$(function(){
			
			// Headers 매핑
			var putBtn = $("#putBtn");				// 버튼 putBtn Element
			var putHeaderBtn = $("#putHeaderBtn");	// 버튼 putHeaderBtn Element
			
			// Content Type 매핑
			var postBtn = $("#postBtn");			// 버튼 postBtn Element
			var putJsonBtn = $("#putJsonBtn");		// 버튼 putJsonBtn Element
			var putXMLBtn = $("#putXMLBtn");		// 버튼 putXMLBtn Element
			
			// Headers 매핑 시작 --------------------------------------
			putBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				// 비동기 처리
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// 강력한 equals
						// 값과 타입과 hash까지 일치하는지를 검증
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putHeaderBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					headers : {
						"X-HTTP-Method-Override" : "PUT"
					},
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Headers 매핑 끝 --------------------------------------
			
			// Content Type 매핑 시작 --------------------------------------
			postBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "post",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putJsonBtn.on("click", function(){
				
			});
			
			putXMLBtn.on("click", function(){
				
			});
			// Content Type 매핑 끝 --------------------------------------
			
		});
	</script>
	
</html>
package kr.or.ddit.controller.board;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.vo.Board;

@Controller
@RequestMapping("/board")
public class BoardController {

	/*
	 * [ 3장 : 컨트롤러 요청 매핑 ]
	 * 
	 * 		1. 요청 경로 매핑
	 * 
	 * 			- @RequestMapping의 value 속성에 요청 경로를 설정한다.
	 * 			- 요청 경로는 반드시 설정해야 하는 필수 정보이다.
	 * 			- 속성이 하나일 때는 속성명을 생략할 수 있다. (default는 value)
	 * 			- 컨트롤러의 클래스 레벨과 메서드 레벨로 지정할 수 있다.
	 * 			- 클래스 레벨로 요청 경로를 지정하면 메서드 레벨에서 지정한 경로의 기본 경로로 취급된다.
	 * 			- 클래스 레벨의 요청 경로에 메서드 레벨의 요청 경로를 덧붙인 형태가 최종 경로가 된다.
	 */
	
	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	
	@RequestMapping(value = "/register")
	public void registerForm() {
		log.info("registerForm() 실행...!");
	}
	
	@RequestMapping(value = "/modify")
	public void modifyForm() {
		log.info("modifyForm() 실행...!");
	}
	
	@RequestMapping(value = "/list")
	public void list() {
		log.info("list() 실행...!");
	}
	
	/*
	 * 		2. 경로 패턴 매핑
	 * 
	 * 			- 요청 경로를 동적으로 표현이 가능한 경로 패턴을 지정할 수 있다.
	 * 			- URL 경로 상의 변하는 값을 경로 변수로 취급한다.
	 * 			- 경로 변수에 해당하는 값을 파라미터 변수에 설정할 수 있다.
	 */
	
	@RequestMapping(value = "/read/{boardNo}")
	public String read(@PathVariable("boardNo") int boardNo) {
		log.info("read() 실행...!");
		log.info("경로 상의 포함된 boardNo : " + boardNo);
		return "board/read";
	}
	
	/*
	 *		3. HTTP 메서드 매핑
	 *
	 *			- method 속성을 사용하여 HTTP 메서드를 매핑 조건으로 지정할 수 있다.
	 *			- 화면으로 응답하는 경우에는 HTTP 메서드로 GET방식과 POST방식 두 가지를 사용할 수 있다.
	 */
	
	// HTTP 메서드 매핑 실행 페이지
	
	@RequestMapping(value = "/formHome", method = RequestMethod.GET)
	public String formHome() {
		log.info("formHome() 실행...!");
		return "formHome";
	}
	
	// register 경로에 GET 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.GET)
	public String registerFormHttp() {
		log.info("registerFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// register 경로에 POST 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.POST)
	public String registerHttp() {
		log.info("registerHttp() 실행...!");
		return "success";
	}
	
	// modify 경로에  GET 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.GET)
	public String modifyFormHttp() {
		log.info("modifyFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// modify 경로에 POST 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.POST)
	public String modifyHttp() {
		log.info("modifyHttp() 실행...!");
		return "success";
	}
	
	// remove 경로에 POST 방식
	@RequestMapping(value = "/http/remove", method = RequestMethod.POST)
	public String removeHttp() {
		log.info("removeHttp() 실행...!");
		return "success";
	}
	
	// list 경로에 GET 방식
	@RequestMapping(value = "/http/list", method = RequestMethod.GET)
	public String listHttp() {
		log.info("listHttp() 실행...!");
		return "success";
	}
	
	/*
	 * 		4. Params 매핑
	 * 
	 * 			- 요청 파라미터를 매핑 조건으로 지정하는 경우에는 params 속성을 사용한다.
	 * 			- 버튼이나 링크에 따라 호출할 메서드를 바꿔야 할 때 사용한다.
	 * 
	 * 			** Params 매핑 테스트 페이지
	 * 				> board/list.jsp
	 * 				> board/modify.jsp
	 * 				> board/read.jsp
	 * 				> board/register.jsp
	 * 				> board/remove.jsp
	 */
	
	// /board/get 경로, GET 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "register")
	public String registerFormParamsGet() {
		log.info("registerFormParamsGet() 실행...!");
		return "board/register";
	}
	
	// /board/post 경로, POST 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "register")
	public String registerParamsPost() {
		log.info("registerParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "modify")
	public String modifyFormParamsGet() {
		log.info("modifyFormParamsGet() 실행...!");
		return "board/modify";
	}
	
	// /board/post 경로, POST 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "modify")
	public String modifyParamsPost() {
		log.info("modifyParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "remove")
	public String removeFormParamsGet() {
		log.info("removeFormParamsGet() 실행...!");
		return "board/remove";
	}
	
	// /board/post 경로, POST 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "remove")
	public String removeParamsPost() {
		log.info("removeParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/list 경로, GET 방식, "list" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "list")
	public String listParamsGet() {
		log.info("listParamsGet() 실행...!");
		return "board/list";
	}
	
	// /board/read 경로, GET 방식, "read" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "read")
	public String readParamsGet() {
		log.info("readParamsGet() 실행...!");
		return "board/read";
	}
	
	/*
	 * 		5. Headers 매핑
	 * 
	 * 			- 요청 헤더를 매핑 조건으로 지정하는 경우에는 headers 속성을 사용한다.
	 */
	
	// Headers 매핑을 테스트할 페이지
	@RequestMapping(value = "/ajaxHome", method = RequestMethod.GET)
	public String ajaxHome() {
		log.info("ajaxHome() 실행...!");
		return "ajaxHome";
	}
	
	// Headers 매핑이지만, headers 설정을 하지 않고 요청
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT)
	public ResponseEntity<String> modifyPut(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board) {
		
		log.info("modifyPut() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
	}
	
	// headers 속성에 설정되어 있는 header 정보를 매핑으로 요청
	// header 속성에 'X-HTTP-Method-Override=PUT' 정보가 들어 있는 요청은 이곳으로 들어옴
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, headers = "X-HTTP-Method-Override=PUT")
	public ResponseEntity<String> modifyByHeader(@PathVariable int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByHeader() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	/*
	 * 		6. Content Type 매핑
	 * 
	 * 			- 요청의 Content-Type 헤더 값을 매핑 조건으로 지정하는 경우에는 consumes 속성을 사용한다.
	 */
	
	// consumes 속성값을 지정하지 않으면 기본값으로 "application/json" 미디어 타입으로 지정된다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.POST)
	public ResponseEntity<String> modifyContentType(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyContentType() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
}

- http://localhost/board/ajaxHome


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AjaxHome</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h3>AJAX HOME</h3>

		<hr />
		
		<form action="" method="get">
			boardNo : <input type="text" name="boardNo" id="boardNo" /><br />
			title : <input type="text" name="title" id="title" /><br />
			content : <textarea rows="20" cols="50" name="content" id="content"></textarea><br />
			writer : <input type="text" name="writer" id="writer" /><br />
			<input type="button" id="btn" value="전송" />
		</form>
		
		<br />
		
		<div>
		
			<h3>Headers 매핑</h3>
			<button id="putBtn" type="button">MODIFY(PUT)</button>
			<button id="putHeaderBtn" type="button">MODIFY(PUT With Header)</button>
			
			<br />
			
			<h3>Content Type 매핑</h3>
			<button id="postBtn" type="button">MODIFY(POST)</button>
			<button id="putJsonBtn" type="button">MODIFY(PUT JSON)</button>
			<button id="putXMLBtn" type="button">MODIFY(PUT XML)</button>
			
		</div>
	</body>
	
	<script type="text/javascript">
		$(function(){
			
			// Headers 매핑
			var putBtn = $("#putBtn");				// 버튼 putBtn Element
			var putHeaderBtn = $("#putHeaderBtn");	// 버튼 putHeaderBtn Element
			
			// Content Type 매핑
			var postBtn = $("#postBtn");			// 버튼 postBtn Element
			var putJsonBtn = $("#putJsonBtn");		// 버튼 putJsonBtn Element
			var putXMLBtn = $("#putXMLBtn");		// 버튼 putXMLBtn Element
			
			// Headers 매핑 시작 --------------------------------------
			putBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				// 비동기 처리
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// 강력한 equals
						// 값과 타입과 hash까지 일치하는지를 검증
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putHeaderBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					headers : {
						"X-HTTP-Method-Override" : "PUT"
					},
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Headers 매핑 끝 --------------------------------------
			
			// Content Type 매핑 시작 --------------------------------------
			postBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "post",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putJsonBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putXMLBtn.on("click", function(){
				
			});
			// Content Type 매핑 끝 --------------------------------------
			
		});
	</script>
	
</html>
package kr.or.ddit.controller.board;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.vo.Board;

@Controller
@RequestMapping("/board")
public class BoardController {

	/*
	 * [ 3장 : 컨트롤러 요청 매핑 ]
	 * 
	 * 		1. 요청 경로 매핑
	 * 
	 * 			- @RequestMapping의 value 속성에 요청 경로를 설정한다.
	 * 			- 요청 경로는 반드시 설정해야 하는 필수 정보이다.
	 * 			- 속성이 하나일 때는 속성명을 생략할 수 있다. (default는 value)
	 * 			- 컨트롤러의 클래스 레벨과 메서드 레벨로 지정할 수 있다.
	 * 			- 클래스 레벨로 요청 경로를 지정하면 메서드 레벨에서 지정한 경로의 기본 경로로 취급된다.
	 * 			- 클래스 레벨의 요청 경로에 메서드 레벨의 요청 경로를 덧붙인 형태가 최종 경로가 된다.
	 */
	
	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	
	@RequestMapping(value = "/register")
	public void registerForm() {
		log.info("registerForm() 실행...!");
	}
	
	@RequestMapping(value = "/modify")
	public void modifyForm() {
		log.info("modifyForm() 실행...!");
	}
	
	@RequestMapping(value = "/list")
	public void list() {
		log.info("list() 실행...!");
	}
	
	/*
	 * 		2. 경로 패턴 매핑
	 * 
	 * 			- 요청 경로를 동적으로 표현이 가능한 경로 패턴을 지정할 수 있다.
	 * 			- URL 경로 상의 변하는 값을 경로 변수로 취급한다.
	 * 			- 경로 변수에 해당하는 값을 파라미터 변수에 설정할 수 있다.
	 */
	
	@RequestMapping(value = "/read/{boardNo}")
	public String read(@PathVariable("boardNo") int boardNo) {
		log.info("read() 실행...!");
		log.info("경로 상의 포함된 boardNo : " + boardNo);
		return "board/read";
	}
	
	/*
	 *		3. HTTP 메서드 매핑
	 *
	 *			- method 속성을 사용하여 HTTP 메서드를 매핑 조건으로 지정할 수 있다.
	 *			- 화면으로 응답하는 경우에는 HTTP 메서드로 GET방식과 POST방식 두 가지를 사용할 수 있다.
	 */
	
	// HTTP 메서드 매핑 실행 페이지
	
	@RequestMapping(value = "/formHome", method = RequestMethod.GET)
	public String formHome() {
		log.info("formHome() 실행...!");
		return "formHome";
	}
	
	// register 경로에 GET 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.GET)
	public String registerFormHttp() {
		log.info("registerFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// register 경로에 POST 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.POST)
	public String registerHttp() {
		log.info("registerHttp() 실행...!");
		return "success";
	}
	
	// modify 경로에  GET 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.GET)
	public String modifyFormHttp() {
		log.info("modifyFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// modify 경로에 POST 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.POST)
	public String modifyHttp() {
		log.info("modifyHttp() 실행...!");
		return "success";
	}
	
	// remove 경로에 POST 방식
	@RequestMapping(value = "/http/remove", method = RequestMethod.POST)
	public String removeHttp() {
		log.info("removeHttp() 실행...!");
		return "success";
	}
	
	// list 경로에 GET 방식
	@RequestMapping(value = "/http/list", method = RequestMethod.GET)
	public String listHttp() {
		log.info("listHttp() 실행...!");
		return "success";
	}
	
	/*
	 * 		4. Params 매핑
	 * 
	 * 			- 요청 파라미터를 매핑 조건으로 지정하는 경우에는 params 속성을 사용한다.
	 * 			- 버튼이나 링크에 따라 호출할 메서드를 바꿔야 할 때 사용한다.
	 * 
	 * 			** Params 매핑 테스트 페이지
	 * 				> board/list.jsp
	 * 				> board/modify.jsp
	 * 				> board/read.jsp
	 * 				> board/register.jsp
	 * 				> board/remove.jsp
	 */
	
	// /board/get 경로, GET 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "register")
	public String registerFormParamsGet() {
		log.info("registerFormParamsGet() 실행...!");
		return "board/register";
	}
	
	// /board/post 경로, POST 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "register")
	public String registerParamsPost() {
		log.info("registerParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "modify")
	public String modifyFormParamsGet() {
		log.info("modifyFormParamsGet() 실행...!");
		return "board/modify";
	}
	
	// /board/post 경로, POST 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "modify")
	public String modifyParamsPost() {
		log.info("modifyParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "remove")
	public String removeFormParamsGet() {
		log.info("removeFormParamsGet() 실행...!");
		return "board/remove";
	}
	
	// /board/post 경로, POST 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "remove")
	public String removeParamsPost() {
		log.info("removeParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/list 경로, GET 방식, "list" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "list")
	public String listParamsGet() {
		log.info("listParamsGet() 실행...!");
		return "board/list";
	}
	
	// /board/read 경로, GET 방식, "read" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "read")
	public String readParamsGet() {
		log.info("readParamsGet() 실행...!");
		return "board/read";
	}
	
	/*
	 * 		5. Headers 매핑
	 * 
	 * 			- 요청 헤더를 매핑 조건으로 지정하는 경우에는 headers 속성을 사용한다.
	 */
	
	// Headers 매핑을 테스트할 페이지
	@RequestMapping(value = "/ajaxHome", method = RequestMethod.GET)
	public String ajaxHome() {
		log.info("ajaxHome() 실행...!");
		return "ajaxHome";
	}
	
	// Headers 매핑이지만, headers 설정을 하지 않고 요청
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT)
	public ResponseEntity<String> modifyPut(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board) {
		
		log.info("modifyPut() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
	}
	
	// headers 속성에 설정되어 있는 header 정보를 매핑으로 요청
	// header 속성에 'X-HTTP-Method-Override=PUT' 정보가 들어 있는 요청은 이곳으로 들어옴
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, headers = "X-HTTP-Method-Override=PUT")
	public ResponseEntity<String> modifyByHeader(@PathVariable int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByHeader() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	/*
	 * 		6. Content Type 매핑
	 * 
	 * 			- 요청의 Content-Type 헤더 값을 매핑 조건으로 지정하는 경우에는 consumes 속성을 사용한다.
	 */
	
	// consumes 속성값을 지정하지 않으면 기본값으로 "application/json" 미디어 타입으로 지정된다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.POST)
	public ResponseEntity<String> modifyContentType(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyContentType() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	// consume 속성 값에 "application/json"의 미디어 타입을 지정한다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, consumes = "application/json")
	public ResponseEntity<String> modifyByJson(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByJson() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
}

- http://localhost/board/ajaxHome


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AjaxHome</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h3>AJAX HOME</h3>

		<hr />
		
		<form action="" method="get">
			boardNo : <input type="text" name="boardNo" id="boardNo" /><br />
			title : <input type="text" name="title" id="title" /><br />
			content : <textarea rows="20" cols="50" name="content" id="content"></textarea><br />
			writer : <input type="text" name="writer" id="writer" /><br />
			<input type="button" id="btn" value="전송" />
		</form>
		
		<br />
		
		<div>
		
			<h3>Headers 매핑</h3>
			<button id="putBtn" type="button">MODIFY(PUT)</button>
			<button id="putHeaderBtn" type="button">MODIFY(PUT With Header)</button>
			
			<br />
			
			<h3>Content Type 매핑</h3>
			<button id="postBtn" type="button">MODIFY(POST)</button>
			<button id="putJsonBtn" type="button">MODIFY(PUT JSON)</button>
			<button id="putXMLBtn" type="button">MODIFY(PUT XML)</button>
			
		</div>
	</body>
	
	<script type="text/javascript">
		$(function(){
			
			// Headers 매핑
			var putBtn = $("#putBtn");				// 버튼 putBtn Element
			var putHeaderBtn = $("#putHeaderBtn");	// 버튼 putHeaderBtn Element
			
			// Content Type 매핑
			var postBtn = $("#postBtn");			// 버튼 postBtn Element
			var putJsonBtn = $("#putJsonBtn");		// 버튼 putJsonBtn Element
			var putXMLBtn = $("#putXMLBtn");		// 버튼 putXMLBtn Element
			
			// Headers 매핑 시작 --------------------------------------
			putBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				// 비동기 처리
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// 강력한 equals
						// 값과 타입과 hash까지 일치하는지를 검증
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putHeaderBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					headers : {
						"X-HTTP-Method-Override" : "PUT"
					},
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Headers 매핑 끝 --------------------------------------
			
			// Content Type 매핑 시작 --------------------------------------
			postBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "post",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putJsonBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putXMLBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var xmlData = "";
				xmlData += "<Board>";
				xmlData += "<boardNo>" + boardNo + "</boardNo>";
				xmlData += "<title>" + title + "</title>";
				xmlData += "<content>" + content + "</content>";
				xmlData += "<writer>" + writer + "</writer>";
				xmlData += "</Board>";
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : xmlData,
					contentType : "application/xml; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Content Type 매핑 끝 --------------------------------------
			
		});
	</script>
	
</html>

[pom.xml]

		<!-- xml 데이터 바인딩을 위한 의존 라이브러리 -->
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
			<version>2.9.5</version>
		</dependency>


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AjaxHome</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h3>AJAX HOME</h3>

		<hr />
		
		<form action="" method="get">
			boardNo : <input type="text" name="boardNo" id="boardNo" /><br />
			title : <input type="text" name="title" id="title" /><br />
			content : <textarea rows="20" cols="50" name="content" id="content"></textarea><br />
			writer : <input type="text" name="writer" id="writer" /><br />
			<input type="button" id="btn" value="전송" />
		</form>
		
		<br />
		
		<div>
		
			<h3>Headers 매핑</h3>
			<button id="putBtn" type="button">MODIFY(PUT)</button>
			<button id="putHeaderBtn" type="button">MODIFY(PUT With Header)</button>
			
			<br />
			
			<h3>Content Type 매핑</h3>
			<button id="postBtn" type="button">MODIFY(POST)</button>
			<button id="putJsonBtn" type="button">MODIFY(PUT JSON)</button>
			<button id="putXMLBtn" type="button">MODIFY(PUT XML)</button>
			
			<br />
			
			<h3>Accept 매핑</h3>
			<button id="getBtn" type="button">READ</button>
			<button id="getJsonBtn" type="button">READ(JSON)</button>
			<button id="getXMLBtn" type="button">READ(XML)</button>
			
		</div>
	</body>
	
	<script type="text/javascript">
		$(function(){
			
			// Headers 매핑
			var putBtn = $("#putBtn");				// 버튼 putBtn Element
			var putHeaderBtn = $("#putHeaderBtn");	// 버튼 putHeaderBtn Element
			
			// Content Type 매핑
			var postBtn = $("#postBtn");			// 버튼 postBtn Element
			var putJsonBtn = $("#putJsonBtn");		// 버튼 putJsonBtn Element
			var putXMLBtn = $("#putXMLBtn");		// 버튼 putXMLBtn Element
			
			// Accept 매핑
			var getBtn = $("#getBtn");				// 버튼 getBtn Element
			var getJsonBtn = $("#getJsonBtn");		// 버튼 getJsonBtn Element
			var getXMLBtn = $("#getXMLBtn");		// 버튼 getXMLBtn Element
			
			// Headers 매핑 시작 --------------------------------------
			putBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				// 비동기 처리
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// 강력한 equals
						// 값과 타입과 hash까지 일치하는지를 검증
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putHeaderBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					headers : {
						"X-HTTP-Method-Override" : "PUT"
					},
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Headers 매핑 끝 --------------------------------------
			
			// Content Type 매핑 시작 --------------------------------------
			postBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "post",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putJsonBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putXMLBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var xmlData = "";
				xmlData += "<Board>";
				xmlData += "<boardNo>" + boardNo + "</boardNo>";
				xmlData += "<title>" + title + "</title>";
				xmlData += "<content>" + content + "</content>";
				xmlData += "<writer>" + writer + "</writer>";
				xmlData += "</Board>";
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : xmlData,
					contentType : "application/xml; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Content Type 매핑 끝 --------------------------------------
			
			// Accept 매핑 시작 --------------------------------------
			getBtn.on("click", function(){
				var boardNo = $("#boardNo").val();
				
				// GET 방식 비동기 HTTP 요청 수행
				$.get("/board/" + boardNo, function(data){
					console.log(data);
					alert(JSON.stringify(data));
				});
			});
			
			getJsonBtn.on("click", function(){
				
			});
			
			getXMLBtn.on("click", function(){
				
			});
			// Accept 매핑 끝 --------------------------------------
			
		});
	</script>
	
</html>
package kr.or.ddit.controller.board;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.vo.Board;

@Controller
@RequestMapping("/board")
public class BoardController {

	/*
	 * [ 3장 : 컨트롤러 요청 매핑 ]
	 * 
	 * 		1. 요청 경로 매핑
	 * 
	 * 			- @RequestMapping의 value 속성에 요청 경로를 설정한다.
	 * 			- 요청 경로는 반드시 설정해야 하는 필수 정보이다.
	 * 			- 속성이 하나일 때는 속성명을 생략할 수 있다. (default는 value)
	 * 			- 컨트롤러의 클래스 레벨과 메서드 레벨로 지정할 수 있다.
	 * 			- 클래스 레벨로 요청 경로를 지정하면 메서드 레벨에서 지정한 경로의 기본 경로로 취급된다.
	 * 			- 클래스 레벨의 요청 경로에 메서드 레벨의 요청 경로를 덧붙인 형태가 최종 경로가 된다.
	 */
	
	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	
	@RequestMapping(value = "/register")
	public void registerForm() {
		log.info("registerForm() 실행...!");
	}
	
	@RequestMapping(value = "/modify")
	public void modifyForm() {
		log.info("modifyForm() 실행...!");
	}
	
	@RequestMapping(value = "/list")
	public void list() {
		log.info("list() 실행...!");
	}
	
	/*
	 * 		2. 경로 패턴 매핑
	 * 
	 * 			- 요청 경로를 동적으로 표현이 가능한 경로 패턴을 지정할 수 있다.
	 * 			- URL 경로 상의 변하는 값을 경로 변수로 취급한다.
	 * 			- 경로 변수에 해당하는 값을 파라미터 변수에 설정할 수 있다.
	 */
	
	@RequestMapping(value = "/read/{boardNo}")
	public String read(@PathVariable("boardNo") int boardNo) {
		log.info("read() 실행...!");
		log.info("경로 상의 포함된 boardNo : " + boardNo);
		return "board/read";
	}
	
	/*
	 *		3. HTTP 메서드 매핑
	 *
	 *			- method 속성을 사용하여 HTTP 메서드를 매핑 조건으로 지정할 수 있다.
	 *			- 화면으로 응답하는 경우에는 HTTP 메서드로 GET방식과 POST방식 두 가지를 사용할 수 있다.
	 */
	
	// HTTP 메서드 매핑 실행 페이지
	
	@RequestMapping(value = "/formHome", method = RequestMethod.GET)
	public String formHome() {
		log.info("formHome() 실행...!");
		return "formHome";
	}
	
	// register 경로에 GET 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.GET)
	public String registerFormHttp() {
		log.info("registerFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// register 경로에 POST 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.POST)
	public String registerHttp() {
		log.info("registerHttp() 실행...!");
		return "success";
	}
	
	// modify 경로에  GET 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.GET)
	public String modifyFormHttp() {
		log.info("modifyFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// modify 경로에 POST 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.POST)
	public String modifyHttp() {
		log.info("modifyHttp() 실행...!");
		return "success";
	}
	
	// remove 경로에 POST 방식
	@RequestMapping(value = "/http/remove", method = RequestMethod.POST)
	public String removeHttp() {
		log.info("removeHttp() 실행...!");
		return "success";
	}
	
	// list 경로에 GET 방식
	@RequestMapping(value = "/http/list", method = RequestMethod.GET)
	public String listHttp() {
		log.info("listHttp() 실행...!");
		return "success";
	}
	
	/*
	 * 		4. Params 매핑
	 * 
	 * 			- 요청 파라미터를 매핑 조건으로 지정하는 경우에는 params 속성을 사용한다.
	 * 			- 버튼이나 링크에 따라 호출할 메서드를 바꿔야 할 때 사용한다.
	 * 
	 * 			** Params 매핑 테스트 페이지
	 * 				> board/list.jsp
	 * 				> board/modify.jsp
	 * 				> board/read.jsp
	 * 				> board/register.jsp
	 * 				> board/remove.jsp
	 */
	
	// /board/get 경로, GET 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "register")
	public String registerFormParamsGet() {
		log.info("registerFormParamsGet() 실행...!");
		return "board/register";
	}
	
	// /board/post 경로, POST 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "register")
	public String registerParamsPost() {
		log.info("registerParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "modify")
	public String modifyFormParamsGet() {
		log.info("modifyFormParamsGet() 실행...!");
		return "board/modify";
	}
	
	// /board/post 경로, POST 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "modify")
	public String modifyParamsPost() {
		log.info("modifyParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "remove")
	public String removeFormParamsGet() {
		log.info("removeFormParamsGet() 실행...!");
		return "board/remove";
	}
	
	// /board/post 경로, POST 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "remove")
	public String removeParamsPost() {
		log.info("removeParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/list 경로, GET 방식, "list" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "list")
	public String listParamsGet() {
		log.info("listParamsGet() 실행...!");
		return "board/list";
	}
	
	// /board/read 경로, GET 방식, "read" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "read")
	public String readParamsGet() {
		log.info("readParamsGet() 실행...!");
		return "board/read";
	}
	
	/*
	 * 		5. Headers 매핑
	 * 
	 * 			- 요청 헤더를 매핑 조건으로 지정하는 경우에는 headers 속성을 사용한다.
	 */
	
	// Headers 매핑을 테스트할 페이지
	@RequestMapping(value = "/ajaxHome", method = RequestMethod.GET)
	public String ajaxHome() {
		log.info("ajaxHome() 실행...!");
		return "ajaxHome";
	}
	
	// Headers 매핑이지만, headers 설정을 하지 않고 요청
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT)
	public ResponseEntity<String> modifyPut(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board) {
		
		log.info("modifyPut() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
	}
	
	// headers 속성에 설정되어 있는 header 정보를 매핑으로 요청
	// header 속성에 'X-HTTP-Method-Override=PUT' 정보가 들어 있는 요청은 이곳으로 들어옴
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, headers = "X-HTTP-Method-Override=PUT")
	public ResponseEntity<String> modifyByHeader(@PathVariable int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByHeader() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	/*
	 * 		6. Content Type 매핑
	 * 
	 * 			- 요청의 Content-Type 헤더 값을 매핑 조건으로 지정하는 경우에는 consumes 속성을 사용한다.
	 */
	
	// consumes 속성값을 지정하지 않으면 기본값으로 "application/json" 미디어 타입으로 지정된다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.POST)
	public ResponseEntity<String> modifyContentType(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyContentType() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	// consume 속성 값에 "application/json"의 미디어 타입을 지정한다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, consumes = "application/json")
	public ResponseEntity<String> modifyByJson(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByJson() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, consumes = "application/xml")
	public ResponseEntity<String> modifyByXml(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByXml() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	/*
	 * 		7. Accept 매핑
	 * 
	 * 			- 요청 Accept 헤더 값을 매핑 조건으로 지정하는 경우에는 produces 속성을 사용한다.
	 */
	
	// produces 속성값을 지정하지 않으면 기본값인 "application/json" 미디어 타입으로 지정된다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.GET)
	public ResponseEntity<Board> readAccept(@PathVariable("boardNo") int boardNo){
		
		log.info("readAccept() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		
		Board board = new Board();
		board.setTitle("제목입니다");
		board.setContent("내용입니다");
		board.setWriter("a001");
		
		return new ResponseEntity<Board>(board, HttpStatus.OK);
		
	}
	
}

[pom.xml] 에서 주석처리 해야 함

		<!-- xml 데이터 바인딩을 위한 의존 라이브러리 -->
		<!-- <dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
			<version>2.9.5</version>
		</dependency> -->

- http://localhost/board/ajaxHome


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AjaxHome</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h3>AJAX HOME</h3>

		<hr />
		
		<form action="" method="get">
			boardNo : <input type="text" name="boardNo" id="boardNo" /><br />
			title : <input type="text" name="title" id="title" /><br />
			content : <textarea rows="20" cols="50" name="content" id="content"></textarea><br />
			writer : <input type="text" name="writer" id="writer" /><br />
			<input type="button" id="btn" value="전송" />
		</form>
		
		<br />
		
		<div>
		
			<h3>Headers 매핑</h3>
			<button id="putBtn" type="button">MODIFY(PUT)</button>
			<button id="putHeaderBtn" type="button">MODIFY(PUT With Header)</button>
			
			<br />
			
			<h3>Content Type 매핑</h3>
			<button id="postBtn" type="button">MODIFY(POST)</button>
			<button id="putJsonBtn" type="button">MODIFY(PUT JSON)</button>
			<button id="putXMLBtn" type="button">MODIFY(PUT XML)</button>
			
			<br />
			
			<h3>Accept 매핑</h3>
			<button id="getBtn" type="button">READ</button>
			<button id="getJsonBtn" type="button">READ(JSON)</button>
			<button id="getXMLBtn" type="button">READ(XML)</button>
			
		</div>
	</body>
	
	<script type="text/javascript">
		$(function(){
			
			// Headers 매핑
			var putBtn = $("#putBtn");				// 버튼 putBtn Element
			var putHeaderBtn = $("#putHeaderBtn");	// 버튼 putHeaderBtn Element
			
			// Content Type 매핑
			var postBtn = $("#postBtn");			// 버튼 postBtn Element
			var putJsonBtn = $("#putJsonBtn");		// 버튼 putJsonBtn Element
			var putXMLBtn = $("#putXMLBtn");		// 버튼 putXMLBtn Element
			
			// Accept 매핑
			var getBtn = $("#getBtn");				// 버튼 getBtn Element
			var getJsonBtn = $("#getJsonBtn");		// 버튼 getJsonBtn Element
			var getXMLBtn = $("#getXMLBtn");		// 버튼 getXMLBtn Element
			
			// Headers 매핑 시작 --------------------------------------
			putBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				// 비동기 처리
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// 강력한 equals
						// 값과 타입과 hash까지 일치하는지를 검증
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putHeaderBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					headers : {
						"X-HTTP-Method-Override" : "PUT"
					},
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Headers 매핑 끝 --------------------------------------
			
			// Content Type 매핑 시작 --------------------------------------
			postBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "post",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putJsonBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putXMLBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var xmlData = "";
				xmlData += "<Board>";
				xmlData += "<boardNo>" + boardNo + "</boardNo>";
				xmlData += "<title>" + title + "</title>";
				xmlData += "<content>" + content + "</content>";
				xmlData += "<writer>" + writer + "</writer>";
				xmlData += "</Board>";
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : xmlData,
					contentType : "application/xml; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Content Type 매핑 끝 --------------------------------------
			
			// Accept 매핑 시작 --------------------------------------
			getBtn.on("click", function(){
				var boardNo = $("#boardNo").val();
				
				// GET 방식 비동기 HTTP 요청 수행
				$.get("/board/" + boardNo, function(data){
					console.log(data);
					alert(JSON.stringify(data));
				});
			});
			
			getJsonBtn.on("click", function(){
				var boardNo = $("#boardNo").val();
				
				$.ajax({
					type : "get",
					url : "/board/" + boardNo,
					headers : {
						"Accept" : "application/json"
					},
					success : function(result) {
						console.log(result);
						alert(JSON.stringify(result));
					}
				});
			});
			
			getXMLBtn.on("click", function(){
				
			});
			// Accept 매핑 끝 --------------------------------------
			
		});
	</script>
	
</html>
package kr.or.ddit.controller.board;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.vo.Board;

@Controller
@RequestMapping("/board")
public class BoardController {

	/*
	 * [ 3장 : 컨트롤러 요청 매핑 ]
	 * 
	 * 		1. 요청 경로 매핑
	 * 
	 * 			- @RequestMapping의 value 속성에 요청 경로를 설정한다.
	 * 			- 요청 경로는 반드시 설정해야 하는 필수 정보이다.
	 * 			- 속성이 하나일 때는 속성명을 생략할 수 있다. (default는 value)
	 * 			- 컨트롤러의 클래스 레벨과 메서드 레벨로 지정할 수 있다.
	 * 			- 클래스 레벨로 요청 경로를 지정하면 메서드 레벨에서 지정한 경로의 기본 경로로 취급된다.
	 * 			- 클래스 레벨의 요청 경로에 메서드 레벨의 요청 경로를 덧붙인 형태가 최종 경로가 된다.
	 */
	
	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	
	@RequestMapping(value = "/register")
	public void registerForm() {
		log.info("registerForm() 실행...!");
	}
	
	@RequestMapping(value = "/modify")
	public void modifyForm() {
		log.info("modifyForm() 실행...!");
	}
	
	@RequestMapping(value = "/list")
	public void list() {
		log.info("list() 실행...!");
	}
	
	/*
	 * 		2. 경로 패턴 매핑
	 * 
	 * 			- 요청 경로를 동적으로 표현이 가능한 경로 패턴을 지정할 수 있다.
	 * 			- URL 경로 상의 변하는 값을 경로 변수로 취급한다.
	 * 			- 경로 변수에 해당하는 값을 파라미터 변수에 설정할 수 있다.
	 */
	
	@RequestMapping(value = "/read/{boardNo}")
	public String read(@PathVariable("boardNo") int boardNo) {
		log.info("read() 실행...!");
		log.info("경로 상의 포함된 boardNo : " + boardNo);
		return "board/read";
	}
	
	/*
	 *		3. HTTP 메서드 매핑
	 *
	 *			- method 속성을 사용하여 HTTP 메서드를 매핑 조건으로 지정할 수 있다.
	 *			- 화면으로 응답하는 경우에는 HTTP 메서드로 GET방식과 POST방식 두 가지를 사용할 수 있다.
	 */
	
	// HTTP 메서드 매핑 실행 페이지
	
	@RequestMapping(value = "/formHome", method = RequestMethod.GET)
	public String formHome() {
		log.info("formHome() 실행...!");
		return "formHome";
	}
	
	// register 경로에 GET 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.GET)
	public String registerFormHttp() {
		log.info("registerFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// register 경로에 POST 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.POST)
	public String registerHttp() {
		log.info("registerHttp() 실행...!");
		return "success";
	}
	
	// modify 경로에  GET 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.GET)
	public String modifyFormHttp() {
		log.info("modifyFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// modify 경로에 POST 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.POST)
	public String modifyHttp() {
		log.info("modifyHttp() 실행...!");
		return "success";
	}
	
	// remove 경로에 POST 방식
	@RequestMapping(value = "/http/remove", method = RequestMethod.POST)
	public String removeHttp() {
		log.info("removeHttp() 실행...!");
		return "success";
	}
	
	// list 경로에 GET 방식
	@RequestMapping(value = "/http/list", method = RequestMethod.GET)
	public String listHttp() {
		log.info("listHttp() 실행...!");
		return "success";
	}
	
	/*
	 * 		4. Params 매핑
	 * 
	 * 			- 요청 파라미터를 매핑 조건으로 지정하는 경우에는 params 속성을 사용한다.
	 * 			- 버튼이나 링크에 따라 호출할 메서드를 바꿔야 할 때 사용한다.
	 * 
	 * 			** Params 매핑 테스트 페이지
	 * 				> board/list.jsp
	 * 				> board/modify.jsp
	 * 				> board/read.jsp
	 * 				> board/register.jsp
	 * 				> board/remove.jsp
	 */
	
	// /board/get 경로, GET 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "register")
	public String registerFormParamsGet() {
		log.info("registerFormParamsGet() 실행...!");
		return "board/register";
	}
	
	// /board/post 경로, POST 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "register")
	public String registerParamsPost() {
		log.info("registerParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "modify")
	public String modifyFormParamsGet() {
		log.info("modifyFormParamsGet() 실행...!");
		return "board/modify";
	}
	
	// /board/post 경로, POST 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "modify")
	public String modifyParamsPost() {
		log.info("modifyParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "remove")
	public String removeFormParamsGet() {
		log.info("removeFormParamsGet() 실행...!");
		return "board/remove";
	}
	
	// /board/post 경로, POST 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "remove")
	public String removeParamsPost() {
		log.info("removeParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/list 경로, GET 방식, "list" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "list")
	public String listParamsGet() {
		log.info("listParamsGet() 실행...!");
		return "board/list";
	}
	
	// /board/read 경로, GET 방식, "read" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "read")
	public String readParamsGet() {
		log.info("readParamsGet() 실행...!");
		return "board/read";
	}
	
	/*
	 * 		5. Headers 매핑
	 * 
	 * 			- 요청 헤더를 매핑 조건으로 지정하는 경우에는 headers 속성을 사용한다.
	 */
	
	// Headers 매핑을 테스트할 페이지
	@RequestMapping(value = "/ajaxHome", method = RequestMethod.GET)
	public String ajaxHome() {
		log.info("ajaxHome() 실행...!");
		return "ajaxHome";
	}
	
	// Headers 매핑이지만, headers 설정을 하지 않고 요청
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT)
	public ResponseEntity<String> modifyPut(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board) {
		
		log.info("modifyPut() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
	}
	
	// headers 속성에 설정되어 있는 header 정보를 매핑으로 요청
	// header 속성에 'X-HTTP-Method-Override=PUT' 정보가 들어 있는 요청은 이곳으로 들어옴
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, headers = "X-HTTP-Method-Override=PUT")
	public ResponseEntity<String> modifyByHeader(@PathVariable int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByHeader() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	/*
	 * 		6. Content Type 매핑
	 * 
	 * 			- 요청의 Content-Type 헤더 값을 매핑 조건으로 지정하는 경우에는 consumes 속성을 사용한다.
	 */
	
	// consumes 속성값을 지정하지 않으면 기본값으로 "application/json" 미디어 타입으로 지정된다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.POST)
	public ResponseEntity<String> modifyContentType(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyContentType() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	// consume 속성 값에 "application/json"의 미디어 타입을 지정한다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, consumes = "application/json")
	public ResponseEntity<String> modifyByJson(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByJson() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, consumes = "application/xml")
	public ResponseEntity<String> modifyByXml(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByXml() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	/*
	 * 		7. Accept 매핑
	 * 
	 * 			- 요청 Accept 헤더 값을 매핑 조건으로 지정하는 경우에는 produces 속성을 사용한다.
	 */
	
	// produces 속성값을 지정하지 않으면 기본값인 "application/json" 미디어 타입으로 지정된다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.GET)
	public ResponseEntity<Board> readAccept(@PathVariable("boardNo") int boardNo){
		
		log.info("readAccept() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		
		Board board = new Board();
		board.setTitle("제목입니다");
		board.setContent("내용입니다");
		board.setWriter("a001");
		
		return new ResponseEntity<Board>(board, HttpStatus.OK);
		
	}
	
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.GET, produces = "application/json")
	public ResponseEntity<Board> readToJson(@PathVariable("boardNo") int boardNo){
		
		log.info("readToJson() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		
		String addStr = "_json";
		Board board = new Board();
		board.setTitle("제목입니다" + addStr);
		board.setContent("내용입니다" + addStr);
		board.setWriter("a001" + addStr);
		
		return new ResponseEntity<Board>(board, HttpStatus.OK);
		
	}
	
}

- http://localhost/board/ajaxHome


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>AjaxHome</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
	</head>
	<body>
		<h3>AJAX HOME</h3>

		<hr />
		
		<form action="" method="get">
			boardNo : <input type="text" name="boardNo" id="boardNo" /><br />
			title : <input type="text" name="title" id="title" /><br />
			content : <textarea rows="20" cols="50" name="content" id="content"></textarea><br />
			writer : <input type="text" name="writer" id="writer" /><br />
			<input type="button" id="btn" value="전송" />
		</form>
		
		<br />
		
		<div>
		
			<h3>Headers 매핑</h3>
			<button id="putBtn" type="button">MODIFY(PUT)</button>
			<button id="putHeaderBtn" type="button">MODIFY(PUT With Header)</button>
			
			<br />
			
			<h3>Content Type 매핑</h3>
			<button id="postBtn" type="button">MODIFY(POST)</button>
			<button id="putJsonBtn" type="button">MODIFY(PUT JSON)</button>
			<button id="putXMLBtn" type="button">MODIFY(PUT XML)</button>
			
			<br />
			
			<h3>Accept 매핑</h3>
			<button id="getBtn" type="button">READ</button>
			<button id="getJsonBtn" type="button">READ(JSON)</button>
			<button id="getXMLBtn" type="button">READ(XML)</button>
			
		</div>
	</body>
	
	<script type="text/javascript">
		$(function(){
			
			// Headers 매핑
			var putBtn = $("#putBtn");				// 버튼 putBtn Element
			var putHeaderBtn = $("#putHeaderBtn");	// 버튼 putHeaderBtn Element
			
			// Content Type 매핑
			var postBtn = $("#postBtn");			// 버튼 postBtn Element
			var putJsonBtn = $("#putJsonBtn");		// 버튼 putJsonBtn Element
			var putXMLBtn = $("#putXMLBtn");		// 버튼 putXMLBtn Element
			
			// Accept 매핑
			var getBtn = $("#getBtn");				// 버튼 getBtn Element
			var getJsonBtn = $("#getJsonBtn");		// 버튼 getJsonBtn Element
			var getXMLBtn = $("#getXMLBtn");		// 버튼 getXMLBtn Element
			
			// Headers 매핑 시작 --------------------------------------
			putBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				// 비동기 처리
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// 강력한 equals
						// 값과 타입과 hash까지 일치하는지를 검증
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putHeaderBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					headers : {
						"X-HTTP-Method-Override" : "PUT"
					},
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Headers 매핑 끝 --------------------------------------
			
			// Content Type 매핑 시작 --------------------------------------
			postBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "post",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putJsonBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var boardObject = {
					boardNo : boardNo,
					title : title,
					content : content,
					writer : writer,
				};
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : JSON.stringify(boardObject),
					contentType : "application/json; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			
			putXMLBtn.on("click", function(){
				var boardNo = $("#boardNo").val();		// 번호 데이터
				var title = $("#title").val();			// 제목 데이터
				var content = $("#content").val();		// 내용 데이터
				var writer = $("#writer").val();		// 작성자 데이터
				
				var xmlData = "";
				xmlData += "<Board>";
				xmlData += "<boardNo>" + boardNo + "</boardNo>";
				xmlData += "<title>" + title + "</title>";
				xmlData += "<content>" + content + "</content>";
				xmlData += "<writer>" + writer + "</writer>";
				xmlData += "</Board>";
				
				$.ajax({
					type : "put",
					url : "/board/" + boardNo,
					data : xmlData,
					contentType : "application/xml; charset=utf-8",
					success : function(result) {
						console.log("result : " + result);
						// '==' : Equals Operator
						// '===' : Strict Equals Operator
						// '==='는 값을 더 엄격하게 비교할 때 사용한다.
						if(result === "SUCCESS") {
							alert(result);
						}
					}
				});
			});
			// Content Type 매핑 끝 --------------------------------------
			
			// Accept 매핑 시작 --------------------------------------
			getBtn.on("click", function(){
				var boardNo = $("#boardNo").val();
				
				// GET 방식 비동기 HTTP 요청 수행
				$.get("/board/" + boardNo, function(data){
					console.log(data);
					alert(JSON.stringify(data));
				});
			});
			
			getJsonBtn.on("click", function(){
				var boardNo = $("#boardNo").val();
				
				$.ajax({
					type : "get",
					url : "/board/" + boardNo,
					headers : {
						"Accept" : "application/json"
					},
					success : function(result) {
						console.log(result);
						alert(JSON.stringify(result));
					}
				});
			});
			
			getXMLBtn.on("click", function(){
				var boardNo = $("#boardNo").val();
				
				$.ajax({
					type : "get",
					url : "/board/" + boardNo,
					headers : {
						"Accept" : "application/xml"
					},
					success : function(result) {
						console.log(result);
						alert(xmlToString(result));
					}
				});
			});
			// Accept 매핑 끝 --------------------------------------
			
		});
		
		function xmlToString(xmlData){
			var xmlString;
			
			// window.ActiveXObject는 ActiveXObject를 지원하는 브라우저라면
			// Object를 리턴하고 그렇지 않다면 null을 리턴한다.
			if(window.ActiveXObject){
				xmlString = xmlData.xml;
			}else {
				xmlString = (new XMLSerializer()).serializeToString(xmlData);
			}
			return xmlString;
		}
	</script>
	
</html>
package kr.or.ddit.controller.board;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import kr.or.ddit.vo.Board;

@Controller
@RequestMapping("/board")
public class BoardController {

	/*
	 * [ 3장 : 컨트롤러 요청 매핑 ]
	 * 
	 * 		1. 요청 경로 매핑
	 * 
	 * 			- @RequestMapping의 value 속성에 요청 경로를 설정한다.
	 * 			- 요청 경로는 반드시 설정해야 하는 필수 정보이다.
	 * 			- 속성이 하나일 때는 속성명을 생략할 수 있다. (default는 value)
	 * 			- 컨트롤러의 클래스 레벨과 메서드 레벨로 지정할 수 있다.
	 * 			- 클래스 레벨로 요청 경로를 지정하면 메서드 레벨에서 지정한 경로의 기본 경로로 취급된다.
	 * 			- 클래스 레벨의 요청 경로에 메서드 레벨의 요청 경로를 덧붙인 형태가 최종 경로가 된다.
	 */
	
	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	
	@RequestMapping(value = "/register")
	public void registerForm() {
		log.info("registerForm() 실행...!");
	}
	
	@RequestMapping(value = "/modify")
	public void modifyForm() {
		log.info("modifyForm() 실행...!");
	}
	
	@RequestMapping(value = "/list")
	public void list() {
		log.info("list() 실행...!");
	}
	
	/*
	 * 		2. 경로 패턴 매핑
	 * 
	 * 			- 요청 경로를 동적으로 표현이 가능한 경로 패턴을 지정할 수 있다.
	 * 			- URL 경로 상의 변하는 값을 경로 변수로 취급한다.
	 * 			- 경로 변수에 해당하는 값을 파라미터 변수에 설정할 수 있다.
	 */
	
	@RequestMapping(value = "/read/{boardNo}")
	public String read(@PathVariable("boardNo") int boardNo) {
		log.info("read() 실행...!");
		log.info("경로 상의 포함된 boardNo : " + boardNo);
		return "board/read";
	}
	
	/*
	 *		3. HTTP 메서드 매핑
	 *
	 *			- method 속성을 사용하여 HTTP 메서드를 매핑 조건으로 지정할 수 있다.
	 *			- 화면으로 응답하는 경우에는 HTTP 메서드로 GET방식과 POST방식 두 가지를 사용할 수 있다.
	 */
	
	// HTTP 메서드 매핑 실행 페이지
	
	@RequestMapping(value = "/formHome", method = RequestMethod.GET)
	public String formHome() {
		log.info("formHome() 실행...!");
		return "formHome";
	}
	
	// register 경로에 GET 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.GET)
	public String registerFormHttp() {
		log.info("registerFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// register 경로에 POST 방식
	@RequestMapping(value = "/http/register", method = RequestMethod.POST)
	public String registerHttp() {
		log.info("registerHttp() 실행...!");
		return "success";
	}
	
	// modify 경로에  GET 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.GET)
	public String modifyFormHttp() {
		log.info("modifyFormHttp() 실행...! GET 방식으로 요청");
		return "success";
	}
	
	// modify 경로에 POST 방식
	@RequestMapping(value = "/http/modify", method = RequestMethod.POST)
	public String modifyHttp() {
		log.info("modifyHttp() 실행...!");
		return "success";
	}
	
	// remove 경로에 POST 방식
	@RequestMapping(value = "/http/remove", method = RequestMethod.POST)
	public String removeHttp() {
		log.info("removeHttp() 실행...!");
		return "success";
	}
	
	// list 경로에 GET 방식
	@RequestMapping(value = "/http/list", method = RequestMethod.GET)
	public String listHttp() {
		log.info("listHttp() 실행...!");
		return "success";
	}
	
	/*
	 * 		4. Params 매핑
	 * 
	 * 			- 요청 파라미터를 매핑 조건으로 지정하는 경우에는 params 속성을 사용한다.
	 * 			- 버튼이나 링크에 따라 호출할 메서드를 바꿔야 할 때 사용한다.
	 * 
	 * 			** Params 매핑 테스트 페이지
	 * 				> board/list.jsp
	 * 				> board/modify.jsp
	 * 				> board/read.jsp
	 * 				> board/register.jsp
	 * 				> board/remove.jsp
	 */
	
	// /board/get 경로, GET 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "register")
	public String registerFormParamsGet() {
		log.info("registerFormParamsGet() 실행...!");
		return "board/register";
	}
	
	// /board/post 경로, POST 방식, "register" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "register")
	public String registerParamsPost() {
		log.info("registerParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "modify")
	public String modifyFormParamsGet() {
		log.info("modifyFormParamsGet() 실행...!");
		return "board/modify";
	}
	
	// /board/post 경로, POST 방식, "modify" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "modify")
	public String modifyParamsPost() {
		log.info("modifyParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/get 경로, GET 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "remove")
	public String removeFormParamsGet() {
		log.info("removeFormParamsGet() 실행...!");
		return "board/remove";
	}
	
	// /board/post 경로, POST 방식, "remove" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/post", method = RequestMethod.POST, params = "remove")
	public String removeParamsPost() {
		log.info("removeParamsPost() 실행...!");
		return "board/list";
	}
	
	// /board/list 경로, GET 방식, "list" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "list")
	public String listParamsGet() {
		log.info("listParamsGet() 실행...!");
		return "board/list";
	}
	
	// /board/read 경로, GET 방식, "read" 요청 파라미터에 대한 처리
	@RequestMapping(value = "/get", method = RequestMethod.GET, params = "read")
	public String readParamsGet() {
		log.info("readParamsGet() 실행...!");
		return "board/read";
	}
	
	/*
	 * 		5. Headers 매핑
	 * 
	 * 			- 요청 헤더를 매핑 조건으로 지정하는 경우에는 headers 속성을 사용한다.
	 */
	
	// Headers 매핑을 테스트할 페이지
	@RequestMapping(value = "/ajaxHome", method = RequestMethod.GET)
	public String ajaxHome() {
		log.info("ajaxHome() 실행...!");
		return "ajaxHome";
	}
	
	// Headers 매핑이지만, headers 설정을 하지 않고 요청
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT)
	public ResponseEntity<String> modifyPut(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board) {
		
		log.info("modifyPut() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
	}
	
	// headers 속성에 설정되어 있는 header 정보를 매핑으로 요청
	// header 속성에 'X-HTTP-Method-Override=PUT' 정보가 들어 있는 요청은 이곳으로 들어옴
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, headers = "X-HTTP-Method-Override=PUT")
	public ResponseEntity<String> modifyByHeader(@PathVariable int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByHeader() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	/*
	 * 		6. Content Type 매핑
	 * 
	 * 			- 요청의 Content-Type 헤더 값을 매핑 조건으로 지정하는 경우에는 consumes 속성을 사용한다.
	 */
	
	// consumes 속성값을 지정하지 않으면 기본값으로 "application/json" 미디어 타입으로 지정된다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.POST)
	public ResponseEntity<String> modifyContentType(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyContentType() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	// consume 속성 값에 "application/json"의 미디어 타입을 지정한다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, consumes = "application/json")
	public ResponseEntity<String> modifyByJson(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByJson() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.PUT, consumes = "application/xml")
	public ResponseEntity<String> modifyByXml(@PathVariable("boardNo") int boardNo,
			@RequestBody Board board){
		
		log.info("modifyByXml() 실행...!");
		
		log.info("경로상의 포함된 boardNo : " + boardNo);
		log.info("넘겨받은 데이터들(boardNo) : " + board.getBoardNo());
		log.info("넘겨받은 데이터들(title) : " + board.getTitle());
		log.info("넘겨받은 데이터들(content) : " + board.getContent());
		log.info("넘겨받은 데이터들(writer) : " + board.getWriter());
		
		return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		
	}
	
	/*
	 * 		7. Accept 매핑
	 * 
	 * 			- 요청 Accept 헤더 값을 매핑 조건으로 지정하는 경우에는 produces 속성을 사용한다.
	 * 			- 서버가 produces = "application/json"으로 보내면 , 클라이언트가 dataType = "json" 으로 받음
	 * 			- 서버가 produces = "text/plain"으로 보내면 , 클라이언트가 dataType = "text" 으로 받음
	 * 
	 * 		비동기 기본 속성들을 알아야 한다.
	 * 		url : 클라이언트가 서버로 요청할 경로
	 * 		type : 클라이언트가 서버로 보내는 method(GET, POST, PUT, DELETE) 방식
	 * 		data : 클라이언트가 서버로 보낼 데이터
	 * 		dataType : 서버에서 클라이언트로 응답을 내보낼때 클라이언트가 받는 응답 데이터 타입
	 * 		success : 성공 했을 때에 대한 콜백 함수
	 * 		contentType : 클라이언트에서 서버 쪽의 목적지로 보낼 때 header에 설정하는  mimeType
	 */
	
	// produces 속성값을 지정하지 않으면 기본값인 "application/json" 미디어 타입으로 지정된다.
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.GET)
	public ResponseEntity<Board> readAccept(@PathVariable("boardNo") int boardNo){
		
		log.info("readAccept() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		
		Board board = new Board();
		board.setTitle("제목입니다");
		board.setContent("내용입니다");
		board.setWriter("a001");
		
		return new ResponseEntity<Board>(board, HttpStatus.OK);
		
	}
	
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.GET, produces = "application/json")
	public ResponseEntity<Board> readToJson(@PathVariable("boardNo") int boardNo){
		
		log.info("readToJson() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		
		String addStr = "_json";
		Board board = new Board();
		board.setTitle("제목입니다" + addStr);
		board.setContent("내용입니다" + addStr);
		board.setWriter("a001" + addStr);
		
		return new ResponseEntity<Board>(board, HttpStatus.OK);
		
	}
	
	@RequestMapping(value = "/{boardNo}", method = RequestMethod.GET, produces = "application/xml")
	public ResponseEntity<Board> readToXml(@PathVariable("boardNo") int boardNo){
		
		log.info("readToXml() 실행...!");
		log.info("경로상의 포함된 boardNo : " + boardNo);
		
		String addStr = "_xml";
		Board board = new Board();
		board.setTitle("제목입니다" + addStr);
		board.setContent("내용입니다" + addStr);
		board.setWriter("a001" + addStr);
		
		return new ResponseEntity<Board>(board, HttpStatus.OK);
		
	}
	
}

[pom.xml] 에서 주석처리 해야 함

		<!-- json 데이터 바인딩을 위한 의존 라이브러리 -->	
		<!-- <dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.5</version>
		</dependency> -->
		
		<!-- xml 데이터 바인딩을 위한 의존 라이브러리 -->
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
			<version>2.9.5</version>
		</dependency>

- http://localhost/board/ajaxHome