본문 바로가기
Spring Framework/Spring

스프링이 자바 빈 등록하는 방법

by devstep 2025. 6. 7.

스프링 프레임워크의 핵심적인 역할 중 하나는 의존성 주입(Dependency Injection)을 통해 객체 생성과 관리 책임을 개발자 대신 수행하는 것입니다.
이러한 역할을 가능하게 하는 주체가 ApplicationContext, 즉 스프링의 IoC 컨테이너입니다.

이 글에서는 스프링이 애플리케이션 실행 시 어떻게 컴포넌트를 탐색하고, 어떤 방식으로 빈을 등록하는지를 정리했습니다.
또한 @Component와 @Bean이 각각 어떤 상황에서 사용되는지, 자동 구성과 명시적 설정의 차이도 작성하였습니다.

 

  • 스프링은 의존성 주입(DI)을 통해 객체 생성과 관리를 개발자 대신 수행함
  • 이 역할을 담당하는 주체는 ApplicationContext, 즉 IoC(의존성주입) 컨테이너
  • 애플리케이션 실행 시, 스프링이 컴포넌트를 어떻게 탐색하고 빈을 등록하는지 정리함
  • @Component와 @Bean의 사용 상황을 비교
  • 자동 구성 vs 명시적 설정의 차이도 함께 설명

1. ApplicationContext (애플리케이션 컨텍스트)

  • 스프링의 IoC(의존성주입) 컨테이너 오브젝트
  • 객체 생성을 개발자가 아닌 스프링이 관리 (new 키워드 사용 불필요)
  • 설정 방식:
    • 애노테이션 기반
    • XML 기반
    • 자바 기반

 

2. 스프링이 자바 빈을 등록하는 방법

2.1 스프링 자바빈 등록 절차

  1. 애플리케이션 시작 시, 스프링 부트가 자동 설정 실행
  2. @ComponentScan이 설정된 경우, 베이스 패키지 이하에서 @Component가 붙은 클래스를 탐색
  3. 찾은 클래스에 대해 객체를 생성하고 필요한 의존성을 주입
    • @Component 붙은 클래스는 스프링이 직접 인스턴스를 생성
    • @Configuration 붙은 클래스는 @Bean 이 붙은 메서드를 호출해 반환된 객체를 빈으로 등록

2.2 @Component

  • 컴포넌트 스캔 대상으로 등록되어 @ComponentScan에 의해 자동으로 빈으로 등록 됨
  • 개발자가 직접 작성한 클래스에 사용
  • @Component 정의
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface Component 

2.3 @Bean

  • 외부 라이브러리 등 직접 수정할 수 없는 클래스의 객체를 빈으로 등록할 때 사용
  • 클래스에 직접 붙일 수 없고, @Configuration 클래스 내부의 메서드에 선언해 사용
  • @Bean 정의
//Target이 METHOD 이므로 클래스에 직접 붙일 수 없다.
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean
  • Bean 사용 예시
    • JPAQueryFactory는 외부 라이브러리(QueryDSL) 클래스이기 때문에 직접 @Component를 붙일 수 없다.
    • EntityManager는 스프링이 관리하고 주입해주므로, 이를 활용해 인스턴스를 생성해야 한다.
    • 생성자 주입(@RequiredArgsConstructor)으로 EntityManager를 받아 사용
    • @Bean을 통해 명시적으로 JPAQueryFactory를 빈으로 등록
@Configuration
@RequiredArgsConstructor
public class QuerydslConfig {

    private final EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }
}

 


3. 참고

3.1 @Configuration이란?

  • 해당 클래스를 스프링의 설정 클래스로 등록
  • @Bean 메서드를 통해 직접 정의한 객체(빈)를 스프링 컨테이너에 등록
  • 내부적으로 @Component가 포함되어 있어 컴포넌트 스캔 대상이 됨
  • @Bean 메서드 호출 시 싱글톤 보장. 참고로,Component는 내부 메서드 간 호출 시 싱글톤을 보장하지 않는다.

3.1.1 @Configuration

  • 내부적으로 CGLIB 프록시가 적용됨
  • @Bean 메서드 간 호출 시, 스프링컨테이너에서 관리하는 빈을 반환
  • 결과적으로 싱글톤이 유지됨
@Configuration
public class AppConfig {

    @Bean
    public A a() {
        return new A(b()); // 실제로는 getBean("b")가 호출됨
    }

    @Bean
    public B b() {
        return new B();
    }
}

3.1.2 @Component

  • 프록시 적용되지 않음
  • @Bean 메서드 간 호출 시, 단순 메서드 직접 호출로 처리됨
  • 결과적으로 매번 새로운 인스턴스가 생성되어 싱글톤이 깨질 수 있음

 

3.2 어노테이션 생성 시 @Target

속성 의미

ElementType.TYPE 클래스, 인터페이스, enum에 사용 가능
ElementType.METHOD 메서드에 사용 가능
ElementType.ANNOTATION_TYPE 다른 애노테이션을 꾸미는 데 사용 가능

@Bean의 정의에 ElementType.ANNOTATION_TYPE이 포함된 의미는 다른 커스텀 애노테이션이 @Bean을 메타 애노테이션으로 사용할 수 있다.

댓글