[SpringBoot] 회원가입 비밀번호, 비밀번호 확인 불일치 처리

2022. 9. 7. 12:51문제해결

개요

SpringBoot 기반 회원가입 서비스 구현중 비밀번호, 비밀번호 확인 필드 입력이 불일치하는 경우 "비밀번호가 일치하지 않습니다." 메시지를 출력하고자 합니다.

 

이 글은 이전 문제해결 글을 기반으로 해결한 문제이기 때문에 글에서 생략된 부분이 많습니다.

https://yonghwankim-dev.tistory.com/515

 

[SpringBoot] 회원가입 유효성 검증 및 중복 조회 처리

개요 SpringBoot 기반으로 회원가입 서비스를 구현하던 중 사용자로부터 입력받은 회원가입 입력정보들이 올바른지 유효성을 검증하고 만약 이미 가입된 아이디, 이메일, 연락처 정보가 있다면 이

yonghwankim-dev.tistory.com

 

CheckPasswordEqualValidator 클래스 추가

@RequiredArgsConstructor
@Component
public class CheckPasswordEqualValidator extends AbstractValidator<MemberForm>{
    @Override
    protected void doValidate(MemberForm dto, Errors errors) {
        if(!dto.getPassword().equals(dto.getPassword_confirm())){
            errors.rejectValue("password_confirm", "비밀번호 일치 오류", "비밀번호가 일치하지 않습니다.");
        }
    }
}

 

MemberController 클래스에 Validator 추가

@Controller
@RequiredArgsConstructor
class MemberController {

	...
    private final CheckPasswordEqualValidator checkPasswordEqualValidator;

    // 커스텀 유효성 검증을 위해 추가
    @InitBinder
    public void validatorBinder(WebDataBinder binder){
        ...
        binder.addValidators(checkPasswordEqualValidator);
    }

    @GetMapping("/members/new")
    public String createForm(Model model){
        model.addAttribute("memberForm", new MemberForm());
        return "members/createMemberForm";
    }

    @PostMapping("/members/new")
    public String create(@Valid MemberForm memberForm, Errors errors, Model model){
        if(errors.hasErrors()){
            // 회원가입 실패시 입력 데이터 값을 유지
            model.addAttribute("memberForm", memberForm);

            // 유효성 통과 못한 필드와 메시지를 핸들링
            Map<String, String> validatorResult = memberService.validateHandling(errors);
            for(String key : validatorResult.keySet()){
                model.addAttribute(key, validatorResult.get(key));
            }
            // 회원가입 페이지로 다시 리턴
            return "members/createMemberForm";
        }

        Member member = Member.createMember(memberForm);
        memberService.signUp(member);
        return "redirect:/";
    }
}

 

createMemberForm.html

<!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}" placeholder="이름을 입력하세요"
                   th:class="${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control'">
            <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></p>
        </div>
        <div class="form-group">
            <label th:for="birthday">생년월일</label>
            <input type="date" th:field="*{birthday}" class="form-control">
        </div>
        <div class="form-group">
            <label th:for="phone">휴대폰번호</label>
            <input type="text" th:field="*{phone}" placeholder="010-0000-0000"
                   th:class="${#fields.hasErrors('phone')}? 'form-control fieldError' : 'form-control'"/>
            <p th:if="${#fields.hasErrors('phone')}" th:errors="*{phone}"></p>
        </div>
        <div class="form-group">
            <label th:for="address">주소</label>
            <div class="form-control" style="height: auto">
                <label th:for="zipcode" style="width : 100px;">우편번호</label>
                <input type="text" th:field="*{zipcode}"/>
                <button type="button" class="btn btn-secondary" onclick="openZipSearch()">검색</button><br>

                <label th:for="street" style="width : 100px;">주소</label>
                <input type="text" th:field="*{street}" readonly /><br>

                <label th:for="detail" style="width : 100px;">상세주소</label>
                <input type="text" th:field="*{detail}"/>
            </div>
        </div>
        <div class="form-group">
            <label th:for="email">이메일</label>
            <input type="email" th:field="*{email}" placeholder="user@gmail.com"
                   th:class="${#fields.hasErrors('email')}? 'form-control fieldError' : 'form-control'"/>
            <p th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></p>
        </div>
        <div class="form-group">
            <label th:for="userId">아이디</label>
            <input type="text" th:field="*{userId}"
                   th:class="${#fields.hasErrors('userId')}? 'form-control fieldError' : 'form-control'"/>
            <p th:if="${#fields.hasErrors('userId')}" th:errors="*{userId}"></p>
        </div>
        <div class="form-group">
            <label th:for="password">비밀번호</label>
            <input type="password" th:field="*{password}"
                   th:class="${#fields.hasErrors('userId')}? 'form-control fieldError' : 'form-control'"/>
            <p th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></p>
        </div>
        <div class="form-group">
            <label th:for="password_confirm">비밀번호 확인</label>
            <input type="password" th:field="*{password_confirm}"
                   th:class="${#fields.hasErrors('password_confirm')}? 'form-control fieldError' : 'form-control'"/>
            <p th:if="${#fields.hasErrors('password_confirm')}" th:errors="*{password_confirm}"></p>
        </div>
        <div class="form-group">
            <label th:for="gender">성별</label>
            <div class="form-control">
                <input type="radio" name="gender" value="male" checked="checked"/>남자
                <input type="radio" name="gender" value="female" />여자
            </div>
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
    <br/>
    <div th:replace="fragments/footer :: footer" />

    <script src="/js/members/address.js"></script>
</div> <!-- /container -->
</body>
</html>

 

실행결과

 

References

source code : https://github.com/yonghwankim-dev/spring_movie/commit/59cdf56ea81712d0084dc0710a627ad69250db62