Spring의 Bean과 Component

jadeco·2024년 10월 11일
0

Spring Framework를 사용하다 보면 자주 마주치게 되는 두 가지 어노테이션이 있습니다. 바로 @Bean@Component입니다. 둘 다 Spring IoC 컨테이너에 빈(Bean)을 등록하는 방법이지만, 사용 목적과 방식에는 중요한 차이가 있습니다. 이번 글에서는 이 두 어노테이션의 차이점과 각각의 사용 사례에 대해 자세히 알아보겠습니다.

@Component란?

특징

  • 클래스 레벨에서 선언됩니다
  • 스프링의 컴포넌트 스캔 메커니즘을 통해 자동으로 빈이 등록됩니다
  • 개발자가 직접 작성한 클래스를 빈으로 등록할 때 주로 사용됩니다
  • @Controller, @Service, @Repository 등은 모두 @Component를 포함하고 있는 특수화된 어노테이션입니다

예시 코드

@Component
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User findUser(Long id) {
        return userRepository.findById(id);
    }
}

Component 스캔 활성화

@Configuration
@ComponentScan(basePackages = "com.example.project")
public class AppConfig {
    // 설정 내용
}

@Bean이란?

특징

  • 메소드 레벨에서 선언됩니다
  • @Configuration 클래스 내부에서 사용됩니다
  • 개발자가 빈의 생성과 설정을 직접 제어할 수 있습니다
  • 주로 서드파티 라이브러리 등을 빈으로 등록할 때 사용됩니다

예시 코드

@Configuration
public class DatabaseConfig {
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
        dataSource.setUsername("user");
        dataSource.setPassword("password");
        dataSource.setMaximumPoolSize(10);
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

실제 사용 사례

@Component 사용이 적절한 경우

  1. 비즈니스 로직을 담은 서비스 클래스
@Service // @Component의 특수화된 어노테이션
public class OrderService {
    private final OrderRepository orderRepository;
    private final PaymentService paymentService;

    public OrderService(OrderRepository orderRepository, PaymentService paymentService) {
        this.orderRepository = orderRepository;
        this.paymentService = paymentService;
    }

    public void processOrder(Order order) {
        // 주문 처리 로직
    }
}
  1. 데이터 접근을 위한 리포지토리 클래스
@Repository // @Component의 특수화된 어노테이션
public class JpaOrderRepository implements OrderRepository {
    private final EntityManager em;

    public JpaOrderRepository(EntityManager em) {
        this.em = em;
    }

    @Override
    public Order save(Order order) {
        em.persist(order);
        return order;
    }
}

@Bean 사용이 적절한 경우

  1. 외부 라이브러리 클래스를 빈으로 등록
@Configuration
public class WebConfig {
	// RestTemplate 빈 등록
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return mapper;
    }
    // webClient 빈 등록
    @Bean
    public WebClient webClient() {
        return WebClient.builder().build();
    }    
}
  1. 동일한 타입의 여러 빈을 등록
@Configuration
public class CacheConfig {
    @Bean
    public Cache userCache() {
        return new ConcurrentMapCache("userCache");
    }

    @Bean
    public Cache productCache() {
        return new ConcurrentMapCache("productCache");
    }
}

주요 차이점 정리

  1. 선언 위치

    • @Component: 클래스 레벨
    • @Bean: 메소드 레벨
  2. 사용 대상

    • @Component: 직접 작성한 클래스
    • @Bean: 외부 라이브러리 클래스 또는 설정이 필요한 객체
  3. 등록 방식

    • @Component: 컴포넌트 스캔을 통한 자동 등록
    • @Bean: 개발자가 직접 등록
  4. 제어 수준

    • @Component: 스프링이 제어
    • @Bean: 개발자가 제어

@Component는 우리가 작성한 코드를 스프링이 관리하도록 할 때 사용하고, @Bean은 외부 라이브러리나 상세한 설정이 필요한 객체를 스프링이 관리하도록 할 때 사용합니다. 도움이 되셨으면 좋겠습니다. 물론 저에게도요.

profile
당신도요

0개의 댓글