개발 공부 기록하기/01. JAVA & Kotlin

코틀린 + 스프링 ArgumentResolver 주의할 점

lannstark 2023. 8. 26. 08:05

코틀린은 타입의 nullable 여부를 확실하게 지정해야 한다.

따라서 Long 타입과 Long? 타입은 java의 (primitive type) long 과 (reference type) Long 으로 컴파일 된다. 이런 이유로 스프링 ArgumentResolver에서 supportsParameter 를 구현할 때 다음과 같은 주의를 기울여야 한다.

다음 코드는 우리가 resolving 하려는 타입이 코틀린의 Long 인지 확인한다. ArgumentResolver를 활용할 때 흔히 작성하는 코드다.

override fun supportsParameter(parameter: MethodParameter): Boolean { 
  return parameter.getParameterAnnotation(커스텀어노테이션::class.java) != null &&
    Long::class.java.isAssignableFrom(parameter.parameterType)
}

그러나 이 코드는 다음 경우에만 동작한다.

fun controllerMethod(@커스텀어노테이션 value: Long) {
  println(value) // 값이 정상적으로 들어 있다.
}

만약 value의 타입이 Long 이 아닌 Long? 으로 된다면, 동작하지 않는다.

fun controllerMethod(@커스텀어노테이션 value: Long?) {
  println(value) // 값이 정상적으로 들어 있지 않다!
}

그 이유는, Long::class.java.isAssignableFrom(parameter.parameterType) 코드에서 parameter.parameterTypeLong 인지 Long?인지에 따라 다르게 true / false를 반환하기 때문이다.

Long? 타입에서도 ArgumentResolver를 활용하고 싶다면 코틀린의 Long (Long::class.java) 대신 자바의 Long을 사용하도록 변경하면 된다.

override fun supportsParameter(parameter: MethodParameter): Boolean { 
  return parameter.getParameterAnnotation(커스텀어노테이션::class.java) != null &&
    Class.forName("java.lang.Long").isAssignableFrom(parameter.parameterType)
}

그럼, Long? 타입에도 값이 정상적으로 들어온다.

fun controllerMethod(@커스텀어노테이션 value: Long?) {
  println(value) // 값이 잘 들어온다~~! 👍
}

1줄 요약 : Kotlin + Spring에서 ArgumentResolver는 argument의 nullable 여부에 따라 적절한 파라미터 타입 비교가 필요하다.