인프런 커뮤니티 질문&답변

용맹돌맹님의 프로필 이미지

작성한 질문수

스프링 핵심 원리 - 기본편

옵션 처리

빈 충돌이 일어나는 테스트 오류를 못잡겠습니다ㅠㅠ

작성

·

599

0


[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오) 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 아니오
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예

[질문 내용]
섹션7의 옵션처리 강의를 보며 테스트 코드를 같이 수정하고 있습니다.CoreApplication을 Run 했을 때 발생하는 오류입니다. *************************** APPLICATION FAILED TO START *************************** Description: Parameter 0 of constructor in hello.core.member.MemberServiceImpl required a single bean, but 2 were found: - memoryMemberRepository: defined in file [C:\Users\hotay\OneDrive\바탕 화면\study\core\core\out\production\classes\hello\core\member\MemoryMemberRepository.class] - memberRepository: defined by method 'memberRepository' in class path resource [hello/core/AppConfig.class] 이 부분을 보고 MemoryMemberRepository 와 AppConfig와 AutoAppConfig 코드를 봤는데 뭐가 문제인지 모르겠습니다.package hello.core.member; import org.springframework.stereotype.Component; import java.util.*; @Component //빈등록될때는 앞에가 소문자로, memoryMemberRepository로 등록된다. public class MemoryMemberRepository implements MemberRepository{ private static Map<Long, Member> store = new HashMap<>(); @Override public void save(Member member) { store.put(member.getId(),member); } @Override public Member findById(Long memberId) { return store.get(memberId); } }package hello.core; import hello.core.discount.DiscountPolicy; import hello.core.discount.FixDiscountPolicy; import hello.core.discount.RateDiscountPolicy; import hello.core.member.MemberService; import hello.core.member.MemberServiceImpl; import hello.core.member.MemoryMemberRepository; import hello.core.order.OrderService; import hello.core.order.OrderServiceImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; //애플리케이션 전체 동작 방식을 구성(config)하기 위해 // 구현객체를 생성하고 연결하는 책임을 가지는 별도의 설정 클래스 //메서드마다 역할이 드러나게끔 한다. @Configuration //설정정보에 적어주는 어노테이션 public class AppConfig { @Bean //스프링 컨테이너에 등록이 된다. public MemberService memberService(){ return new MemberServiceImpl(memberRepository());//생성자 주입 //MemberServiceImpl이 필요로 하는 MemberRepository 의존성을 외부에서 주입 } @Bean public MemoryMemberRepository memberRepository() {//구현객체를 반환해주는 역할 return new MemoryMemberRepository(); } @Bean public OrderService orderService(){ return new OrderServiceImpl(memberRepository(),discountPolicy());//생성자 주입 } @Bean public DiscountPolicy discountPolicy(){ return new RateDiscountPolicy(); } } package hello.core; import hello.core.member.MemberRepository; import hello.core.member.MemoryMemberRepository; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; @Configuration //설정정보 어노테이션 @ComponentScan( basePackages = "hello.core", excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)//AppConfig를 등록하지않도록 필터링 ) //컴포넌트 스캔 일일이 @bean 등록안해도됨 public class AutoAppConfig { //수동으로 빈을 등록하면 자동 빈보다 우선권을 가지게되어 오버라이딩 된다. (충돌오류X) //최근 스프링 부트에서는 수동 빈 등록과 자동 빈 등록이 충돌나면 오류가 발생하도록 기본 값을 바꾸었다. // application.properties에 spring.main.allow-bean-definition-overriding=true를 등록하면 오버라이딩 할 수 있다. /* @Bean(name = "memoryMemberRepository") public MemberRepository memberRepository() { return new MemoryMemberRepository(); }*/ } AutoAppConfig에 강사님 말씀 처럼 빈 충돌 테스트 한 부분을 주석처리해줬고 AppConfig를 등록하지 않도록 필터링 했는데도 어디에서 오류를 잡아야할지 모르겠습니다.   

답변 3

1

안녕하세요. 용맹돌맹님, 공식 서포터즈 OMG입니다.

스프링부트 3.2부터 변경사항으로 인해 빌드 실행이 Gradle이 아닐 시 예상치 못한 동작이 발생할 수 있습니다.

빌드 실행이 Gradle로 되어 있는지 확인해보시겠어요?

image

감사합니다.

0

용맹돌맹님의 프로필 이미지
용맹돌맹
질문자

“강의를 따라가다가 하나의 빈이 필요한데, 2개의 빈이 조회된다고 나오면서 스프링 서버가 띄워지지 않습니다.”

위 답변을 확인했으나 질문자의 마지막 질문과 제 질문이 같습니다. 수동 빈 등록하여 충돌 테스트를 한 부분을 주석처리했는데도 강사님은 오류가 안나는데 저는 오류가 납니다..

안녕하세요. 용맹돌맹님, 공식 서포터즈 OMG입니다.

도움을 드리고 싶지만 질문 내용만으로는 답변을 드리기 어렵습니다.

실제 동작하는 전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx


주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요


추가로 다음 내용도 코멘트 부탁드립니다.

1. 문제 영역을 실행할 수 있는 방법

2. 문제가 어떻게 나타나는지에 대한 상세한 설명


링크: 공식 서포터즈

링크: 자주하는 질문

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다.

용맹돌맹님, 스프링 핵심 원리 - 기본편 강의를 열심히 수강하시면서 발생한 빈 충돌 문제에 대해 질문주셨군요. 질문 내용과 유사한 상황을 설명한 다른 질문들을 검토한 결과, 여러 개의 빈이 조회되는 문제는 @ComponentScan@Configuration 설정에서 발생할 수 있는데, 이는 두 개의 빈이 스프링 컨테이너에 등록되어 충돌을 일으키는 것입니다.

해당 문제는 @Configuration 클래스인 AppConfig에서 @Bean으로 MemberRepository를 등록하고, 동시에 MemoryMemberRepository 클래스에 @Component 어노테이션이 붙어 컴포넌트 스캔 과정에서 MemberRepository 타입의 빈이 하나 더 생성되어 발생합니다.

또한 AutoAppConfig에서는 AppConfig를 제외하기 위해 excludeFilters를 사용하셨는데, 여전히 문제가 발생하는 경우가 있습니다. 이는 AppConfig 및 컴포넌트 스캔 대상이 정확하게 설정되었는지 확인해볼 필요가 있습니다.

비슷한 문제를 해결한 다른 학습자의 예시가 있어 링크를 공유드립니다. 아래 링크에는 빈 충돌 문제로 인해 발생한 오류와 그것을 해결하는 구체적인 방법이 설명되어 있습니다:

빈 충돌의 원인이 되는 빈이 두 번 등록되지 않도록 하나의 설정만 사용하거나, 만약 두 설정을 모두 사용해야 한다면 빈 이름을 명시적으로 다르게 설정하여 충돌을 방지할 수 있습니다.

또한 AutoAppConfig에서 수동으로 MemberRepository 빈을 등록하는 코드가 주석 처리되어 있지만, 이렇게 해도 문제가 해결되지 않는 경우, 스프링의 로딩 과정에서 다른 설정이나 어노테이션이 예상치 못한 방식으로 작동할 수도 있습니다. 따라서 @ComponentScanbasePackages 설정을 점검해보시고, 필요한 경우 스프링 문서나 추가적인 자료를 참고하시는 것이 좋습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.