참고 : 인프런 [ 실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 - 김영한 ]
@Getter @Setter
public class MemberForm {
@NotEmpty(message = "회원 이름은 필수 입니다")
private String name;
private String city;
private String street;
private String zipcode;
}
@NotEmpty 오류 발생
유효성 검사를 해주는 어노테이션
비어있으면 오류
강의 자료와 똑같이 작성하였지만 어노테이션이 적용되지 않았다.@NotEmpty는 javax.validation.constraints 패키지안에 존재하는 어노테이션인데, 스프링 부트 2.3 이상은 의존성을 직접 넣어주어야 적용된다고 한다.
=> build.gradle 에 추가implementation 'org.springframework.boot:spring-boot-starter-validation'

정상적으로 어노테이션이 적용되는 것을 확인하였다.
@Controller
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
@GetMapping(value = "/members/new")
public String createForm(Model model) {
model.addAttribute("memberForm", new MemberForm());
return "members/createMemberForm";
}
}
!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments/header :: header" />
<style>
.fieldError {
border-color: #bd2130;
}
</style>
<body>
<div class="container">
<div th:replace="fragments/bodyHeader :: bodyHeader"/>
<form role="form" action="/members/new" th:object="${memberForm}"
method="post">
<div class="form-group">
<label th:for="name">이름</label>
<input type="text" th:field="*{name}" class="form-control"
placeholder="이름을 입력하세요"
th:class="${#fields.hasErrors('name')}? 'form-control
fieldError' : 'form-control'">
<p th:if="${#fields.hasErrors('name')}"
th:errors="*{name}">Incorrect date</p>
</div>
...
th:object="${memberForm}"
th:field="*{name}"
th:class="${#fields.hasErrors('name')}? 'form-control is-invalid' : 'form-control'"
form role="form" action="/members/new" th:object="${memberForm}" method="post">
@PostMapping(value = "/members/new")
public String create(@Valid MemberForm form, BindingResult result){ //폼 등록
if(result.hasErrors()){ //오류가 있으면
return "members/createMemberForm";
}
Address address = new Address(form.getCity(), form.getStreet(), form.getZipcode());
Member member=new Member();
member.setName(form.getName());
member.setAddress(address);
memberService.join(member);
return "redirect:/";
}
@Valid 어노테이션
- Java Bean Validation API에서 제공하는 어노테이션
- 객체의 필드 값들이 유효한지 검증할 때 사용
- 주로 Spring MVC와 함께 사용되어, 컨트롤러에서 입력 데이터의 유효성을 검증할 때 많이 활용
BindingResult
- Spring Framework에서 제공하는 인터페이스
- 폼 데이터와 객체를 바인딩하는 과정에서 발생한 오류들을 저장하고 처리
- 주로 컨트롤러 메서드에서 사용되며, 유효성 검사 결과를 포함하여 폼 데이터를 처리하는데 도움을 줌
@NotEmpty(message = "회원 이름은 필수 입니다")
private String name;
로 선언하였기 때문에, 만약 회원가입 폼에서 이름을 입력하지 않으면,

위와 같은 화면이 나오게 된다.
<input type="text" th:field="*{name}" class="form-control"
placeholder="이름을 입력하세요"
th:class="${#fields.hasErrors('name')}? 'form-controlfieldError' : 'form-control'">
<p th:if="${#fields.hasErrors('name')}"
th:errors="*{name}">Incorrect date</p>
th:if="${#fields.hasErrors('name')}"<p> 태그를 렌더링th:errors="*{name}"Incorrect date: 오류가 있을 경우 표시될 기본 텍스트. 실제로는 th:errors 속성이 유효성 검사 메시지로 대체💡 return 하였는데도 왜 그 전에 입력한 도시,거리,우편번호 값 그대로 화면에 뿌려질까?
@PostMapping(value = "/members/new") public String create(@Valid MemberForm form, BindingResult result){ ...
- 컨트롤러에서 MemberForm 을 파라미터로 받게 된다. 만약 @Valid 어노테이션과 BindingResult를 통해 오류가 발생하게 되어 해당 폼 페이지로 다시 이동한다.
- MemberForm 객체는 유효성 검사 후에도 그대로 유지되며, 컨트롤러에서 다시 폼 페이지로 전달된다.
- 이는 Spring MVC가 자동으로 폼 데이터를 다시 바인딩하여, 입력했던 데이터를 유지한다.



회원가입을 테스트해보면 정상적으로 처리되는 것을 확인할 수 있다!