@Valid 를 사용하기 위해 implementation 'org.springframework.boot:spring-boot-starter-validation'
추가 후,
LoginRequest.kt
data class LoginRequest(
@field:Email(message = "올바른 이메일 형식이 아닙니다.")
@field:NotBlank(message = "이메일을 입력해주세요")
val email: String,
@field:NotBlank(message = "비밀번호를 입력해주세요")
val password: String,
)
SignUpRequest.kt
data class SignUpRequest(
@field:Email(message = "올바른 이메일 형식이 아닙니다.")
@field:NotBlank(message = "이메일을 입력해주세요")
val email: String,
@field:NotBlank(message = "닉네임을 입력해주세요")
val nickName: String,
@field:NotBlank(message = "비밀번호를 입력해주세요")
val password: String,
@field:NotBlank(message = "'MEMBER'/'ADMIN' 중 역할을 입력해주세요")
val role: String,
)
Validation 관련 annotation에 @field:를 prefix로 붙이고 message에 출력문을 적어준다.
AppUserController.kt
@PostMapping("/login")
fun login(@Valid @RequestBody loginRequest: LoginRequest): ResponseEntity<LoginResponse> {
return ResponseEntity
.status(HttpStatus.OK)
.body(appUserService.login(loginRequest))
}
}
@RequestBody에 대한 validation 에러는 MethodArgumentNotValidException이다.
GlobalExceptionHandler.kt
@ExceptionHandler(MethodArgumentNotValidException::class)
fun handleMethodArgumentNotValidException(e: MethodArgumentNotValidException): ResponseEntity<ErrorResponse> {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(ErrorResponse(e.bindingResult.allErrors.map { it.defaultMessage }.reduce { acc, string -> "$acc, $string" }))
}
}
ErrorResponse로 반환할 때
e.bindingResult -> 유효성 검사에서 발생한 모든 오류를 가져온다.
.map { it.defaultMessage } -> 각 오류의 기본 메시지를 추출한다.
.reduce { acc, cur -> "$acc, $cur" } -> 모든 메시지를 하나의 문자열로 결합한다. 각 메시지는 컴마로 구분되고 모든 메시지가 단일 문자열로 결합한다.
컨트롤러에서 실행되는 유효성 검사 실패에 대한 모든 메시지를 하나의 문자열로 합쳐서 클라이언트에세 전달할 에러 응답문을 생성한다.
reduce()를 실행하면 하나의 결과값을 반환한다.
줄이다라는 뜻 그 자체의 성질을 가지며 축적되며 줄여나간다.
acc
accumulator : 누산기, 누적되는 값, 최종적으로 출력되는 값
cur
current : 현재 돌고 있는 요소