본문 바로가기
Issue/Server

[Spring][MyBatis] Multi-Module 프로젝트에서 @MybatisTest 테스트 실행 시 중복 fragment 등록 문제 (XML fragments parsed from previous mappers already contains key)

by chickenman 2025. 5. 31.

1. 현상

멀티 모듈 프로젝트를 진행하면서, 공통 모듈에 DB 설정코드(빈)을 작성하고 그 외 DB를 활용하는 모듈에서 common 모듈을 implementation에 사용하는 방식으로 개발중이었다.

(이전 게시글 참고 ->  https://happiestlife.tistory.com/23 )

 

[Spring][MyBatis] 이상한 클래스가 Mapper class가 scan되는 문제 개선

1. 현상멀티 모듈 프로젝트를 진행하면서, 각 모듈에 DB 설정빈을 추가하니 중복 빈 등록 오류가 발생했다.그래서 common 모듈로 공통화를 시키고, DB를 활용하는 모듈에서 common 모듈을 implementation

happiestlife.tistory.com

 

DB를 사용하는 각 모듈에서 자신의 도메인에 맞는 .xml 및 Mapper 클래스를 구현하였기 때문에 @MybatisTest 테스트 코드도 각 모듈에 위치하였다.

그렇게 @MybatisTest 테스트 코드를 작성하고 실행시키니까 아래와 같은 오류가 발생하였다.

test code
issue

즉, 중복된 아이디(key)를 가진 fragment가 이미 등록되었다는 문제였다.

 

근데 모든 모듈을 수십번 둘러보아도 UserAccoutMapper.xml은 한 개였다. 그렇게 귀결된 원인에 대한 추측은 어떤 이유에서 동일 UserAccoutMapper.xml를 2번 이상 조회한다는 것이었다.

 

그렇게 오류가 발생한 "at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:1071)" 지점부터 디버깅을 실행해보았다.

2. 원인

결론적으로 PathMatchingResourcePatternResolver를 사용하고 "classpath*:mapper/*.xml"와 같은 포맷으로 리소스를 불러왔을 때 classpath에 위치했던 mapper.xml 뿐만 아니라 빌드된 jar에 포함되어 있던 xml도 매핑되는 오류였다.

 

Gradle 빌드 도구를 기준으로, 멀티 모듈에 테스트를 실행하면 모든 모듈에서 jar Task가 실행된 후 test Task가 실행된다.

그에 따라 빌드된 jar에서도 mapper xml이 확인되고 classpath에 있는 xml도 확인되는 문제였다. 

 

만약 bootJar Task를 실행시켰다면 jar Task는 수행되지 않기 때문에 아래와 같이 중복 없이 mapper xml 파일을 불러온 것을 확인할 수 있다.

 

* 조금 더 자세히 설명하면, 그 모듈이 가지고 있는 mapper xml에 대해서 중복으로 처리되었다. 

3. 해결

나는 resource를 가지고 온 후 File의 Path에서 "모듈 이름"과 "모듈에서의 mapper xml 상대 경로"를 가지고 unique 함을 판단해서 중복되는 reousrce가 발견될 경우, 하나만 납두고 필터링하는 것으로 해결하였다. 

빨간색 부분이 변경된 부분인데, 동일하게 resource를 가져온 이후 가져온 resource의 path를 가지고 "모듈이름:mapper의 상대경로" 형태로 key를 만들어 중복될 경우 필터링 되도록 구현하였다.

 

그 결과, @MybatisTest는 모두 성공하였고 API 호출 시에도 문제 없는 것을 확인하였다.