개요
Bean Validation을 이용해 정규표현식으로 검증을 하다보니 동일한 정규표현식이 여러 객체에 사용되는 케이스가 많았다. 기존엔 정규표현식을 String의 형태로 넣어줬었지만 이 방식은 유지보수하기가 까다로웠다. 프로젝트의 규모가 점점 커지면서 검증 로직을 수정해달라는 요청이 종종 들어오는데, 해당 검증 로직을 사용하는 객체를 매번 찾아다녀야 했기 때문이다. 그래서 아래와 같이 이넘을 이용해 정규표현식을 상수화시켜서 관리하고자 했다.
AS-IS
@field:Pattern(
regexp = "^\\d{5}\$",
message = "우편번호는 5자리입니다."
)
val zoneCode: String,
TO-BE - 이넘 클래스를 활용한 상수화
enum class RegexConst(
val regexp: String,
val message: String?,
) {
ZONE_CODE(
regexp = "^\\d{5}\$",
message = "우편번호는 5자리입니다.",
)
}
@field:Pattern(
regexp = RegexConst.ZONE_CODE.regexp,
message = RegexConst.ZONE_CODE.message,
)
val zoneCode: String,
그러나 이내 곧 다음과 같은 에러를 만나게 되었다..
An annotation argument must be a compile-time constant
해결
@Pattern 애너테이션의 인자로 전달되는 값은 컴파일 타임에 할당된 값이어야 하는데, 위 코드엔 런타임에 할당된 값(val)이 전달되었기 때문이다. 따라서 상수를 const val에 담아 컴파일 타임에 할당되도록 만들면 된다. companion object를 써도 되고, object를 써도 되는데 여기선 object를 사용했다.
object RegexConst {
const val zoneCodeRegexp = "^\\d{5}\$"
const val zoneCodeMessage = "우편번호는 5자리입니다."
}
@field:Pattern(
regexp = RegexConst.zoneCodeRegexp,
message = RegexConst.zoneCodeMessage
)
val zoneCode: String,
kotlin으로 작성된 클래스를 자바 코드로 디컴파일해보면 다음과 같이 static 변수에 값이 할당된 것을 확인할 수 있다.