Spring으로 개발을 하다보면
@Bean과 @Component의 차이점이 뭔지 의문을 가질 때가 많다.
@Bean && @Component 공통점
애플레케이션 컨텍스트에 Bean을 등록할 때 사용하는 어노테이션이다.
(애플리케이션 컨텍스트 같은 경우에는 다음 게시글에서 자세히 쓸 예정이다.)
둘의 차이점은 사용 목적에 있어 나타난다.
예를 들어, 실무에서는 주로
외부 라이브러리에서 제공하는 클래스들 : @Bean을 통해 등록하고,
애플리케이션의 특정 기능을 담당하는 사용자 정의 클래스들 : @Component를 사용해 등록하는 경우가 다수다.
@Bean과 @Component의 차이점
@Bean:
주로 개발자가 외부 라이브러리의 클래스를 빈으로 등록하고자 할 때 사용된다.

예를 들어, ObjectMapper와 같은 외부 라이브러리 클래스를 빈으로 등록하려면 @Bean을 사용해야 한다.
@Bean은 메소드 수준에서 적용되며, 해당 메소드에서 반환된 객체가 빈으로 등록된다.
이 경우 객체의 생성이나 초기화 과정을 개발자가 직접 관리할 수 있다.
@Component:
이 어노테이션은 일반적으로 애플리케이션에서 직접 작성한 클래스를 빈으로 등록할 때 사용한다.
이때, 해당 클래스는 Spring이 관리하는 객체로 등록되며, 별도의 메소드가 필요 없다.

예를 들어, 서비스 계층의 @Service,
데이터베이스 접근을 담당하는 @Repository,
HTTP 요청을 처리하는 @Controller 등도 모두
내부적으로 @Component 어노테이션을 상속받는다.

Controller, Service, Repository 다 내부적으로 Component 어노테이션이 있다.
| @Service | 비즈니스 로직을 처리하는 서비스 계층 |
| @Repository | DB 접근을 담당하는 DAO 클래스 |
| @Controller | HTTP 요청을 처리하는 웹 컨트롤러 |
| @Component | 특정한 계층에 속하지 않는 일반적인 빈 (유틸리티, 이벤트 핸들러, AOP 등) |
👉 즉, @component 어노테이션은 기본적으로 특정한 계층에 속하지 않는 일반적인 Bean을 정의할 때 사용된다.
결론
@Bean의 경우 개발자가 컨트롤이 불가능한
외부 라이브러리들을 Bean으로 등록하고 싶은 경우에 사용된다고 보면 된다.
코드를 한 번 작성해보자면

ObjectMapper의 경우 ObjectMapper Class에 @Component를 선언할수는 없으니
ObjectMapper의 인스턴스를 생성하는 메소드를 만들고 해당 메소드에
@Bean을 선언하여 Bean으로 등록하여 사용 한다.
Component 어노테이션을 선언하지 못하는 외부라이브러리의 기준은 바로
Spring이 관리하는 패키지
이를 이해하기 위해서는 Spring이 component를 스캔하는 방식에 대해서 알아야 한다.
Spring이 @Component를 스캔하는 방식
Spring이 @Component(혹은 @Service, @Repository, @Controller)가 붙은 클래스를 찾아 빈으로 등록하려면,
Spring이 스캔하는 패키지 내부에 클래스가 있어야한다.
즉, @Component 스캔이 적용되는 범위는 @ComponentScan이 적용된 패키지 내부에 있는 클래스들뿐.
ObjectMapper는 다음 패키지에 존재한다.
package com.fasterxml.jackson.databind;

근데 이제 MyComponent 처럼 내 패키지 안에 있는 사용자 정의 클래스라면,
이 경우에는 Spring이 스캔하는 패키지 내부이면서, 개발자가 컨트롤 가능한 클래스라서
Component를 붙여야 하는 것이다.
근데 @Component 대신 @Service, @Repository, @Controller를 사용할 수 있는가?
내부적으로 Component 어노테이션 있자나요
결론부터 말하면 된다. 실행하면 오류 없이 잘 된다.
@Component는 Spring에서 모든 빈을 스캔하고 등록하는 기본적인 어노테이션이니깐.
그러나 @Service, @Repository, @Controller는 각각 의미상으로 특정 계층을 명시하기 위한 어노테이션이다.
예를 들어,
@Service는 비즈니스 로직을 처리하는 서비스 클래스에,
@Repository는 데이터베이스 연동을 담당하는 DAO 클래스에 사용됩니다.
사실상, 이 어노테이션들은 @Component의 특수화된 형태이므로,
의미에 맞는 어노테이션을 사용하는 것이 좋다고 생각합니다.
그럼 개발자가 생성한 Class에 @Bean은 선언이 가능할까?

안된다
@Bean과 @Component는 각자 선언할 수 있는 타입이 정해져있어 해당 용도외에는 컴파일 에러를 발생시킨다.


그럼 한 번 외부 라이브러리에 Component 붙여서 오류를 내볼게여 제가
@Component
public class ObjectMapperProvider {
private final ObjectMapper objectMapper = new ObjectMapper();
public ObjectMapper getObjectMapper() {
return objectMapper;
}
}
외부 라이브러리인 ObjectMapper에 Component를 붙여보고
@Service
public class MyService {
private final ObjectMapper objectMapper;
public MyService(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
public void printMessage() {
System.out.println(objectMapper);
}
}
Service에서 주입받아 사용을 해보면 (애초에 ObjectMapper 제대로 쓰려면 객체 파싱 해야하는데 지금은 예시니까 생략)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.fasterxml.jackson.databind.ObjectMapper' available
이렇듯 오류가 납니다.
참고로
Component -> Bean
Bean -> Component 모두
RuntimeException이다.
왜냐면 스프링의 빈 주입은 애플리케이션 실행 시점에
1. 스프링이 클래스 경로를 스캔하고,
2. 이 과정에서 잘못된 어노테이션을 사용한 클래스를 빈으로 등록하려고 하면,
3. 해당 클래스가 빈으로 등록되지 않거나, 잘못된 빈 주입이 이루어져
=> 런타임 오류가 발생하게 된다.
그러니까 애초에 잘 해주도록 하자 . . .
https://jojoldu.tistory.com/27
@Bean vs @Component
Spring으로 개발을 하다보면 @Bean과 @Component를 언제 써야할지 헷갈릴때가 있다.둘다 목적이 명확하지 않은 Bean을 생성할때 사용하는 어노테이션인데 왜 2개로 나누어져있나 궁금했었는데, 박재성
jojoldu.tistory.com
'Spring' 카테고리의 다른 글
| WebClient가 빠른 진짜 이유: 논블로킹 I/O vs 블로킹 스레드 (7) | 2025.08.03 |
|---|