Spring

[Spring] 유효성 검사(Validating Form)

cornarong 2021. 8. 18. 01:06

사용해 보면서 테스트한 내용을 간단하게 정리한 글입니다.

 

validation이란 어떤 데이터의 값이 유효한지, 타당한지 확인하는 것을 의미한다.

즉 데이터 필드들의 값 존재 여부, 글자의 제한 등 해당 양식에 유효한지 판별하기 위해서 사용한다.

 

1. 의존성 주입

gradle

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

maven

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

 

2. 데이터 컨테이너 클래스

유효성을 검사가 필요한 데이터가 담긴 클래스를 선택한다.

아래 Board클래스는 id, title, contet를 프로퍼티로 사용하고 있고 유효성 검사가 필요하다고 가정 하자.

 

1. 편리한 어노테이션을 이용한 제약조건 사용

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class Board {
    private Long id;
    @NotNull
    @Size(min=2, max=30, message = "제목은 2자 이상 30자 이하 입니다.")
    private String title;
    private String content;
}

import는 javax.validation.constraints.xxx 이부분만 확인하면 된다.

javax에서 기본적으로 지원해주는 어노테이션들이 많이 있다.

(아래 정리가 잘된 블로그를 참조해 놓았습니다.)

 

위의 프로퍼티 'title'에는 NotNull과 Size의 제한(최소2, 최대30)을 사용하고 있다.

또한 어노테이션에 매개변수를 message를 추가하여 error메시지를 직접 넣어 사용할 수 있다.

 

이렇게 어노테이션을 이용하여 제약조건을 주는 방법 외에 

상황에 맞게 더 유연하게 아래와 같이 직접 커스텀할 수도 있다.

직접 Validator구현체를 만들어 마지막 남은 'content' 프로퍼티를 커스텀 해보자.

 

2. 제약조건을 유연하게 직접 커스텀하여 사용 (BoardValidator 클래스)

https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/validation.html

- 7.2 Validation using Spring's Validator interface 참고

import com.mytoy.bookstore.model.Board;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.thymeleaf.util.StringUtils;

@Component
public class BoardValidator implements Validator {
    @Override
    public boolean supports(Class<?> clazz) {
        return Board.class.equals(clazz); // 사용할 class = 'Board'
    }
	// validate는 컨트롤러에서 매개변수로 
    // 유효성을 검사할 클래스 객체와 바인딩 결과 BindingResult를 받게 된다.
    @Override
    public void validate(Object target, Errors errors) {
        Board board = (Board)target; // 전달받은 target을 Board타입으로 형변환
        // 입맛에 맞게 커스텀 한다.
        if(StringUtils.isEmpty(board.getContent())) {
        	// field = content , errorCode = "key" , dafaultMessage="내용을 입력하세요."
            errors.rejectValue("content", "key", "내용을 입력하세요.");
        }
    }
}

 

Controller 컨트롤러

    @Autowired
    private BoardValidator boardValidator;

위서 직접 커스텀한 BoardValidator 사용하기 위해 빈을 주입해준다.

@PostMapping("/add")
public String add(@Valid Board board, BindingResult bindingResult, RedirectAttributes riRedirectAttributes){
	boardValidator.validate(board, bindingResult);
    if (bindingResult.hasErrors()) {
   		return "board/addForm";
    }
    Board savedBoard = boardRepository.save(board);
    riRedirectAttributes.addAttribute("savedBoardId",savedBoard.getId());
    riRedirectAttributes.addAttribute("saved",true);
    return "redirect:/board/list/{savedBoardId}";
}

위의 "/add"로 post요청이 온 데이터를 유효성 검사해보자.

기존 사용하던 @ModelAttribute대신 @Valid를 사용한다

@Valid Board board와 BindingResult bindingResult를 선언해서 받아준다.

* BindingResult는 유효성을 검사할 객체 바로 뒤에 선언되어야 한다.

bindingResult.hasErrors가 true일 경우 addForm페이지로 돌아가도록 만들었다.

 

추가로 타임리프에서

th:if="${#fields.hasErrors('프로퍼티명')}" == true,

th:errors="*{프로퍼티명}" == "error메시지" 등을 사용하여 화면을 이쁘게 작업할 수 있다.

 

 


 

 

Reference

https://spring.io/guides/gs/validating-form-input/

https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/validation.html

 

* 추가로 어노테이션 정리가 잘되어있는 블로그를 발견해서 참조했습니다.

https://hyeran-story.tistory.com/81