일친 (IlChin) - Spring Validation 적용

no.oneho·2025년 6월 11일
0

일친 개발기

목록 보기
16/17

이제 dto별 유효성 검증을 하도록 하겠다.

이전에 만든 메서드가 있긴있지만 해당 메서드는 여러번 dto가 재사용될 때 유효성 검증 항목이 상이할 때만 사용하고 일반적으론 편하게 Spring Validation을 쓰도록 하겠다.

먼저 의존성을 받아준다

build.gradle

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

그리고 사용할 dto나 파일에 가서 붙여준다

public record CreateReq(
        @NotBlank(message = "부서명은 빈 값일 수 없습니다.") String name,
        @NotBlank(message = "부서설명은 빈 값일 수 없습니다.") String description,
        @NotNull(message = "부서장을 선택해주세요.") Long managerUserId,
        String tel
) {
}

가장 많이 사용하는게 @NotNull, @NotEmpty, @NotBlank 이렇게 세가지이다.

서로 역할이 조금씩 다르므로 주의하도록 한다.
@NotNull: Null값만 검증 실패
@NotEmpty: Null과 "" 빈 문자열만 검증 실패
@NotBlank: Null과 ""및 " "와 같이 공백문자만 존재하는 문자열도 검증 실패

여기서 NotEmpty, NotBlank는 검증하는 "" 자체가 이미 문자열이므로 문자열타입에만 적용 가능한 검증이다.

그 외 타입에서 null검사를 하고싶으면 @NotNull을 사용하자

그리고 컨트롤러에 가서

@Auth
    @PostMapping
    public Response<DepartmentResp> createDepartment(@RequestBody @Valid CreateReq createReq) {
        return Api.success(200, "부서 생성 완료", departmentService.createDepartment(createReq));
    }

@Valid 라는 어노테이션을 인자로 받을 dto앞에 붙여주면 끝








진짜 끝일까?

한번 실제로 api를 호출해보면

이와같이 정돈되지않은 에러메시지가 그대로 노출이 되어버리는데
Spring Validation에서 잡힌 Exception도 advice에서 따로 처리를 해줘야한다.

  @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Response<Map<String, String>>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        Map<String, String> errors = new HashMap<>();
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        for (FieldError fieldError : fieldErrors) {
            errors.put(fieldError.getField(), fieldError.getDefaultMessage());
        }
        Response<Map<String, String>> errorResponse = Api.error(HttpStatus.BAD_REQUEST, "유효성 검증에 실패하였습니다.", errors);
        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
        
    }

나는 이런느낌으로 만들었다. MethodArgumentNotValidException에서 유효성 검증이 실패한 필드와 해당 메시지는 List fieldErrors = e.getBindingResult().getFieldErrors(); List를 만들어 가져 올 수 있고
각 인덱스마다 getField()와 getDefaultMessage() 로 꺼내서 쓸 수 있다.

그럼 다시 API를 호출해보자

이제 원하는대로 잘 나온다. 프론트 개발자 입장에선 key을 통해 컴포넌트를 참조해서 에러이벤트를 화면에 띄어주면 될 거 같다.

아마 실제 개발환경이였다면 http status를 400이 아닌 999같이 커스텀해서 유효성 검증용 에러코드로 전달해드렸을듯..?

profile
이렇게 짜면 요구사항이나 기획이 변경됐을 때 불편하지 않을까? 라는 생각부터 시작해 설계를 해나가는 개발자

0개의 댓글