만약 질문을 등록할 때 질문 내요을 비어 있는 값으로도 등록할 수 있다.
하지만 이건 옳지 않는 방법이므로 아무것도 입력하지 않은 상태에서 질문이 등록될 수 없도록 해야한다.
따라서 폼 클래스를 사용하여 입력값을 체크하는 방법을 이요해보자.
Spring Boot Validation 라이브러리 설치하기
build.gradle
...
//SpringBoot Validation
implementation 'org.springframework.boot:spring-boot-starter-validation'
...
항목 | 설명 |
@Size | 문자 길이 제한 |
@NotNull | Null을 허용하지 않음 |
@NotEmpty | Null 또는 빈 문자열("")을 허용하지 않음 |
@Past | 과거 날짜만 입력 가능 |
@Future | 미래 날짜만 입력 가능 |
@FutureOrPresent | 미래 또는 오늘 날짜만 입력 가능 |
@Max | 최댓값 이하의 값만 입력할 수 있도록 제한 |
@Min | 최솟값 이상의 값만 입력할 수 있도록 제한 |
@Pattern | 입력값을 정규식 패턴으로 검증 |
폼 클래스 만들기
질문 등록 페이지에서 사용자로부터 입력받은 값을 검증하는데 필요한 폼 클래스를 만들어보자.
/question/QuestionForm.java
package com.mysite.sbb.question;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class QuestionForm {
@NotEmpty(message="제목은 필수 항목입니다.")
@Size(max=200)
private String subject;
@NotEmpty(message="내용은 필수 항목입니다.")
private String content;
}
컨트롤러에 전송하기
/question/QuestionController.java
...
@PostMapping("/create")
public String questionCreate(@Valid QuestionForm questionForm, BindingResult bindingResult){
if (bindingResult.hasErrors()) {
return "question_form";
}
this.questionService.create(questionForm.getSubject(), questionForm.getContent());
return "redirect:/question/list";
}
...
이 메서드의 매개변수를 subject, content 대신 QuestionForm 객체로 변경했다.
이미 class QuestionForm에는 subject, content 항목을 포함하고 있기때문에 자동으로 바인딩 된다.
앞의 @Valid 어노테이션은 검증 기능이 동작한다.
bindingResult는 검증 결과를 의미한다.
템플릿 수정하기
검증에 실패했다는 오류 메시지를 보여주기 위해 템플릿을 수정한다.
/templates/question_form.html
<html layout:decorate="~{layout}">
<div layout:fragment="content" class="container">
<h5 class="my-3 border-bottom pb-2">질문등록</h5>
<form th:action="@{/question/create}" th:object="${questionForm}" method="post">
<div class="alert alert-danger" role="alert" th:if="${#fields.hasAnyErrors()}">
<div th:each="err: ${#fields.allErrors()}" th:text="${err}"></div>
</div>
<div class="mb-3">
<label for="subject" class="form-label">제목</label>
<input type="text" name="subject" id="subject" class="form-control">
</div>
<div class="mb-3">
<label for="content" class="form-label">내용</label>
<textarea name="content" id="content" class="form-control" rows="10"></textarea>
</div>
<input type="submit" value="저장하기" class="btn btn-primary my-2">
</form>
</div>
</html>
form의 속성 th:object는 <form>의 입력 항목들이 QuestionForm과 연결된다는 점을 타임리프에 알려준다.
그런데 여기 th:object 속성을 추가했으므로 controller에서 getMapping으로 매핑한 메서드에서도 QuestionForm 객체를 넘겨주어야 한다.
/question/QuestionController.java
@GetMapping("/create")
public String questionCreate(QuestionForm questionForm) {
return "question_form";
}
오류 처리하기
만약 내용을 입력하지 않고 제목만 입력 후 저장하기 버튼을 클릭하게 되면
/templates/question_form.html
<html layout:decorate="~{layout}">
<div layout:fragment="content" class="container">
<h5 class="my-3 border-bottom pb-2">질문등록</h5>
<form th:action="@{/question/create}" th:object="${questionForm}" method="post">
<div class="alert alert-danger" role="alert" th:if="${#fields.hasAnyErrors()}">
<div th:each="err: ${#fields.allErrors()}" th:text="${err}"></div>
</div>
<div class="mb-3">
<label for="subject" class="form-label">제목</label>
<input type="text" th:field="*{subject}" class="form-control">
</div>
<div class="mb-3">
<label for="content" class="form-label">내용</label>
<textarea th:field="*{content}" class="form-control" rows="10"></textarea>
</div>
<input type="submit" value="저장하기" class="btn btn-primary my-2">
</form>
</div>
</html>
입력값을 담는 input태그와 textarea에 name속성 대신 th:field로 수정했다.
그럼 태그의 id, name, value 속성이 모두 자동으로 생성되고 타임리프가 value 속성에 기존에 입력된 값을 채워 넣어준다.
'IT > Spring Boot' 카테고리의 다른 글
[Spring Boot] 18. 공통 템플릿 만들기 (0) | 2024.04.30 |
---|---|
[Spring Boot] 17. 폼(Form) 활용하기(2) (0) | 2024.04.30 |
[Spring Boot] 15. 질문 등록 기능 추가하기 (0) | 2024.04.30 |
[Spring Boot] 14. 표준 HTML 구조로 변경 (0) | 2024.04.11 |
[Spring Boot] 13. 부트스트랩으로 화면 꾸미기 (0) | 2024.04.11 |