본문 바로가기
Spring

[SpringBoot/Thymleaf] validation

by noddu 2022. 6. 28.
728x90
반응형

 

implementation 'org.springframework.boot:spring-boot-starter-validation'

bulid.gradle에 validation 의존성 추가한다


어노테이션 기능

어노테이션 설명
@Null null만 허용
@NotNull 빈 문자열(""), 공백(" ")은 허용하되, Null은 허용하지 않음
@NotEmpty 공백(" ")은 허용하되, Null과 빈 문자열("")은 허용하지 않음
@NotBlank null, 빈 문자열(""), 공백(" ") 모두 허용하지 않음
@Email 이메일 형식을 검사한다. 단, 빈 문자열("")의 경우엔 통과 시킨다. ( @Pattern을 통한 정규식 검사를 더 많이 사용
@Pattern(regexp = ) 정규식 검사할 때 사용
@Size(min=, max=) 길이를 제한할 때 사용
@Max(value = ) value 이하의 값만 허용
@Min(value = ) value 이상의 값만 허용
@Positive 값을 양수로 제한
@PositiveOrZero 값을 양수와 0만 가능하도록 제한
@Negative 값을 음수로 제한
@NegativeOrZero 값을 음수와 0만 가능하도록 제한
@Future Now 보다 미래의 날짜, 시간이어야 함
@FutureOrPresent Now 거나 미래의 날짜, 시간이어야 
@Past Now 보다 과거의 날짜, 시간이어야 
@PastFutureOrPresent Now 거나 과거의 날짜, 시간이어야 

domain(DAO,DTO)

public class Member {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY) // PK
    private Long id;

    @NotBlank(message = "이름은 필수 입력 값입니다.")
    private String name;

    @NotBlank(message = "비밀번호는 필수 입력 값입니다.")
    private String password;
    
    @Pattern(regexp = "^(?:\\w+\\.?)*\\w+@(?:\\w+\\.)+\\w+$", message = "이메일 형식이 올바르지 않습니다.")
    @NotBlank(message = "이메일은 필수 입력 값입니다.")
    private String email;

    @Pattern(regexp = "^[ㄱ-ㅎ가-힣a-z0-9-_]{2,10}$", message = "닉네임은 특수문자를 제외한 2~10자리여야 합니다.")
    @NotBlank(message = "닉네임은 필수 입력 값입니다.")
    private String nickname;
    }

 

domain에서 다음과 같이 유효성 검증으로 Pattern과

빈칸이면 안되는 컬럼을 NotBlank로 설정했다


Controller

@PostMapping("/register")
public String register(@Valid Member member, Errors errors, Model model){
    if (errors.hasErrors()) {

        /** 회원가입 실패시, 입력 데이터를 유지 */
        model.addAttribute("wrote", member);

        /** 유효성 통과 못한 필드와 메시지를 핸들링 */
        Map<String, String> validatorResult = userService.validateHandling(errors);
        for (String key : validatorResult.keySet()) {
            model.addAttribute(key, validatorResult.get(key));
        }
        return "account/register";
    }
    /** 중복 검사  */
    userService.checkNameDuplication(member);

    userService.save(member);
    
    return "redirect:/";
}

컨트롤러에서 Request 객체 앞에 @Valid 어노테이션을 사용하고, Errors를 통해 유효성 검사 적합 여부를 확인한다.

※ 이때 Errors는 반드시 Request 객체 바로 뒤에 위치해야 한다.

(두 개의 객체에 validation 검사를 한다면, 각각 객체 뒤에 Errors를 받도록 한다.)

 

그리고 hasErrors() 메서드를 통해 Request 객체에 설정한 유효성 검사에 문제가 있는지 확인하고,

 

문제가 있다면 원하는 데이터 형식으로 가공해서 사용하면 된다.


Service

/** 회원가입 시, 유효성 체크 */
public Map<String, String> validateHandling(Errors errors) {
    Map<String, String> validatorResult = new HashMap<>();

    for (FieldError error : errors.getFieldErrors()) {
        String validKeyName = String.format("valid_%s", error.getField());
        validatorResult.put(validKeyName, error.getDefaultMessage());
    }
    return validatorResult;
}

/** 아이디, 닉네임, 이메일 중복 여부 확인 */
public void checkNameDuplication(Member member) {
    boolean nameDuplicate = userDJRepository.existsByName(member.getName());
    if (nameDuplicate) {
        throw new IllegalStateException("이미 존재하는 아이디입니다.");
    }
}

유효성 검사에 실패한 필드들은 Map 자료구조를 이용해 키값과 에러 메시지를 응답한다.

Key : valid_member의 필드명

Message : Member(domain)에서 작성한 message 값

 

유효성 검사에 실패한 필드 목록을 받아 미리 정의된 메시지를 가져와 Map에 넣어준다.


register.html

 

<div class="form-floating">
    <input type="text" class="form-control" id="name" name="name" th:value="${wrote?.name}" placeholder="Username"
           oninput="Check()">
    <label for="name">Username</label>
    <span id="checkId" class="check" th:text="${valid_name}"></span>
</div>


<div class="form-floating">
    <input type="password" class="form-control" id="floatingPassword" name="password" placeholder="Password">
    <label for="floatingPassword">Password</label>
    <span class="check" th:text="${valid_password}"></span>
</div>

<div class="form-floating">
    <input type="text" class="form-control" id="email" name="email" th:value="${wrote?.email}" placeholder="Email"
           oninput="Check()">
    <label for="email">Email</label>
    <span id="checkEmail" class="check" th:text="${valid_email}"></span>
</div>

Service 계층에서 에러 객체의 Key 이름을 valid_%s로 설정해놨기 때문에 valid_필드명으로 작성한다.

 


https://fpem3309.tistory.com/121

 

[SpringBoot/Thymeleaf] ajax 회원가입 중복체크 (Spring Data JPA)

register.html oninput으로 script의 함수를 설정해서 입력을 받으면 즉시 DB에서 비교할 수 있다. id값이 name인 input에 작성한 값을 ajax로 /account/check의 경로로 보낸다(Controller) 그리고 그에 따라 적당..

fpem3309.tistory.com

Exception이 에러페이지로만 나타나서

중복회원이면 회원가입 버튼을 못하게 바꾸고

여러가지 추가했다

 


출처: https://dev-coco.tistory.com/124 [슬기로운 개발생활:티스토리]

 

 

반응형