kotlin Spring Validation 기능을 사용해보자
kotlin Spring Validation 기능을 사용해보자 — #kotlinspring #코틀린spring #springvalidation #개발자의도구들 🚨📝 📖 📒✏️💡🔍 AI스...
#kotlinspring #코틀린spring #springvalidation #개발자의도구들
🚨📝 📖 📒✏️💡🔍
AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니다
\* 현재 Spring 프로젝트를 진행 중입니다. 전체적인 목차를 보시려면 여기를 눌러주세요.
서버는 데이터를 어떻게 검증하는가
Validation 사용이유
거의 모든 서버는 회원가입시에 다양한 요구사항을 보냅니다. 예를들어 비밀번호의 조합이라던지, 닉네임의 길이, id길이 등 등 다양한 것들을 요구하는데요.
실제로는 이런 요구사항을 서버에서는 어떻게 하나 하나 검증을 수행할까요? 오늘은 이 부분에 대한 하나의 답이 될 수 있는 Spring Validation 기능을 알아봅시다.
Spring Validation
사실 서버에서 하는 동작은 간단합니다. 문자열에서 특정 패턴을 찾아내거나, 길이를 찾아서 임계값과 비교하는 식으로 설정하면 됩니다. 이건 누구나 생각할 수 있는 아이디어지만, 구현하기에는 너무 번거롭습니다.
Spring은 이런 부분을 해결하기 위해 검증을 쉽게 할 수 있도록 Validation이라는 강력한 기능을 제공합니다.
build.gradle
implementation("org.springframework.boot:spring-boot-starter-validation:3.3.4")
해당 의존성을 추가해주세요. 버전은 작성 시점 기준 3.3.4가 최신이었습니다.
@
기본적으로 지원하는 Annotaion들에 대해 간략하게 정리했습니다.
@NotNull: 해당 데이터가 Not Null 이어야 함
@NotEmpty: 해당 데이터가 Not Null이며, 비어 있지 않아야 함
@NotBlank: 해당 데이터가 Not Null이며, 공백 문자열이 아니어야 함
@Size: 문자열, 배열 등의 크기가 지정된 범위 내에 있어야 한다.
ex) @Size(min = 6, max = 14)
val password: String? = null
@Min, @Max : 숫자 값이 지정한 최소/최대 일 것
ex) @Min(Value = 19)
var age: Int? = null,
@Email: 문자열이 유효한 이메일 형식이어야 함
@Pattern: 정규 표현식을 사용하여 문자열 패턴을 지정할 수 잇다.
ex) @Pattern(regxp = "^[a`zA-Z0-9]+$", message = "Username must be alphanumeric")
@Past, @Future: 날짜가 과거, 미래 여야 한다.
이 정도가 활용성이 높은 것 같고, 나머지는 또 추가로 찾아보시면 될 것 같습니다. 전체를 다루기에는 너무 많아요.
DTO
이 validation기능은 Client의 데이터를 검증하는 것 입니다. Client의 Request로 넘어오는 JSON 데이터를 보통 DTO로 변환하여 사용하는게 일반적인데요. 고로 DTO 필드에 @을 사용하여 검증을 수행합니다.
package com.example.frontServer.dto
import com.example.frontServer.annotaion.ValidBirthday
import com.example.frontServer.annotaion.ValidPassword
import com.example.frontServer.enum.RoleNumber
import jakarta.validation.constraints.Email
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.NotEmpty
import jakarta.validation.constraints.Pattern
import java.time.LocalDate
data class SignUpRequest (
@field:NotEmpty(message = "id is required")
@field:NotBlank(message = "id can't contain blank")
@field:Pattern(
regexp = "^[a-zA-Z0-9]+$", // alphabet & number only !!
message = "Username must not contain spaces or special characters"
)
val username: String,
// custom @ with passy
@field:ValidPassword(message = "password must have Character, number and special Char at least one")
@field:NotEmpty
val password: String,
@field:Email(message = "Email format is invalid")
@field:NotEmpty(message = "email is required")
val email: String,
val introduction: String? = null,
// custom @ with passy
@field:ValidBirthday(message = "Birth date must be after 2012 and before today")
@NotEmpty
val birthday: LocalDate,
val country: String? = null,
var role: RoleNumber = RoleNumber.NORMAL
)//
\*message는 오류가 나는 경우 Client에게 전달됩니다.
위와 같은 방법으로 DTO에 사용하면 되고, 해당 DTO를 전달 받는 Controller에서 @Valid를 선언해주어야 합니다.
Controller
package com.example.frontServer.controller
import com.example.frontServer.dto.GetUserResponse
import com.example.frontServer.dto.ResponseToClientDto
import com.example.frontServer.dto.SignUpRequest
import com.example.frontServer.enum.ResponseCode
import com.example.frontServer.enum.SignUpStatus
import com.example.frontServer.service.UserService
import io.github.oshai.kotlinlogging.KotlinLogging
import jakarta.validation.Valid
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
@RestController
class UserController(
private val userService: UserService
) {
private val logger = KotlinLogging.logger {}
@PostMapping("/sign-up")
fun signUp(
@Valid @RequestBody signUpRequest: SignUpRequest
): ResponseEntity<ResponseToClientDto> {
--
}
}
@Valid 어노테이션이 붙은 Class의 @Field를 참고하여 유효성 검사를 진행합니다. 참고로 비밀 번호 같은 경우에는 워낙 다양한 패턴이 존재하다 보니, passy와 같은 유명 library를 사용하여 구현할 수 있습니다.
🙆♀️ passy libary를 통해 Custom한 @을 등록하여 사용이 가능합니다.
테스트
현재 validation 실패시 message가 제대로 보내지지 않아서 오류 수정 후 작성하겠습니다.
