Spring발행일 2024. 10. 9.원본 https://blog.naver.com/jword_/223611524502 ↗

kotlin Spring Validation 기능을 사용해보자

kotlin Spring Validation 기능을 사용해보자 — #kotlinspring #코틀린spring #springvalidation #개발자의도구들 🚨📝 📖 📒✏️💡🔍 AI스...

#Spring#Naver Blog

#kotlinspring #코틀린spring #springvalidation #개발자의도구들

🚨📝 📖 📒✏️💡🔍

이미지

​

AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니다

\* 현재 Spring 프로젝트를 진행 중입니다. 전체적인 목차를 보시려면 여기를 눌러주세요.

서버는 데이터를 어떻게 검증하는가

Validation 사용이유

거의 모든 서버는 회원가입시에 다양한 요구사항을 보냅니다. 예를들어 비밀번호의 조합이라던지, 닉네임의 길이, id길이 등 등 다양한 것들을 요구하는데요.

​

실제로는 이런 요구사항을 서버에서는 어떻게 하나 하나 검증을 수행할까요? 오늘은 이 부분에 대한 하나의 답이 될 수 있는 Spring Validation 기능을 알아봅시다.

Spring Validation

사실 서버에서 하는 동작은 간단합니다. 문자열에서 특정 패턴을 찾아내거나, 길이를 찾아서 임계값과 비교하는 식으로 설정하면 됩니다. 이건 누구나 생각할 수 있는 아이디어지만, 구현하기에는 너무 번거롭습니다.

​

Spring은 이런 부분을 해결하기 위해 검증을 쉽게 할 수 있도록 Validation이라는 강력한 기능을 제공합니다.

build.gradle

javascript 코드 예제
                                    implementation("org.springframework.boot:spring-boot-starter-validation:3.3.4")

해당 의존성을 추가해주세요. 버전은 작성 시점 기준 3.3.4가 최신이었습니다.

​

@

기본적으로 지원하는 Annotaion들에 대해 간략하게 정리했습니다.

javascript 코드 예제
                                    @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 필드에 @을 사용하여 검증을 수행합니다.

​

javascript 코드 예제
                                    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

javascript 코드 예제
                                    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를 사용하여 구현할 수 있습니다.

javascript 코드 예제
                                    🙆‍♀️ passy libary를 통해 Custom한 @을 등록하여 사용이 가능합니다.

테스트

현재 validation 실패시 message가 제대로 보내지지 않아서 오류 수정 후 작성하겠습니다.