Spring | Java Bean Validation

바다·2024년 5월 20일
0

Spring

목록 보기
6/13
post-thumbnail

Bean Validation이란?

검증 기능을 매번 코드로 작성하는 것이 아닌, 어노테이션을 활용하여 모든 프로젝트에 공통적으로 적용할 수 있는 기술

  • 어노테이션 형태로 제약 조건을 달아주어 쉽게 검증할 수 있도록 돕는 API
  • Bean Validation은 특정한 구현체가 아니라 Bean Validation 2.0(JSR-380) 이라는 기술 표준
  • Bean Validation을 구현한 기술 중에서 일반적으로 사용하는 구현체는 하이버네이트 Validatior

하이버네이트 Validator 관련 링크


Bean Validation 사용하기

1. 의존관계 추가하기

build.gradle 파일에 dependency 추가

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

2. 객체에 어노테이션 적용하기

검증이 필요한 필드 위에 어노테이션을 적용하여서 제약 조건을 달아 준다

(제약 조건을 나타내는 어노테이션과 관련된 내용은 아래에서 자세하게 다루어볼 예정이다)

public class ScheduleRequestDTO {

	@NotBlank(message = "제목을 입력해주세요.")
	@Size(min = 1, max = 200, message = "제목은 1자 이상, 200자 이내로 입력해주세요.")
	private String title;

	@NotBlank(message = "내용을 입력해주세요.")
	@Size(min = 1, message = "내용은 1자 이상 입력해주세요.")
	private String contents;

	@NotBlank(message = "이메일을 입력해주세요.")
	@Email(message = "이메일 형식을 지켜주세요.")
	private String email;

	@NotBlank(message = "비밀번호를 입력해주세요.")
	private String password;
}

3. 컨트롤러에서 사용하기

검증이 필요한 객체 앞에 @Valid or @Validated 어노테이션 붙이기

@PostMapping
public ResponseEntity<ResponseMessage<ScheduleResponseDTO>> saveSchedule(@Valid @RequestBody ScheduleRequestDTO requestDTO) {
	ScheduleResponseDTO responseDTO = scheduleService.saveSchedule(requestDTO);

	ResponseMessage<ScheduleResponseDTO> responseMessage = ResponseMessage.<ScheduleResponseDTO>builder()
		.statusCode(HttpStatus.CREATED.value())
		.message("일정이 추가되었습니다.")
		.data(responseDTO)
		.build();

	return new ResponseEntity<>(responseMessage, HttpStatus.CREATED);
}

해당 어노테이션을 선언한 곳에 유효성 검증을 실패하면, MethodArgumentNotValidException으로 에러가 발생한다

4. Exception Handler

  • 유효성 검증을 실패하면, 에러 메시지를 출력할 수 있도록 작업하는 과정
  • 해당 과정은 필수가 아님! 원하는 방식으로 Exception을 핸들링 해주면 됨
@ControllerAdvice
public class GlobalExceptionHandler {
 @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
                .map(error -> error.getField() + " " + error.getDefaultMessage())
                .collect(Collectors.joining(", "));
        return new ResponseEntity<>(message, HttpStatus.BAD_REQUEST);
    }
}

5. 확인하기

1) 스케줄 저장

request

{
    "title":"test",
    "contents":"hello",
    "email":"heesue@gmail.com",
    "password":"1234"
}

response

{
    "statusCode": 201,
    "message": "일정이 추가되었습니다.",
    "data": {
        "id": 25,
        "title": "test",
        "contents": "hello",
        "email": "heesue@gmail.com",
        "createDate": "2024-05-18T23:09:11.411277",
        "modifyDate": "2024-05-18T23:09:11.411277"
    }
}

2) 제목 없음

request

{
    "title":"",
    "contents":"hello",
    "email":"heesue@gmail.com",
    "password":"1234"
}

response

title 제목을 입력해주세요., title 제목은 1자 이상, 200자 이내로 입력해주세요.

3) 이메일 형식 아님

request

{
    "title":"test",
    "contents":"hello",
    "email":"heesue",
    "password":"1234"
}

response

email 이메일 형식을 지켜주세요.

검증 어노테이션

jakarta Bean Validation API

자바에서 지원하는 Validation

@Null

  • Null 값만 입력 가능

@NotNull

  • Null이 아닌 값만 입력 가능

@NotEmpty

  • Null과 빈 문자열이 아닌 값만 입력 가능

@NotBlank

  • Null, 빈 문자열, 스페이스만 있는 문자열이 아닌 값만 입력 가능

@Size(min =, max=)

  • 해당 값의 최소값과 최대값 내의 값만 입력 가능

@Max(value=) / @Min(value=)

  • 해당 값의 최대값/최소값 내에서만 입력 가능

@Pattern(regex=, flags=)

  • 해당 값의 유효성 패턴을 지정
  • 정규식 검사를 할 때 사용
  • 예시) 휴대폰 번호에 대한 Pattern
    @Pattern(regexp="\\(\\d{3}\\)\\d{3}-\\d{4}")

@Email

  • 이메일 형식만 입력이 가능하다
  • 단, 빈 문자열의 경우엔 통과된다
  • @Pattern을 통한 정규식 검사를 더 많이 사용한다

@Future

  • 입력된 날짜는 미래의 날짜여야 함

@Past

  • 입력된 날짜는 과거의 날짜여야 함

@AssertFalse/ @AssertTrue

  • 입력된 값이 flase 또는 true여야 함

Hibernate Validation

하이버네이트에서 제공하는 사용자 정의 제약 조건

@CreditCarNumber(ignoreNondigitCharacteres=)

  • 입력된 문자 시퀀스가 Luhn 체크섬 테스트를 통과하는지 확인
  • 신용카드 유효성이 아닌 사용자 실수를 확인하는 것을 목표로 함

@Currency(value=)

  • 입력된 값이 javax.money.MonetaryAmount에 지정된 통화 단위의 일부인지 확인

@URL(protocol=, host=, port=, regexp=, flags=)

  • 입력된 값이 RFC2396에 따라 유효한 URL인지 확인

@EAN

  • 입력한 값이 유효한 EAN(국제 상품 번호
    ) 바코드인지 확인
  • 기본값은 EAN-13

@ISBN

  • 입력된 갑이 유효한 ISBN(국제 표준 도서 번호)인지 확인
  • 기본 값은 ISBN-13

이 외에도...

소개한 어노테이션 외에도 공식 문서를 찾아보면, 우리가 개발할 때 필요한 어노테이션들이 거의 다 제공되고 있다!

+그리고 사용자 정의 제약 조건을 구성하여 사용할 수도 있다
하지만, 내가 아직 거기까지 사용할 것 같진 않으니... 해당 내용은 이후에 다루어 보겠다!

사용자 정의 제약 조건 구성 예시

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MyConstraintValidator.class)
public @interface MyConstraint {
}
profile
ᴘʜɪʟɪᴘᴘɪᴀɴs 3:14

0개의 댓글