코틀린에서 유효성 검사를 적용할 때, @field:
사용 위치 지정자를 사용하는 이유와 그 차이를 명확히 이해하는 것은 중요합니다. 이는 실제 유효성 검사 시 예상한 대로 동작하도록 보장합니다.
코틀린에서 애노테이션을 프로퍼티에 적용할 때는 @field:
, @get:
, @set:
, @param:
등의 사용 위치 지정자(use-site target)를 사용하지 않으면, 기본적으로 애노테이션은 프로퍼티의 게터 메서드에 적용됩니다.
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Positive
data class CreatePostRequestDTO(
val id: Long?,
@field:NotBlank(message = "제목은 필수입니다.")
val title: String,
@field:NotBlank(message = "내용은 필수입니다.")
val content: String,
@field:Positive(message = "작성자는 양수여야 합니다.")
val memberId: Long
)
@field:
: 필드에 직접 애노테이션을 적용합니다.@get:
: 게터 메서드에 애노테이션을 적용합니다.아래는 필드와 게터 메서드에 각각 @NotBlank
애노테이션을 적용하여 유효성 검사를 테스트하는 예제입니다.
import jakarta.validation.constraints.NotBlank
data class FieldDTO(
@field:NotBlank(message = "내용은 필수입니다.")
val content: String
)
data class GetterDTO(
@get:NotBlank(message = "내용은 필수입니다.")
val content: String
)
package com.example.validation
import jakarta.validation.Validation
import jakarta.validation.Validator
import jakarta.validation.ValidatorFactory
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
class ValidationTest {
companion object {
private lateinit var validator: Validator
@BeforeAll
@JvmStatic
fun setUp() {
val factory: ValidatorFactory = Validation.buildDefaultValidatorFactory()
validator = factory.validator
}
}
@Test
fun `FieldDTO should fail validation when content is blank`() {
val dto = FieldDTO(content = "")
val violations = validator.validate(dto)
assertEquals(1, violations.size)
assertEquals("내용은 필수입니다.", violations.first().message)
}
@Test
fun `GetterDTO should fail validation when content is blank`() {
val dto = GetterDTO(content = "")
val violations = validator.validate(dto)
assertEquals(1, violations.size)
assertEquals("내용은 필수입니다.", violations.first().message)
}
@Test
fun `FieldDTO should pass validation when content is not blank`() {
val dto = FieldDTO(content = "유효한 내용")
val violations = validator.validate(dto)
assertEquals(0, violations.size)
}
@Test
fun `GetterDTO should pass validation when content is not blank`() {
val dto = GetterDTO(content = "유효한 내용")
val violations = validator.validate(dto)
assertEquals(0, violations.size)
}
}
코틀린은 널 안정성을 기본적으로 지원하지만, 클라이언트에서 들어오는 요청 데이터는 서버 측에서 유효성 검사가 필요합니다. DTO 클래스의 유효성 검사를 통해 데이터의 무결성을 보장할 수 있습니다.
컨트롤러에서 @Valid
를 사용하여 요청 바디의 객체에 대한 유효성 검사를 실행할 때는 필드에 직접 유효성 검사를 정의해야 합니다.