Backend/Kotlin

[Kotlin] interface default method

findmypiece 2021. 12. 22. 22:38
728x90

코틀린에서는 interface의 default method 를 지원하지 않는다. interface 에 구현부를 포함한 메소들 포함해서 사용할 순 있지만 java의 default method 와는 다르다. 

 

자바 코드로 변환된 내용을 보면 알겠지만 내부클래스를 정의하고 그 안에 static 메소드로 만들어진다. 이로 인해 코틀린 환경에서 JpaRepository 를 상속한 interface 에 구현부를 포함한 메소드를 포함할 경우 컴파일 단계에서 아래와 같은 에러를 마주하게 된다.

No property betweenOsVer found for type ${EntityName}

 

spring-data-jpa 에서는 "쿼리 메소드" 라는 기능이 있는데 JpaRepository 를 상속한 interface 해당하는 구현체를 자동으로 만들어주는 과정에서 그곳에 포함된 추상메소드 이름을 기반으로 쿼리를 만들어주는 기능이다.

 

이러한 "쿼리 메소드" 기능을 사용하려면 메소드 이름을 find…By, read…By, query…By, count…By 와 같이 사전에 약속된 네이밍을 따라야 한다.

 

다만 사용자가 직접 쿼리를 정의해야 하는 경우가 있을 수 있기 때문에 default method 는 "쿼리 메소드" 대상에 포함시키지 않도록 되어 있다.

 

그런데 코틀린에는 default 메소드가 없다보니 정의된 메소드에 대해 모두 "쿼리메소드" 가 수행되게 되고 약속된 네이밍이 아닌 메소드에 대해 위와 같은 에러메시지를 리턴하게 된다.

 

결국 JpaRepository 를 상속한 interface 에 구현부를 포함한 메소드를 포함하려면 default  메소드만 가능하다는 말이다. 다르게 말하면 현재 코틀린 환경에서는 JpaRepository 를 상속한 interface 에 구현부를 포함한 메소드를 포함하면 안된다.

 

QueryDsl을 사용할 경우 JpaRepository 를 상속한 interface 에 default method를 정의할 일은 없다. @Query 기능을 활용하거나 "쿼리메소드" 기능을 사용할 때나 필요할 것이다.

 

다만 나의 경우 BooleanExpression 로 동적쿼리를 만드는 과정에서 관련 메소드를 정의하는데 사용하고자 했다. 알다시피 동적쿼리를 만드는 방법에는 BooleanExpression과 BooleanBuilder 가 있는데 둘 중 BooleanExpression 이 선호되기 때문이다.

 

 

BooleanExpression 의 경우 조건을 동적으로 만들어주는 메소드가 필요하고 이는 Entity에 종속적이기 때문에 JpaRepository 를 상속한 interface 두는 게 맞다고 생각했기 때문이다.

 

그런데 위와 같은 이유로 인해 나는 코틀린 환경에서는 BooleanExpression 동적으로 만들어주는 메소드를 Entity 에 companion object 를 활용해서 만들어서 사용 중이다.

 

 

https://velog.io/@lsb156/SpringBoot-with-Kotlin에서-JpaRepository-default-method-구현에-따른-오류
728x90