728x90
반응형
SMALL
만약 질문을 등록할 때 질문 내요을 비어 있는 값으로도 등록할 수 있다.
하지만 이건 옳지 않는 방법이므로 아무것도 입력하지 않은 상태에서 질문이 등록될 수 없도록 해야한다.
따라서 폼 클래스를 사용하여 입력값을 체크하는 방법을 이요해보자.

 

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 속성에 기존에 입력된 값을 채워 넣어준다.

 

그럼 제목만 입력 후 저장하기 버튼을 클릭하면 기존 값이 유지된다.

 

728x90
반응형
LIST

+ Recent posts