Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 카카오 인턴
- Python
- 알고리즘
- 징검다리 건너기
- 튜플
- 티스토리
- 호텔 방 배정
- Open API
- Spring Boot
- pycon
- Tistory
- 프로그래머스
- jdbc
- bulk update
- 트라이
- trie
- 티스토리 open api
- 트라이 #trie #알고리즘
- 크레인 인형뽑기 게임
- 가사 검색
- 불량 사용자
- CleanCode
- 보행자 천국
Archives
- Today
- Total
택시짱의 개발 노트
Kotlin Spring Boot 중첩 클래스에 @Valid 사용 - feat) 이모지 체크(Emoji Valid) 본문
입력 값에 대한 Validation 처리 필요할 때가 있다
예를들어 아래와 같은 User를 생성하는 간단한 예제가 있을때
@RestController
@RequestMapping("/user")
class UserController(
private val userUseCase: UserUseCase,
){
@PostMapping("")
fun createUser(
@RequestBody request: CreateUserRequest,
){
userUserCase.create(command=request.toCommand())
}
}
data class CreateUserRequest(
val name: String,
val age: Int,
val address: AddressRequest,
){
fun toCommand(): CreateUserRequest{
....
return CreateUserRequest(....)
}
}
data class AddressRequest(
val detailAddress
)
다음과 같은 제약조건이 있다고 가정
- 이름에는 이모지가 포함되면 안된다.
- 나이는 1살 이상 100살 이하 이여야 한다
- 주소에는 이모지가 포함되면 안된다.
일단 이모지를 검증하기 위해서 EmojiCheck 라는 Annotation과 EmojiValidator를 생성
- EmojiValidator
class EmojiValidator : ConstraintValidator<EmojiCheck, String> {
override fun isValid(text: String?, context: ConstraintValidatorContext): Boolean {
if (checkIsEmpty(text)) {
return false
}
return !containsEmoji(text!!)
}
companion object {
private fun checkIsEmpty(value: String?): Boolean {
return value == null || value.isEmpty()
}
private fun containsEmoji(value: String): Boolean {
val codePointCount = value.codePointCount(0, value.length)
for (index in 0 until codePointCount) {
val codePoint = value.codePointAt(index)
if (isEmoji(codePoint)) {
return true
}
}
return false
}
private fun isEmoji(codePoint: Int): Boolean {
return codePoint in 0x1F600..0x1F64F // Emoticons
|| codePoint in 0x1F300..0x1F5FF // Misc Symbols and Pictographs
|| codePoint in 0x1F680..0x1F6FF // Transport and Map
|| codePoint in 0x1F1E0..0x1F1FF // Regional country flags
|| codePoint in 0x2600..0x26FF // Misc symbols
|| codePoint in 0x2700..0x27BF // Dingbats
|| codePoint in 0xFE00..0xFE0F // Variation Selectors
|| codePoint in 0x1F900..0x1F9FF // Supplemental Symbols and Pictographs
|| codePoint in 0x1F018..0x1F270 // Various asian characters
|| codePoint in 0x238C..0x2454 // Misc items
|| codePoint in 0x20D0..0x20FF // Combining Diacritical Marks for Symbols
}
}
}
- EmojiCheck Annotation
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = [EmojiValidator::class])
annotation class EmojiCheck(
val message: String = "이모지는 사용할 수 없습니다.",
val groups: Array<KClass<*>> = [],
val payload: Array<KClass<*>> = [],
)
1. 이름에는 이모지가 포함되면 안된다.
일반적으로 Controller 의 requestBody앞에 @Valid 를 추가해주면 유효성 검증이 진행된다.
@RestController
@RequestMapping("/user")
class UserController(
private val userUseCase: UserUseCase,
){
@PostMapping("")
fun createUser(
@Valid @RequestBody request: CreateUserRequest,
){
userUserCase.create(command=request.toCommand())
}
}
data class CreateUserRequest(
@field:EmojiCheck(message = "한글/영문/숫자/특수문자만 입력해 주세요.")
val name: String,
val age: Int,
val address: AddressRequest,
){
fun toCommand(): CreateUserRequest{
....
return CreateUserRequest(....)
}
}
data class AddressRequest(
val detailAddress
)
2. 나이는 1살 이상 100살 이하 이여야 한다.
age에 Range를 추가하여 유효성 검사 진행
@RestController
@RequestMapping("/user")
class UserController(
private val userUseCase: UserUseCase,
){
@PostMapping("")
fun createUser(
@Valid @RequestBody request: CreateUserRequest,
){
userUserCase.create(command=request.toCommand())
}
}
data class CreateUserRequest(
@field:EmojiCheck(message = "한글/영문/숫자/특수문자만 입력해 주세요.")
val name: String,
@field:Range(min = 1, max = 100, message = "1~100자 사이로 입력해 주세요.")
val age: Int,
val address: AddressRequest,
){
fun toCommand(): CreateUserRequest{
....
return CreateUserRequest(....)
}
}
data class AddressRequest(
val detailAddress
)
3. 주소에는 이모지가 포함되면 안된다.
아래 처럼 AddressRequest의 detailAddress에 EmojiCheck Annotation을 추가하면 유효성 검사가 될 것이라 생각 했으나 유효성 검사가 되지 않고 바로 통과됨..
stackoverflow를 찾아보니 nested valid를 하게 될 경우에는 nested field에 @Valid 를 추가해 주어야 유효성 검사가 된다고 함
@RestController
@RequestMapping("/user")
class UserController(
private val userUseCase: UserUseCase,
){
@PostMapping("")
fun createUser(
@Valid @RequestBody request: CreateUserRequest,
){
userUserCase.create(command=request.toCommand())
}
}
data class CreateUserRequest(
@field:EmojiCheck(message = "한글/영문/숫자/특수문자만 입력해 주세요.")
val name: String,
@field:Range(min = 1, max = 100, message = "1~100자 사이로 입력해 주세요.")
val age: Int,
@field:Valid
val address: AddressRequest,
){
fun toCommand(): CreateUserRequest{
....
return CreateUserRequest(....)
}
}
data class AddressRequest(
@field:EmojiCheck(message = "한글/영문/숫자/특수문자만 입력해 주세요.")
val detailAddress
)
결론
중첩클래스에서 유효성 검사를 진행하려면 중첩 클래스가 선언된 field에 @Valid 를 추가하는걸 잊지 말자
반응형
'spring' 카테고리의 다른 글
Spring Boot Jdbc Bulk Update 삽질기 (Feat. VALUES Parsing Problem) (1) | 2024.02.15 |
---|---|
Spring Cloud OpenFeign의 Logging 방법 (0) | 2023.07.07 |
AWS EC2 freetier instance에 spring boot 배포시 멈춤 현상 (0) | 2022.12.04 |
spring cloud open feign이란?? (작성중) (0) | 2022.10.23 |
Spring Boot - RestAPI (0) | 2022.07.31 |
Comments