Spring - (9) : Bean 중복

­이승환·2021년 12월 9일
0

spring

목록 보기
7/26

서론


앞선 포스팅에서 빈을 @configure에서 등록해서 스프링컨테이너(어플리케이션 컨테이너) 에서 싱글톤으로 관리한다는 것을 소개했다. 스프링 컨테이너에 빈을 등록하면 스프링 컨테이너가 알아서 의존관계를 맺어준다. 그런데 의존관계를 맺어줄 때 해당하는 타입의 빈이 2개 이상(인터페이스 중복으로 인한)이라면 어떤 문제가 발생할까?

문제

아래 예제를 확인해보자

public interface MyRepository {
	...
}

@Repository
public class MemoryRepository implements MyRepository{
	...
}

@Repository
public class JpaRepository implements MyRepository{
	...
}

위 예제에서 리포지토리 관련 Impl 클래스들이 JPA를 사용하거나 Inmemory 방식을 사용한다고 가정해보자. 중복된 MyRepository를 @Autowired 로 연결한다면 어떻게 될까?

@Component
public class MyService {

    @Autowired
    private MyRepository myRepository;
}

아마 MyRepository는 인터페이스이기 때문에 사용하기 위해선 실제로 구현한 MemoryRepository나 JpaRepository 중 하나를 주입해야 할 것이다.

스프링 컨테이너 입장에서는 둘 중 어떤 빈을 주입해야 할지 판단할 수 없기 때문에 에러가 발생한다. 실제로 동작해보면 에러가 발생한다.

터페이스를 주입받지 말고 구현된 하위 클래스를 지정하면 해결할 수 있지만 이는 다형성을 깨뜨리기 때문에 Repository를 교체할 경우 DIP와 OCP 정책을 위배하고 유연성이 떨어지는 단점이 있다.

해결책

결론적으로 해결책은 3가지 방법이 있다.

(1) @Autowired 필드 명 매칭
(2) @Qualifier 사용
(3) @Primary 사용

@Autowired 필드명 사용

@Autowired
private MyRepository memoryRepository;

@Autowired
private MyRepository jpaRepository;

클래스 명과 동일한 타입의 iv 필드명을 사용하는 방법이 있다.

@Qualifier 사용하기

@Repository
@Qualifier("memoryRepository")
public class MemoryRepository implements MyRepository{
}

@Repository
@Qualifier("jpaRepository")
public class JpaRepository implements MyRepository{
}

------------------------------------------------------
@Autowired
@Qualifier("jpaRepository")
private MyRepository myRepository;

명시적으로 작성한다는 점에서 큰 장점이 있는 방법이다.

@Primary 사용하기

@Repository
public class JpaRepository implements MyRepository{
}

위 방법을 통해서 우선순위를 줘서 빈을 주입할 수 있다.

결론

우선 @Autowired 필드 명 매칭 방식은 어노테이션을 적용한 게 아니라 단순히 필드 명을 바꾼 것이기 때문에 오타를 낼 수 도 있고, 다른 사람이 봤을 때 알아채기가 힘들다.

또한, @Qualifier은 모든 코드에 작성해야 하는 반면, @Primary 방법은 하나만 작성하면 되기 때문에 굉장히 간단해 보인다.

따라서 기본적으로 애플리케이션 생명주기 동안 변하지 않는다면 @Primary를 사용하면 된다.

만약 애플리케이션 생명주기동안 default값으로 MemoryRepository를 사용하다가 특별한 경우에 JpaRepository를 사용해야 하는 경우가 발생한다면 MemoryRepository에 @Primary를 적용해주고 JpaRepository에 @Qualifier를 적용해주면 된다.

둘 중 @Qualifier가 우선순위가 더 높기 때문이다.

profile
Mechanical & Computer Science

0개의 댓글