본문 바로가기
Spring

@MapperScan 사용 주의점!

by ycjung93 2024. 4. 30.

SpringBoot 기반의 프로젝트를 진행하던 중에 발생된 에러..

***************************

APPLICATION FAILED TO START

***************************

 

Description:

 

Field visitBaseInfoService in com.idrsoft.insight.web.client.visitor.baseinfo.VisitorBaseInfoController required a single bean, but 2 were found:

- visitBaseInfoServiceImpl: defined in file [C:\Dev\100. STS\sts-4.19.0\workspace-insighthub\.git\insight-hub\insight-web\target\classes\com\idrsoft\insight\web\client\visitor\baseinfo\impl\VisitorBaseInfoServiceImpl.class]

- visitorBaseInfoService: defined in file [C:\Dev\100. STS\sts-4.19.0\workspace-insighthub\.git\insight-hub\insight-web\target\classes\com\idrsoft\insight\web\client\visitor\baseinfo\VisitorBaseInfoService.class]

 

 

Action:

 

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

 

위 Controller 에서 @Autowired 로 가져온 VisitorBaseInfoService 라는 서비스가 2개 이상의 빈을 가지고 있어서 @Qualifier 이나 @Primary 어노테이션을 써서 사용하라는 의미의 오류를 발생하고 있는데요.

 

지금 사용하고 있었던 패키지의 구조는 다음과 같았습니다.

 

insight

  ㄴ com.idrsoft.insight.web

    ㄴ client

      ㄴ visitor.baseInfo

        ㄴ impl

          ㄴ VisitorBaseInfoServiceImpl.java

        ㄴ VisitorBaseInfoController.java

        ㄴ VisitorBaseInfoMapper.java

        ㄴ VisitorBaseInfoService.java

 

보통 스프링 패키지를 만들 때 위와 같은 형태로 만들곤 하는데요.

 

 

Mapper 에 대한 특정 SqlSession 을 사용하기 위해 아래와 같이 사용되어 집니다.

 

아래 그림과 같이 @Mapper 어노테이션을 붙이고,

 

CustomDataSourceConfiguration 에서 @MapperScan 의 basePackages 를 통해 @Mapper 들을 포함시키죠.

그러면, basePackages 에 등록된 Mapper 들을 아래의 Configuration 에 설정된 DataSource SqlSession을 사용하게 됩니다.

 

문제는.. 

위와 같은 패키지 구조일 경우에 문제가 발생하는데

@MapperScan 은 interface 로된 모든 것들을 Mapper 라고 판단하고 Bean 을 생성한다는 것 입니다.

 

아래에서 Bean 으로 만들어지면 안되는 Service Interface 가 Bean 으로 생성된다는 문제가 발생합니다.

 

insight

  ㄴ com.idrsoft.insight.web

    ㄴ client

      ㄴ visitor.baseInfo

        ㄴ impl

          ㄴ VisitorBaseInfoServiceImpl.java

        ㄴ VisitorBaseInfoController.java

        ㄴ VisitorBaseInfoMapper.java -> @MapperScan 으로 정상적으로 Bean 등록

        ㄴ VisitorBaseInfoService.java -> @MapperScan 으로 의도치 않은 Bean 등록

 

위와 같다면, Controller 에서 @Autowired 를 통해 SingleTon Bean 을 가져온다고 착각하고 사용하여맨 처음과 같은 오류가 발생되어 지는 것 입니다.

 

이미 VisitorBaseInfoService 를 구현하는 Impl 구현체에 @Service 어노테이션을 달아줬기 때문에

 

서비스 빈은

visitorBaseInfoService 라는 빈 1개

visitorBaseInfoServiceImpl 라는 빈 1개

총 두 개의 빈을 생성하기 때문에 Controller 에서 @Autowired 로 가져오면 당연히 오류가 발생되는 것 입니다.

 

물론 @Qualifier 이나 @Primary 를 통해 위 오류를 해결할 수 있겠지만

근본적인 해결 방법은 아니라고 생각됩니다.

 

 

결론!

해결법은 다음과 같습니다.

 

위와 같이 지정된 패키지의 모든 Interface 를 빈으로 만드는 것이 아니라

@MapperScan 에 있는 속성 중에 annotationClass 를 사용하여 @Mapper 어노테이션이 붙은 Interface 들 만을 빈으로 만들겠다 라는 설정을 하면 되겠습니다~~~

 

 

 

'Spring' 카테고리의 다른 글

Spring lombok 사용법  (0) 2023.06.23