[Spring Boot] Validation+@Valid를 적용한 값의 유효성 검증

손은실·2024년 8월 7일
0

Spring Boot

목록 보기
3/11
post-thumbnail

해당 포스팅의 실제 코드는 EunsilSon - BookMarky에서 확인할 수 있습니다.


유효성 검증이 필요한 이유

'사용자의 입력 값을 프론트에서 검증하면 항상 알맞은 값을 넘겨줄테니 백에서는 검증할 필요가 없지 않나?' 라는 생각을 했습니다.

하지만 프론트와 백 모두 검증이 필요하다는 것을 알게되었습니다.

Front: 값에 대한 즉각적인 피드백과 서버 전송 전 잘못된 입력 필터링
Back: SQL Injection, XSS 공격 등 보안상 문제와 데이터 무결성 보장

양 쪽에서 값을 검증해 안전하고 효율적인 웹을 구축할 수 있습니다.


유효성 검증이란?

데이터 필드가 미리 정의한 규칙을 지키는 값인지 확인하는 것입니다.
해당 포스팅에서는 Spring Validation을 적용해 유효성 검증을 수행했습니다.

Spring Validation
클라이언트가 전달하는 데이터에 대해 유효성 검증을 수행해 예외를 발생시키고 이를 처리하는 기능을 수행하는 라이브러리


개발 환경

  • Java 17
  • Spring Boot 3
  • MySQL
  • spring-boot-starter-validation

1. @Valid 유효성 검증

🟢 build.gradle

💡 유효성 검증을 수행 할 매개변수에 @Valid 어노테이션을 주입합니다. 어노테이션 주입을 위해 필요한 Validation 의존성을 추가합니다.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-validation'
}


자주 사용되는 Validation 어노테이션 종류

Validation with Spring Boot - the Complete Guide 를 참고했습니다.

  • @NotNull: null 불가능

  • @NotEmpty: null, "" 불가능

  • @NotBlank: null, "", " " 불가능

  • @Min: 최솟값을 벗어나는지

  • @Max: 최댓값을 벗어나는지

  • @Pattern: 문자열 필드가 정규표현식과 일치하는지

  • @Email: 문자열 필드가 이메일 형식과 일치하는지


🟢 UserController

💡 클라이언트로부터 @RequestBodyVO 형태로 데이터를 받고, @Valid를 통해 유효성 검증을 수행합니다.
💡 유효성 검증을 수행 할 매개변수에 @Valid 어노테이션을 주입합니다.

클라이언트의 요청이 Service 레이어로 전달되기 전에, 요청을 직접적으로 받는 Controller에서 유효성 검사를 수행하므로 잘못된 데이터가 전달되는 것을 방지할 수 있게 됩니다.

유효성 검증에 실패했을 때, MethodArgumentNotValidException 에러가 발생합니다.



🟢 UserVO

💡 유효성 검증이 필요한 클래스의 변수에 @Pattern 를 주입해 정규표현식으로 입력값에 규칙을 적용합니다.

<코드에 적용한 규칙>

  • 이메일 - 이메일 형식
  • 휴대폰 번호 - 숫자와 하이픈
  • 닉네임 - 아이디 대소문자 및 한글
  • 비밀번호 - 대소문자, 숫자 5개 이상, 특수 문자 포함 2개 이상


2. 제약조건 위반 예외 처리

미리 지정한 제약조건에 맞지 않는 데이터의 경우 MethodArgumentNotValidException을 반환합니다.
해당 예외를 처리하는 핸들러를 구현해 응답 메세지를 깔끔하게 만들어 보겠습니다.

@RestControllerAdvice 전역 예외 처리

@RestControllerAdvice
전역으로 Rest 컨트롤러의 예외를 처리하는데 사용되며, 예외 핸들러 메서드의 반환 값을 JSON 또는 XML 형식으로 응답 본문에 작성합니다.

저는 @RestControllerAdvice 를 주입한 핸들러 클래스를 만들어 직접 정의한 실패 응답 객체를 반환했습니다.
이때 객체가 정상적으로 전달되었을 때 요청의 결과는 실패임에도 불구하고 HTTP 상태 코드는 200 OK 가 반환되기 때문에, ResponseEntity를 통해 HTTP 상태 코드와 함께 객체를 반환했습니다.



🟢 Handler

💡 UserController에서@Valid 어노테이션을 주입해 유효성을 검증할 때 실패한 경우 발생하는 예외를 미리 정의한 이 Handler 클래스에서 처리하게 됩니다.

예외 처리 흐름
MethodArgumentNotValidException 예외 발생
@ExceptionHandler 가 이를 가로챔
▶ 미리 정의된 핸들러 메서드 실행

  • @ExceptionHandler(MethodArgumentNotValidException.class) :
    MethodArgumentNotValidException 발생 시 아래 메서드를 실행
  • e.getStatusCode().value() : HTTP 상태 코드를 int 타입
  • e.getBindingResult().getAllErrors().get(0).getDefaultMessage() :
    직접 지정한 @Pattern 의 message
    • get(0) 으로 지정했기 때문에 여러 필드에 대한 유효성 검증이 실패해도 첫 필드에 대한 메세지만 출력

🟢 CommonResponse: 응답 객체


🟢 ResponseService: 응답 객체를 만드는 서비스



3. 테스트

예외 처리 전

어떤 필드에서 어떤 이유로 제약조건이 위배되었는지 알 수 없는 응답 메세지입니다.

@Pattern 위배

@Size 위배

실패 응답 메세지와 HTTP 상태 코드까지 깔끔하게 반환되어 실패 원인을 빠르게 알 수 있게 되었습니다. 😄

0개의 댓글