코틀린 스프링 3번째 시간입니다.
회원 가입 시에 받는 정보를 확인하는 validation을 만들어보겠습니다
이 기록 겸 강의는 초보자 기준으로 작성이 되었고, 새로 시작하게 된 코틀린 스프링 유저에게 많은 도움이 될 수 있었다면 좋겠다는 마음으로 시작합니다.
틀린 부분이 있다면 알려주시면 감사하겠습니다.
시작과 앞서 Maven Repository를 소개해드리겠습니다.
[프로젝트] Kotlin Spring 00. 초기 설정
여기 전에 강의에서 Dependencies를 추후에 추가한다라는 말을 드렸습니다.
그 의존성을 검색하고 얻어오는 곳이 Maven Repository입니다.
Maven Repository: Search/Browse/Explore
여기 상단에 검색창에 validation을 검색하게 되면
3번째 Spring Boot Starter Validation을 클릭합니다.
상단 3.3.5를 눌러보겠습니다. 만약 다른 버전이 보인다면 가장 위에 있는 것을 눌러주시면 됩니다.
Gradle(Kotlin) 항목에 있는 코드를 사용합니다
implementation("org.springframework.boot:spring-boot-starter-validation")
거기서 뒷부분에 해당하는 버전을 지우기 때문에 어떤 버전을 고르셔도 상관이 없습니다.
InteliJ에서 Gradle빌드 다시 진행해 주시고 코드 수정 들어가겠습니다.
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Constraint(validatedBy = [ValidEnumValidator::class])
annotation class ValidEnum(
val message: String = "Invalid enum Value",
val groups: Array<KClass<*>> = [],
val payload: Array<KClass<out Payload>> = [],
val enumClass: KClass<out Enum<*>>
)
class ValidEnumValidator: ConstraintValidator<ValidEnum, Any>{
private lateinit var enumValues: Array<out Enum<*>>
override fun initialize(annotation: ValidEnum) {
enumValues = annotation.enumClass.java.enumConstants
}
override fun isValid(value: Any?, context: ConstraintValidatorContext?): Boolean {
if(value == null){
return true
}
return enumValues.any { it.name == value.toString() }
}
}
- @Target(AnnotationTarget.FIELD) : 어노테이션 클래스에 지정되어 사용할 종류를 정의합니다.
- @Retention(AnnotationRetention.RUNTIME) : 어노테이션을 런타임에 반영한다는 것을 정의합니다.
- @MustBeDocumented : API의 일부분으로 문서화를 도와줍니다
- @Constraint(validatedBy = [ValidEnumValidator::class]) : ValidEnumValidator클래스에 의해 검증된다는 내용입니다.
- annotation class ValidEnum(
- message: 유효성 검사 실패 시 표시되는 내용입니다. 기본값으로 "Invalid enum Value"를 적용시켰습니다.
- groups: 그룹을 정의할 수 있는 배열입니다. 기본값은 빈 배열입니다.
- payload: 추가정보를 담을 수 있는 배열입니다. 기본값은 빈 배열입니다.
- enumClass: 검증할 열거형 클래스입니다.
- 검증기 클래스인 ValidEnumValidator에서 ValidEnum 어노테이션을 검증합니다.
- enumValues를 통해 검증할 열거형 값들을 저장하고
- initialize를 통해 어노테이션이 초기화될 때 호출되어, 열거형 값을 설정합니다.
- isValid에서 주어진 값이 유효한지 검증하는 메서드입니다. null일 경우 유효한 것으로 간주하고 아니라면 열거형 값 중 하나와 일치하는지 확인합니다.
만들었으니 이제 적용을 해보겠습니다.
dto를 열어줍니다
data class MemberDtoRequest(
val id: Long?,
@field:NotBlank
@JsonProperty("loginId")
private val _loginId: String?,
@field:NotBlank
@field:Pattern(
regexp="^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#\$%^&*])[a-zA-Z0-9!@#\$%^&*]{8,20}\$",
message = "영문, 숫자, 특수 문자를 포함한 8~20 자리로 입력 해주세요"
)
@JsonProperty("password")
private val _password: String?,
@field:NotBlank
@JsonProperty("name")
private val _name: String?,
@field:NotBlank
@field:Email
@JsonProperty("email")
private val _email: String?,
@field:NotBlank
@field:ValidEnum(enumClass = Area::class,
message = "해당 코드로 입력 해 주세요.")
@JsonProperty("area")
private val _area: String?,
) {
val loginId: String
get() = _loginId!!
val password: String
get() = _password!!
val name: String
get() = _name!!
val email: String
get() = _email!!
val area: Area
get() = Area.valueOf(_area!!)
}
특이사항을 설명드리면 캡슐화를 위해 private로 선언하고, 이름을 변경하고, 그로 인해 받아올 JSON의 이름이 달라지기에 @JsonProperty를 이용해 원래 이름과 연결시켜 줍니다.
@field:NotBlank를 이용해 빈 값을 불가능하게 하고, 비밀번호의 경우 패턴을 주어 안전성을 올려줍니다.
또 다른 하나는 Area라는 객체가 생겼습니다. 지역별로 코드값을 지정했습니다.
제가 설정한 값 이외에 값이 오면 반환시키게끔 했습니다.
쉽게 설명하면 강원도 강원도특별차지도 이렇게 두 가지 방법으로 받게 되면 다른 지역이 되기 때문에 하나로 통일한 것입니다.
이를 활용해서 성별을 받아오는 것도 가능합니다.
남, 남자, man, male 여러 가지 있는 값을 하나의 상황으로 만들어 준다고 볼 수 있겠습니다.
그 Enum 클래스를 설정하는 곳을 보겠습니다.
core > status패키지를 생성해 주시고 EnumStatus.kt를 만들어줍니다
enum class Area(val des: String){
SEOU("서울"),
BUSA("부산"),
DAEG("대구"),
INCH("인천"),
GWAN("광주"),
DAEJ("대전"),
ULSA("울산"),
SEJO("세종"),
GYEO("경기"),
GANG("강원"),
CHUB("충북"),
CHUN("충남"),
JEOB("전북"),
JEON("전남"),
GYUB("경북"),
GYUN("경남"),
JEJU("제주")
}
영어 Issues로 인해 코드가 난해한 점 죄송합니다.
마지막으로 Controller를 수정해 주겠습니다.
@PostMapping("signup")
fun signUp(@RequestBody @Valid memberDtoRequest: MemberDtoRequest): BaseResponse<Unit>{
val resultMsg : String = memberService.signUp(memberDtoRequest)
return BaseResponse(message = resultMsg)
}
@Valid가 있으면 DTO에 데이터를 담은 후에 검사가 진행됩니다.
이렇게 오늘은 정형화된 값으로만 받을 수 있게끔 수정해 봤습니다.
- 비밀번호 암호화
- 로그인 및 다른 기능들
정형화되지 않은 Dto값들을 처리할 방법- 오류 제어
- 그 이외의 것들
추가적으로 달려서 더 추가해 가면서 만들어 나아가 보겠습니다.
부족한 글 읽어 주셔서 감사합니다.
피드백은 언제든 환영입니다.
'BackEnd > 코틀린 스프링' 카테고리의 다른 글
[Kotlin Spring] 프로젝트 04. JWT를 이용해 로그인 구현하기 01: JWT토큰 생성 (1) | 2024.11.04 |
---|---|
[Kotlin Spring] 프로젝트 Extra00. InteliJ에서 http통신 보내기 (0) | 2024.10.29 |
[Kotlin Spring] 프로젝트 03. 예외 처리 (1) | 2024.10.29 |
[Kotlin Spring] 프로젝트 01. 회원 가입 만들기 (1) | 2024.10.28 |
[Kotlin Spring] 프로젝트 00. 프로젝트 초기 설정 (4) | 2024.10.27 |