11 Validation(검증)
p197 ~ 199 - src/main/java/spring/mvc/controller/ValidationFormController
@Slf4j
@Controller
@RequestMapping("/validation/form")
public class ValidationFormController {
private final BookService bookService;
public ValidationFormController(BookService bookService) {
this.bookService = bookService;
}
@GetMapping("/books")
public String showBookForm(Model model) {
model.addAttribute("book", new Book()); // 빈 Book 객체를 모델에 추가
return "validation/bookForm";
}
// CREATE: 책 생성 - 수동 검증
@PostMapping("/books")
public String createBook(@ModelAttribute Book book, Model model) {
// 수동 검증 로직
if (book.getTitle() == null || book.getTitle().trim().isEmpty()) {
model.addAttribute("error", "책 제목은 필수 입력값입니다.");
return "validation/bookForm";
}
if (book.getPublisher() == null || book.getPublisher().trim().isEmpty()) {
model.addAttribute("error", "저자는 필수 입력값입니다.");
return "validation/bookForm";
}
if (book.getSalePrice() < 0) {
model.addAttribute("error", "책 가격은 0 이상이어야 합니다.");
return "validation/bookForm";
}
// 검증이 통과된 경우 책 생성
Book createdBook = bookService.createBook(book);
model.addAttribute("book", createdBook);
model.addAttribute("success", "책이 성공적으로 생성되었습니다!");
return "validation/bookForm"; // 동일한 폼 페이지로 리다이렉트하여 성공 메시지 표시
}
// READ: ID로 책 검색 - 수동 검증
@GetMapping("/books/{bookIdx}")
public String getBookById(@PathVariable Long bookIdx, Model model) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
model.addAttribute("error", "책 ID는 0보다 큰 값이어야 합니다.");
return "validation/bookDetail";
}
Optional<Book> book = bookService.getBookById(bookIdx);
if (book.isPresent()) {
model.addAttribute("book", book.get());
return "validation/bookDetail"; // 책 정보를 보여줄 뷰 페이지
} else {
model.addAttribute("error", "책을 찾을 수 없습니다.");
return "validation/bookDetail";
}
}
// UPDATE: 책 정보 수정 - 수동 검증
@PostMapping("/books/{bookIdx}/update")
public String updateBook(@PathVariable Long bookIdx, @ModelAttribute Book updatedBook, Model model) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
model.addAttribute("error", "책 ID는 0보다 큰 값이어야 합니다.");
return "validation/bookForm";
}
if (updatedBook.getTitle() == null || updatedBook.getTitle().trim().isEmpty()) {
model.addAttribute("error", "책 제목은 필수 입력값입니다.");
return "validation/bookForm";
}
if (updatedBook.getPublisher() == null || updatedBook.getPublisher().trim().isEmpty()) {
model.addAttribute("error", "저자는 필수 입력값입니다.");
return "validation/bookForm";
}
if (updatedBook.getSalePrice() < 0) {
model.addAttribute("error", "책 가격은 0 이상이어야 합니다.");
return "validation/bookForm";
}
Optional<Book> book = bookService.updateBook(bookIdx, updatedBook);
if (book.isPresent()) {
model.addAttribute("book", book.get());
model.addAttribute("success", "책 정보가 성공적으로 수정되었습니다!");
return "validation/bookForm"; // 동일한 폼 페이지로 리다이렉트하여 성공 메시지 표시
} else {
model.addAttribute("error", "책을 찾을 수 없습니다.");
return "validation/bookForm";
}
}
// DELETE: 책 삭제 - 수동 검증
@PostMapping("/books/{bookIdx}/delete")
public String deleteBook(@PathVariable Long bookIdx, Model model) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
model.addAttribute("error", "책 ID는 0보다 큰 값이어야 합니다.");
return "validation/bookDetail";
}
boolean deleted = bookService.deleteBook(bookIdx);
if (deleted) {
model.addAttribute("message", "책이 성공적으로 삭제되었습니다.");
return "validation/bookDetail"; // 동일한 페이지에서 메시지 표시
} else {
model.addAttribute("error", "책을 찾을 수 없습니다.");
return "validation/bookDetail";
}
}
// BOOKING: 책 대여 - 수동 검증
@PostMapping("/books/{bookIdx}/rent/{userIdx}")
public String rentBook(@PathVariable Long bookIdx, @PathVariable Long userIdx, Model model) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
model.addAttribute("error", "책 ID는 0보다 큰 값이어야 합니다.");
return "validation/bookDetail";
}
if (userIdx == null || userIdx <= 0) {
model.addAttribute("error", "사용자 ID는 0보다 큰 값이어야 합니다.");
return "validation/bookDetail";
}
try {
Optional<Book> rentedBook = bookService.rentBook(bookIdx, userIdx);
if (rentedBook.isPresent()) {
model.addAttribute("book", rentedBook.get());
model.addAttribute("success", "책이 성공적으로 대여되었습니다!");
return "validation/bookDetail"; // 동일한 페이지에서 메시지 표시
} else {
model.addAttribute("error", "책을 찾을 수 없습니다.");
return "validation/bookDetail";
}
} catch (IllegalStateException | IllegalArgumentException e) {
log.error("책 대여 오류: {}", e.getMessage());
model.addAttribute("error", e.getMessage());
return "validation/bookDetail";
}
}
// RETURN: 책 반납 - 수동 검증
@PostMapping("/books/{bookIdx}/return/{userIdx}")
public String returnBook(@PathVariable Long bookIdx, @PathVariable Long userIdx, Model model) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
model.addAttribute("error", "책 ID는 0보다 큰 값이어야 합니다.");
return "validation/bookDetail";
}
if (userIdx == null || userIdx <= 0) {
model.addAttribute("error", "사용자 ID는 0보다 큰 값이어야 합니다.");
return "validation/bookDetail";
}
try {
Optional<Book> returnedBook = bookService.returnBook(bookIdx, userIdx);
if (returnedBook.isPresent()) {
model.addAttribute("book", returnedBook.get());
model.addAttribute("success", "책이 성공적으로 반납되었습니다!");
return "validation/bookDetail"; // 동일한 페이지에서 메시지 표시
} else {
model.addAttribute("error", "책을 찾을 수 없습니다.");
return "validation/bookDetail";
}
} catch (IllegalStateException | IllegalArgumentException e) {
log.error("책 반납 오류: {}", e.getMessage());
model.addAttribute("error", e.getMessage());
return "validation/bookDetail";
}
}
}
p202 - src/main/java/spring/mvc/controller/ValidationFormBindingController
@Slf4j
@Controller
@RequestMapping("/validation/form/binding")
public class ValidationFormBindingController {
private final BookService bookService;
public ValidationFormBindingController(BookService bookService) {
this.bookService = bookService;
}
@GetMapping("/books")
public String showBookForm(Model model) {
model.addAttribute("book", new Book()); // 빈 Book 객체를 모델에 추가
return "validation/bookFormBinding";
}
// CREATE: 책 생성 - BindingResult 사용
@PostMapping("/books")
public String createBook(@ModelAttribute Book book, BindingResult bindingResult, Model model) {
// 수동 검증 로직
if (book.getTitle() == null || book.getTitle().trim().isEmpty()) {
bindingResult.rejectValue("title", "error.title", "책 제목은 필수 입력값입니다.");
}
if (book.getPublisher() == null || book.getPublisher().trim().isEmpty()) {
bindingResult.rejectValue("publisher", "error.publisher", "저자는 필수 입력값입니다.");
}
if (book.getSalePrice() < 0) {
bindingResult.rejectValue("salePrice", "error.salePrice", "책 가격은 0 이상이어야 합니다.");
}
// 검증 실패 시, 다시 폼 페이지로 이동
if (bindingResult.hasErrors()) {
log.info("errors = {}", bindingResult);
return "validation/bookFormBinding";
}
// 검증이 통과된 경우 책 생성
Book createdBook = bookService.createBook(book);
model.addAttribute("book", createdBook);
model.addAttribute("success", "책이 성공적으로 생성되었습니다!");
return "validation/bookFormBinding";
}
// READ: ID로 책 검색 - 수동 검증
@GetMapping("/books/{bookIdx}")
public String getBookById(@PathVariable Long bookIdx, Model model) {
if (bookIdx <= 0) {
model.addAttribute("error", "책 ID는 0보다 큰 값이어야 합니다.");
return "validation/bookDetailBinding";
}
Optional<Book> book = bookService.getBookById(bookIdx);
if (book.isPresent()) {
model.addAttribute("book", book.get());
} else {
model.addAttribute("error", "책을 찾을 수 없습니다.");
}
return "validation/bookDetailBinding";
}
// UPDATE: 책 정보 수정 - BindingResult 사용
@PostMapping("/books/{bookIdx}/update")
public String updateBook(@PathVariable Long bookIdx, @ModelAttribute Book updatedBook, BindingResult bindingResult, Model model) {
// 수동 검증 로직
if (updatedBook.getTitle() == null || updatedBook.getTitle().trim().isEmpty()) {
bindingResult.rejectValue("title", "error.title", "책 제목은 필수 입력값입니다.");
}
if (updatedBook.getPublisher() == null || updatedBook.getPublisher().trim().isEmpty()) {
bindingResult.rejectValue("publisher", "error.publisher", "저자는 필수 입력값입니다.");
}
if (updatedBook.getSalePrice() < 0) {
bindingResult.rejectValue("salePrice", "error.salePrice", "책 가격은 0 이상이어야 합니다.");
}
// 검증 실패 시, 다시 폼 페이지로 이동
if (bindingResult.hasErrors()) {
return "validation/bookFormBinding";
}
Optional<Book> book = bookService.updateBook(bookIdx, updatedBook);
if (book.isPresent()) {
model.addAttribute("book", book.get());
model.addAttribute("success", "책 정보가 성공적으로 수정되었습니다!");
} else {
model.addAttribute("error", "책을 찾을 수 없습니다.");
}
return "validation/bookFormBinding";
}
}
p203 - src/main/resources/templates/validation/bookFormBinding.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>책 관리 폼</title>
</head>
<body>
<h1>책 관리</h1>
<!-- 에러 메시지 표시 -->
<div th:if="${error}" style="color: red;">
<p th:text="${error}"></p>
</div>
<!-- 성공 메시지 표시 -->
<div th:if="${success}" style="color: green;">
<p th:text="${success}"></p>
</div>
<form th:action="@{/validation/form/binding/books}" th:object="${book}" method="post">
<label for="title">책 제목:</label>
<input type="text" th:field="*{title}" id="title"><br>
<div th:if="${#fields.hasErrors('title')}" style="color: red;">
<p th:errors="*{title}"></p>
</div>
<label for="publisher">저자:</label>
<input type="text" th:field="*{publisher}" id="publisher"><br>
<div th:if="${#fields.hasErrors('publisher')}" style="color: red;">
<p th:errors="*{publisher}"></p>
</div>
<label for="salePrice">가격:</label>
<input type="text" th:field="*{salePrice}" id="salePrice"><br>
<div th:if="${#fields.hasErrors('salePrice')}" style="color: red;">
<p th:errors="*{salePrice}"></p>
</div>
<button type="submit">제출</button>
</form>
</body>
</html>
p206 , 207- src/main/java/spring/mvc/controller/ValidationController
@Slf4j
@RestController
@RequestMapping("/validation")
public class ValidationController {
private final BookService bookService;
private final ObjectMapper objectMapper = new ObjectMapper();
public ValidationController(BookService bookService) {
this.bookService = bookService;
}
// JSON 변환을 위한 헬퍼 메서드
private String convertToJson(Object object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
log.error("JSON 변환 오류: {}", e.getMessage());
return "{\"error\": \"JSON 변환 중 오류가 발생했습니다.\"}";
}
}
// CREATE: 책 생성 - 수동 검증
@PostMapping("/books")
public String createBook(@RequestBody Book book) {
// 수동 검증 로직
if (book.getTitle() == null || book.getTitle().trim().isEmpty()) {
return "{\"error\": \"책 제목은 필수 입력값입니다.\"}";
}
if (book.getPublisher() == null || book.getPublisher().trim().isEmpty()) {
return "{\"error\": \"저자는 필수 입력값입니다.\"}";
}
if (book.getSalePrice() < 0) {
return "{\"error\": \"책 가격은 0 이상이어야 합니다.\"}";
}
// 검증이 통과된 경우 책 생성
Book createdBook = bookService.createBook(book);
return convertToJson(createdBook);
}
// READ: ID로 책 검색 - 수동 검증
@GetMapping("/books/{bookIdx}")
public String getBookById(@PathVariable Long bookIdx) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
return "{\"error\": \"책 ID는 0보다 큰 값이어야 합니다.\"}";
}
Optional<Book> book = bookService.getBookById(bookIdx);
if (book.isPresent()) {
return convertToJson(book.get());
} else {
return "{\"error\": \"책을 찾을 수 없습니다.\"}";
}
}
// UPDATE: 책 정보 수정 - 수동 검증
@PutMapping("/books/{bookIdx}")
public String updateBook(@PathVariable Long bookIdx, @RequestBody Book updatedBook) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
return "{\"error\": \"책 ID는 0보다 큰 값이어야 합니다.\"}";
}
if (updatedBook.getTitle() == null || updatedBook.getTitle().trim().isEmpty()) {
return "{\"error\": \"책 제목은 필수 입력값입니다.\"}";
}
if (updatedBook.getPublisher() == null || updatedBook.getPublisher().trim().isEmpty()) {
return "{\"error\": \"저자는 필수 입력값입니다.\"}";
}
if (updatedBook.getSalePrice() < 0) {
return "{\"error\": \"책 가격은 0 이상이어야 합니다.\"}";
}
Optional<Book> book = bookService.updateBook(bookIdx, updatedBook);
if (book.isPresent()) {
return convertToJson(book.get());
} else {
return "{\"error\": \"책을 찾을 수 없습니다.\"}";
}
}
// DELETE: 책 삭제 - 수동 검증
@DeleteMapping("/books/{bookIdx}")
public String deleteBook(@PathVariable Long bookIdx) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
return "{\"error\": \"책 ID는 0보다 큰 값이어야 합니다.\"}";
}
boolean deleted = bookService.deleteBook(bookIdx);
if (deleted) {
return "{\"message\": \"책이 성공적으로 삭제되었습니다.\"}";
} else {
return "{\"error\": \"책을 찾을 수 없습니다.\"}";
}
}
// BOOKING: 책 대여 - 수동 검증
@PostMapping("/books/{bookIdx}/rent/{userIdx}")
public String rentBook(@PathVariable Long bookIdx, @PathVariable Long userIdx) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
return "{\"error\": \"책 ID는 0보다 큰 값이어야 합니다.\"}";
}
if (userIdx == null || userIdx <= 0) {
return "{\"error\": \"사용자 ID는 0보다 큰 값이어야 합니다.\"}";
}
try {
Optional<Book> rentedBook = bookService.rentBook(bookIdx, userIdx);
if (rentedBook.isPresent()) {
return convertToJson(rentedBook.get());
} else {
return "{\"error\": \"책을 찾을 수 없습니다.\"}";
}
} catch (IllegalStateException | IllegalArgumentException e) {
log.error("책 대여 오류: {}", e.getMessage());
return "{\"error\": \"" + e.getMessage() + "\"}";
}
}
// RETURN: 책 반납 - 수동 검증
@PostMapping("/books/{bookIdx}/return/{userIdx}")
public String returnBook(@PathVariable Long bookIdx, @PathVariable Long userIdx) {
// 수동 검증 로직
if (bookIdx == null || bookIdx <= 0) {
return "{\"error\": \"책 ID는 0보다 큰 값이어야 합니다.\"}";
}
if (userIdx == null || userIdx <= 0) {
return "{\"error\": \"사용자 ID는 0보다 큰 값이어야 합니다.\"}";
}
try {
Optional<Book> returnedBook = bookService.returnBook(bookIdx, userIdx);
if (returnedBook.isPresent()) {
return convertToJson(returnedBook.get());
} else {
return "{\"error\": \"책을 찾을 수 없습니다.\"}";
}
} catch (IllegalStateException | IllegalArgumentException e) {
log.error("책 반납 오류: {}", e.getMessage());
return "{\"error\": \"" + e.getMessage() + "\"}";
}
}
}
Last updated