티스토리 뷰
업무에서 파라미터 유효성 체크를 할 때 각 클래스마다 checkParam의 방식으로 유효성 체크를 해왔는데, 좀 더 편하게 할 수 있는 방법이 없을까 고민했고, 이 글은 고민했던 내용을 적은 것이다.
우선은 기존에도 가지고 있었지만 사용하지는 않았던 Validation을 사용해보기로 했다.
기본적인 흐름은 다음과 같다.
1. 컨트롤러의 메서드 호출
2. @Valid 어노테이션이 붙은 파라미터의 유효성 조건 체크
3. 유효성 조건을 만족하지 못하면 ControllerAdvisor의 해당 Exception의 ExceptionHandler 어노테이션이 붙은 메서드가 수행된다.
@Controller
@RequestMapping("/post")
public class TestPostController {
@ResponseBody
@PostMapping("/completeAjax")
public SingleResult completeAjax(@RequestBody @Valid Post post) {
// 예시라 비즈니스 로직 제외
SingleResult singleResult = new SingleResult(ResponseCode.OK);
return singleResult;
}
}
위와 같이 컨트롤러의 메서드가 있다고 하면 /post/completeAjax를 호출했을 때 Post의 유효성 검사를 하게 된다. 유효성 검사를 하게 될 때 사용하는 조건은 Post 클래스에 아래와 같이 정의한다.
@Getter
@Setter
@AllArgsConstructor
@ToString
public class Post {
@Size(min = 1, max = 10, message = "제목은 10자까지 가능합니다.")
private String title;
@Size(min = 1, message = "내용은 입력되어야 합니다.")
private String content;
}
위처럼 각 필드마다 조건을 정의하고, Exception이 발생했을 때의 메시지를 지정해줄 수 있다. 이 조건을 만족하지 못하면 BindException(혹은 MethodArgumentNotValidException)이 발생하게 되고, 그러면 이 Exception을 handle해주는 메서드를 호출하게 된다.
@ControllerAdvice
@RestController
public class ExceptionAdvisor {
@ExceptionHandler(BindException.class)
public BaseResult processValidationError(BindException exception) {
BindingResult bindingResult = exception.getBindingResult();
StringBuilder builder = new StringBuilder();
BaseResult baseResult = new BaseResult(ResponseCode.WRONG_PARAMETER_VALUE_ERROR);
if (bindingResult.hasFieldErrors()) {
for (FieldError fieldError : bindingResult.getFieldErrors()) {
builder.append(fieldError.getDefaultMessage());
}
}
baseResult.setResultMessage(builder.toString());
return baseResult;
}
}
위와 같이 처리했을 때 기존과는 다른 점이 몇 가지 생겼다.
1. 더 이상 컨트롤러 내부에서 파라미터 체크를 하지 않아도 된다. -> 코드가 자신이 할 일에만 집중되어 간결해진다.
2. 파라미터를 체크할 클래스에서 체크조건을 명시하기 때문에 유효성정책을 훨씬 더 알아보기 쉽다.
반면 아쉬운 점도 있었다. @ControllerAdvice는 적용범위를 아래의 조건에 따라 제한할 수 있다.
1. 특정 어노테이션을 가지고 있는지
2. 특정 패키지 이하에 존재하는지
3. 특정 클래스 타입인지
이때, 내가 원하는 조건에 따라 제한할 수가 없어서 그 부분이 아쉬웠다. 파라미터 체크를 한 후, 뷰를 돌려줘야할 수도 있고 객체를 돌려줘야할 수도 있는데 이 부분이 우리 업무구조상 같은 클래스에 존재하기 때문에 어떻게 뜯어내야할지 애매했다. 가장 간단한 방법은 그냥 ajax를 사용하거나 api처럼 객체를 돌려줘야할 때만 들어오는 파라미터에 @Valid를 사용하게 하는 것인데... 더 좋은 방법이 있을지 생각해봐야겠다.
'공부흔적 > 스프링' 카테고리의 다른 글
Transaction 관련 내부 코드 뜯어보기 (0) | 2022.08.02 |
---|---|
중첩된 @Transactional을 실험해보자 (0) | 2022.07.27 |
DispatcherServlet 뜯어보기 (0) | 2022.03.20 |
체크박스 객체로 받기 (0) | 2021.09.28 |
Spring mvc interceptor (0) | 2021.05.18 |