안녕하세요. 아직도 취준중인 백수, 청주는사과아님 입니다.
이전 포스팅에서 Spring-data-jpa 의 Non-bean instance loaded to context 에러 를 발견해 기록 했었는데요.
이제 시간이 지나 어느정도 변경점이 완료된 것 같아 유지보수 포스팅(?) 을 작성해 보고자 합니다.
이전에 발견했던 에러를 간단히 다시 회고시키겠습니다.
에러는 아래와 같은 상황에서 일어났습니다.
interface SomeJpaInterface extends JpaRepository< ... > { /* ... */ }
// 그냥 이름이 (SomeJpaInterface) + (Impl) 일 뿐인
// Spring 과 아무런 관련이 없는 클래스
class SomeJpaInterfaceImpl {
// this is just a random instance
// so it should NOT be loaded to spring context
}
위처럼 JPA
인터페이스의 이름이 SomeJpaInterface
이고, Spring
과 관련 없는 SomeJpaInterfaceImpl
가 존재할 때, 이 클래스가 Spring Context
에 적재되는 에러였습니다.
저번 포스팅에서는 위 에러를 발견 후, 공식 github
에 물어 답변을 기다리던 상태였습니다.
Spring-data-jpa
형님들의 답변issue
를 올리고 다음날 Spring-data-jpa
형님의 댓글이 달렸습니다.
형님의 답변에 의하면 Custom Repository
자체는 1.x
버전대에 만들어져 (인터페이스 이름) + Impl
인 이름 만으로 Custom Repository
를 선언하였다고 합니다.
즉, 지금은 [1]
처럼 사용하라 문서에 나와있지만 옛날에는 [2]
방식 이었다는 것이지요.
// [1] : 지금은 spring-data-jpa 3.x 버전대
// CustomRepository 를 extends 해서 **CustomRepository 를 사용함을 명시**
interface MyJpa extends JpaRepository< ... >, CustomRepository {/* ... */}
interface CustomRepository {
/* ... Custom query methods ... */
}
class CustomRepositoryImpl implements CustomRepository {
/* ... Custom query method implements ... */
}
// [2] : 옛날 옛적 호랑이 담배피던 1.x 시절
// 우리 에러 났었던 예시랑 동일
interface MyJpa extends JpaRepository< ... > {/* ... */}
class MyJpaImpl {
// this were `Custom Repository` on Spring-data-jpa 1.x
}
그래서 형님은 1.x
버전대의 코드 때문에 위 에러가 발생한 것이라 의심하였고, 몇번의 추가적인 대화 끝에 이에 착수하겠다 하였습니다.
Spring-data-jpa
의 Custom Repository Implementations 문서그러부터 몇일이 지나 확인해보니 이전 올렸던 issue
가 spring-data-commons
로 옮겨졌고, 관련된 pull request
가 만들어졌습니다.
한번 pr
변경점을 확인해보니 Custom Repository Implementations
문서가 변경되고 있었습니다.
위 내용을 각각 정리하면 다음과 같습니다.
Note
Custom Repository
를 만들 때Impl
접미사를 붙이십시오.
이 때@Enable<StoreModule>Repositories(repositoryImplementationPostfix = ...)
를 통해Impl
대신 다른 접미사를 사용할 수 있습니다.
Warning
역사적(?) 으로
Custom Repository 구현체
는 아래와 같은 특정 네이밍 패턴 에 기반해 탐색됩니다.interface UserRepositoryCustom { public void someCustomMethod(User user); } class UserRepositoryImpl implements UserRepositoryCustom { public void someCustomMethod(User user) { // Your custom implementation } }
이는 한
Custom Repository
마다 단 하나 의 구현체만 가능토록하기 위한 의도입니다.즉,
Custom Repository 인터페이스
와 동일한 패키지에 존재 하고 (인터페이스 이름) + 접미사 인 구현체는Custom Repository 구현체
로 간주 되며, 이는 의도치 않은 행동을 야기할 수 있습니다.때문에 우리는 "이름에 기반한 단일 Custom Repository 구현체 방식(?)"
(single-custom implementation naming)
의 만료를 고려중이며, 이러한 사용 방식(pattern)
을 권장하지 않습니다.
대신 "fragment 에 기반한 프로그래밍 모델(???)"(fragment-based programming model)
로 이주하십시오.
single-custom implementation naming
, fragment-based programming model
이 번역이 올바른지는 모르겠지만, 어찌되었든 이름에 기반한 Custom Repository
방식을 deprecated
하려는 것 처럼 보입니다.
현재 앞서 보여드린 문서 변경점
은 실제 공식 문서에도 적용되었습니다.
사실 포스팅으로 정리하기 전 까지만 해도 문서만 바꿔두고 안고친다
는 줄 알았는데, deprecated
시키려 하는 걸 보니 언젠가 라이브러리에 위 에러가 고쳐질 수도 있을 것 같다는 생각이 드네요.
이 에러를 물어보면서도 내가 그냥 멍청한게 아닐까
, 진짜 물어보는게 맞나
등 참 많이 고민했었는데, 실제로 이렇게 답변 받고 확인을 받으니 시원하네요.
역시 모를땐 그냥 물어보는게 가장 빠르고 확실한 것 같습니다.