Spring Bean 등록

이진일·2026년 4월 9일
post-thumbnail

Bean 수동 등록하기

@Component를 사용하면 @ComponentScan에 의해 자동으로 스캔되어 해당 클래스를 Bean으로 등록해준다. 그래서 일반적으로는 @Component를 사용하여 Bean을 자동으로 등록하여 관리하는 것이 좋다.

하지만 기술적인 문제나 공통적인 관심사를 처리할 때 사용하는 객체들은 수동으로 등록하는 것이 좋다. 공통 로그처리같은 비즈니스 로직을 지원하기 위한 부가적이고 공통적인 기능들을 기술지원 Bean이라고 하는데 이 기술지원 Bean들을 수동 등록하면 문제가 발생했을 때 해당 위치를 파악하기 쉽다는 장점이 있다.

Bean 수동 등록 방법

비밀번호를 암호화할 때 사용하는 PasswordEncoder의 구현체 BCryptPasswordEncoder를 Bean으로 수동 등록하는 예로 설명해보자면

@Configuration
public class PasswordConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
  • Bean으로 등록하고자하는 객체를 반환하는 메서드를 선언하고 @Bean을 설정한다.
  • Bean을 등록하는 메서드가 속한 해당 클래스에 @Configuration을 설정한다.
  • Spring 서버가 뜰 때 Spring IoC 컨테이너에 Bean으로 저장된다.

같은 타입의 Bean이 2개라면?

public interface Food {
	void eat();
}
public class Chicken implements Food {
	@Override
    public void eat() {
    	System.out.println("치킨을 먹습니다.");
    }
}
public class Pizza implements Food {
	@Override
    public void eat() {
    	System.out.println("피자을 먹습니다.");
    }
}

위와 같이 Food의 구현체 Chicken, Pizza가 있다고 하자.

@SpringBootTest
public class BeanTest {

    @Autowired
    Food food;
    
}

이 때 Food food; 필드에 @Autowired를 사용하여 Bean 객체를 주입려고 시도한다. 하지만 "Could not autowired. There is more than one bean of 'Food' type."이라는 오류가 발생한다.
즉, food 필드에 Bean을 주입해야 하는데 같은 타입의 Bean 객체가 하나 이상이기 때문에 어떤 Bean을 등록해야할 지 알 수 없어서 오류가 발생하는 것이다.

등록된 Bean 이름 명시하기

@SpringBootTest
public class BeanTest {

    @Autowired
    Food pizza;
    
    @Autowired
    Food chicken;
    
}

이렇게 등록된 Bean 이름을 정확하게 명시해주면 문제를 해결할 수 있다. 여기서 알 수 있는 것은 @Autowired는 기본적으로 Bean Type으로 DI를 지원하고, 연결이 되지 않을 경우 Bean Name으로 찾는다는 것을 알 수 있다.

@Primary 사용하기

@Component
@Primary
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}

위의 Chicken 클래스에 @Primary를 추가한다.

@SpringBootTest
public class BeanTest {
    @Autowired
    Food food;
}

이 경우 Chicken 클래스에 @Primary가 있기 때문에 같은 타입의 Bean이 여러 개 있더라도 @Primary가 붙은 Bean 객체를 우선적으로 주입한다.

@Qualifier 사용하기

@Component
@Qualifier("pizza")
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}

Pizza 클래스에 @Qualifier("pizza")를 추가한다.

@SpringBootTest
public class BeanTest {

    @Autowired
    @Qualifier("pizza")
    Food food;
}

Bean 객체를 주입하고자 하는 필드에도 @Qualifier를 추가해주면 해당 Bean 객체가 주입된다.

@Primary VS @Qualifier

같은 타입의 Bean들에 @Primary와 @Qualifier가 동시에 적용되어 있다면 어떤 Bean 주입할까?

이 경우 @Qualifier의 우선순위가 더 높다.
같은 타입의 Bean이 여러 개 있을 때는 범용적으로 사용되는 Bean 객체에는 @Primary를 설정하고 지엽적으로 사용되는 Bean 객체에는 @Qualifier를 사용하는 것이 효율적이다.

0개의 댓글