@Service를 붙이면 스프링이 알아서 객체를 만들어 주는데, 이 "알아서"가 정확히 어떤 과정인 걸까요?

빈(Bean)의 정의

빈이란, 스프링의 어플리케이션 컨텍스트(Application Context) 가 생성하고 등록해서 관리하는 객체를 의미합니다. 즉, 개발자가 직접 객체를 생성하는 대신, 스프링이 객체의 생성과 생명주기 관리를 담당합니다. 이렇게 생성된 객체들은 어플리케이션 컨텍스트에 등록되어 필요할 때마다 사용할 수 있습니다.

왜 빈을 사용할까?

스프링에서 빈을 사용하는 가장 큰 이유는 객체 관리와 의존성 설정의 편리함입니다. 스프링 컨테이너가 객체를 대신 생성하고 관리해주기 때문에, 개발자는 복잡한 객체 생성 과정이나 의존성 연결에 신경 쓰지 않아도 됩니다. 이를 통해 코드의 결합도를 낮추고, 유지보수성과 테스트 용이성을 높일 수 있습니다.

빈 등록 방법

스프링에서는 여러 가지 방법으로 빈을 등록할 수 있습니다. 대표적으로는 @Component, @Service, @Repository와 같은 어노테이션을 클래스에 붙여 빈으로 등록하거나, 설정 파일을 통해 직접 등록할 수도 있습니다. 그러면 MyBean 이라는 객체를 여러 방법을 사용하여 빈으로 등록해보는 예제 코드를 작성해보겠습니다.

등록 방식사용 위치특징
@Bean@Configuration 클래스 내부메서드 반환값을 빈으로 등록, 외부 라이브러리 객체 등록에 유용
@Component클래스 선언부컴포넌트 스캔으로 자동 감지, 직접 작성한 클래스에 주로 사용
  • 예제 클래스
    JAVA
    public class MyBean {
    	public String greet() {
    		return "Hello from MyBean!";
    	}
    }
    

@Bean 사용

  • @Bean 어노테이션을 사용한 예제
    JAVA
    @Configuration
    public class MyConfig {
    
    	@Bean
    	public MyBean myBean() {
    		return new MyBean();
    	}
    }
    

@Bean 어노테이션을 사용할 때는 반드시 @Configuration 으로 등록한 클래스 안에서만 등록 가능합니다. @Configuration 어노테이션을 사용한 클래스는 스프링 차원에서 특별하게 처리됩니다. @Configuration 어노테이션 은 설정 클래스로서 해당 클래스 내부의 @Bean 을 호출해 빈 객체를 생성하고 어플리케이션 컨텍스트에 등록하는 기능을 수행합니다.

@Component 사용

  • @Component 어노테이션을 사용한 예제
    JAVA
    @Component // 클래스 위에 @Component 추가
    public class MyBean {
    	public String greet() {
    		return "Hello from MyBean!";
    	}
    }
    

내부적으로 @Repository, @Service, @Configuration, @Controller, @RestController 어노테이션 모두 @Component 어노테이션을 사용하기 때문에 각 어노테이션들 모두 @Component 어노테이션과 동일한 방식으로 빈으로 등록할 수 있습니다.

빈 등록 시 주의 사항

@ComponentScan

특정 클래스를 빈으로 등록하기 위해서는 @ComponentScan이 해당 패키지를 스캔 범위에 포함해야 합니다. @SpringBootApplication이 위치한 패키지와 그 하위 패키지만 기본으로 스캔되므로, 메인 클래스의 위치가 중요합니다.

주의할 점

1. @Component와 @Bean을 동시에 등록하면 빈이 충돌한다

같은 클래스에 @Component를 붙여서 자동 등록하고, 동시에 @Configuration 클래스에서 @Bean으로도 등록하면 같은 타입의 빈이 두 개가 됩니다. Spring Boot 2.1+에서는 기본적으로 빈 오버라이드가 금지되어 BeanDefinitionOverrideException이 발생합니다. 하나의 등록 방식만 사용하세요.

2. 빈 등록 없이 new로 생성한 객체에는 DI가 동작하지 않는다

new MyService()로 직접 생성한 객체는 스프링 컨테이너가 관리하지 않으므로, 내부의 @Autowired 필드가 null입니다. 이 객체의 메서드를 호출하면 NullPointerException이 발생합니다. 스프링의 DI를 사용하려면 반드시 컨테이너가 생성한 빈을 사용해야 합니다

댓글 로딩 중...