[Spring] 컴포넌트 스캔, 의존 관계 주입, 조회되는 빈

2024. 1. 25. 23:55Backend/Spring

 

📝 인프런에서 강의를 하고 계시는 김영한 님의 Spring Framework를 공부하고 있습니다. 틀리거나 다른 부분이 있을 수 있습니다.

 

1. 컴포넌트 스캔 (component scan)

 

1) 자동 등록

 

스프링 프레임워크에서는 설정된 정보가 없더라도, 스프링 빈을 자동으로 등록해주는 '컴포넌트 스캔' 기능을 사용할 수 있다. 컴포넌트 스캔을 사용하기 위해서는 @ComponentScan 이라는 annotation을 설정 정보에 붙여주면 된다.

 

@Configuration
@ComponentScan	// 이렇게 붙여주면 된다
public class Config {
}

 

이렇게 되면 @Component라고 붙인 모든 곳에서 스캔하여, 의존관계를 자동으로 주입하게 된다. 일반적으로 @Component @Controller @Service @Repository @Configuration이 컴포넌트 스캔의 대상이 될 수 있다.

 

2) 충돌

 

스프링 빈을 등록하는 방법은 1. 수동 2. 자동의 방법이 있다.

 

자동 빈과 자동 빈의 이름이 같아 충돌이 날 경우에는, ConflictingBeanDefinitionException이 발생하게 된다. 수동 빈과 자동 빈이 충돌될 경우, 최근 스프링부트에서는 오류가 발생하도록 기본 값이 설정되어 있다고 한다.

 

 

2. 의존관계 주입

 

1) @Autowired 방법

 

a. 생성자 주입 (constructor)

b. 수정자 주입 (setter)

c. 필드 주입

d. 메서드 주입

 

이처럼 의존 관계 주입 방법은 다양하다. 그렇지만 여기서 생성자 주입을 사용하는 것이 좋다.

 

예를 들어, 수정자(setter)인 경우 public하게 수정이 가능할 수 있어 값이 유지되지 않는다. 또한 생성자를 제외한 주입 방식들은 생성자 이후에 호출되기 때문에 final(1회 초기화 후, 변경 안됨) 키워드를 사용할 수 없기 때문이다.

 

 

2) 옵션

 

주입할 스프링 빈이 없다. 그럼에도 프로그램이 동작해야 할 때가 있다. 이 때 옵션 처리를 해주면 된다!

 

@Autowired의 특징으로 주입 대상이 없으면 오류가 발생하게 된다는 점이다. 그렇기 때문에 옵션 처리를 해줄 수 있는데, 이는 3가지 방법이 있다.

 

a. @Autowired(required=false) : 기본값은 true인데, false로 설정해둔다면, 주입 대상이 없을 경우 호출되지 않는다.

@Autowired(required=false)
public void ~~~ (Furniture funiture){
	System.out.println(funiture); // 호출 안됨
}

 

b. @Nullable :주입 대상이 없으면 null을 반환한다.

@Autowired
public void ~~(@Nullable Funiture funiture) {
	System.out.println(funiture); // null
}

 

c. Optional<> : 주입 대상이 없으면 Optional.empty를 반환한다.

@Autowired
public void ~~~(Optional<Funiture> funiture){
	System.out.println(funiture); // Optional.empty
}

 

3. 조회되는 빈

 

1) 타입 조회? 그래서 문제는?

@Autowired의 특징은 빈을 조회할 때 타입(Type)으로 조회한다는 것이다. 마치 스프링 컨테이너에서 .getBean(Config.class)와 같다. 따라서, 조회된 빈이 2개 이상일 경우가 발생하는데, 이 경우 NoUniqueBeanDefinitionException 과 같은 오류가 발생할 수 있다.

 

2) 이 문제를 해결해보자

 

a. @Autowired 의 필드명을 맞추는(matching) 방법이 있다. 

// 기존 필드
@Autowired
private Furniture furniture;

// 필드 이름을 매칭
@Autowired
private Furniture desk;

 

b. @Qualifier를 사용하는 것이다. 

Qualifier를 사용하는 것은 추가적인 구분자를 붙여주는 것이다. 사용 방법은 다음과 같다.

// Qualifier 붙여주기
@Component
@Qualifier("desk")
public class desk implements Funiture {}

// 매칭할 때
@Autowired
public sellServiceImpl(@Qualifier("desk") Funiture funiture){
}

 

c. @Primary 사용

우선순위를 정하는 것이다. 예를 들어, Furniture을 찾을 때 조회되는 빈이 desk, chair 2개가 있다고 하자. 근데 desk에 @Primary가 붙어 있다면, desk가 우선권을 가지게 된다.

@Component
@Primary
public class desk implements Furniture{}

@Component
public class chair implements Furniture{}

 

 

 

결론

스프링의 세계는 재밌으면서도, 엄청나게 편리하고 좋은 기능이 많다... 배워야 한다!

 

 

Reference

1. 김영한 [스프링 핵심원리 - 기본편]

'Backend > Spring' 카테고리의 다른 글

[Spring] AOP  (0) 2024.03.10
[Spring] Spring Controller - InitBinder, Model, ModelAttribute  (0) 2024.03.10
[Spring] Singleton Container  (1) 2024.01.24
[Spring] Class Assertions  (0) 2024.01.24
[Spring] Spring Container  (1) 2024.01.23