
1. 스프링 빈(Bean)이란?
스프링 프레임워크에서 빈(Bean) 은 스프링 컨테이너가 관리하는 객체를 의미합니다. 일반적인 Java 객체와 동일하지만, 스프링의 IoC(Inversion of Control) 컨테이너에 의해 생성 및 관리됩니다.
🔹 스프링 빈의 특징
- 스프링 컨테이너가 직접 객체를 생성 및 관리
- 싱글톤(Singleton)으로 관리 (기본 설정 시)
- DI(Dependency Injection, 의존성 주입) 지원
- 필요할 때 스프링 컨테이너에서 빈을 가져와 사용 가능
2. @Bean 어노테이션
@Bean은 개발자가 직접 제어할 수 있는 방법으로 스프링 빈을 등록할 때 사용됩니다. 주로 @Configuration과 함께 사용되며, 메서드에 붙여서 해당 메서드가 반환하는 객체를 스프링 컨테이너가 관리하는 빈으로 등록합니다.
✅ @Bean 사용 방법
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
위 코드에서 myService() 메서드가 반환하는 객체는 스프링 컨테이너에 의해 빈으로 등록됩니다.
🔹 @Bean의 특징
- 메서드 이름이 빈의 이름이 됨 (예: myService)
- 개발자가 직접 객체 생성 로직을 제어 가능
- 외부 라이브러리 등의 클래스를 빈으로 등록할 때 유용
- 싱글톤을 보장하려면 반드시 @Configuration과 함께 사용해야 함
3. @Configuration 어노테이션
@Configuration은 해당 클래스가 하나 이상의 @Bean을 정의하고 있음을 나타내는 설정 클래스를 의미합니다.
✅ @Configuration 사용 방법
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
🔹 @Configuration의 특징
- @Bean을 여러 개 포함할 수 있는 설정 클래스
- 싱글톤을 보장 (@Component 와의 차이점)
- 다른 빈과의 의존 관계 설정 가능
✅ @Configuration 싱글톤 보장 예제
@Configuration
public class AppConfig {
@Bean
public AService aService() {
return new AService(bService());
}
@Bean
public BService bService() {
return new BService();
}
}
위 코드에서 aService()에서 bService()를 호출하지만, 스프링 컨테이너가 관리하는 동일한 bService 인스턴스가 사용됩니다.
⚠ @Configuration을 사용하지 않으면 싱글톤이 깨질 수 있음
public class AppConfig {
@Bean
public AService aService() {
return new AService(bService());
}
@Bean
public BService bService() {
return new BService();
}
}
위처럼 @Configuration이 없으면 bService()가 호출될 때마다 새로운 객체가 생성됩니다. 따라서 @Bean을 사용할 때는 반드시 @Configuration을 함께 사용하여 싱글톤을 보장해야 합니다.
4. @Component 어노테이션
@Component는 개발자가 직접 클래스를 스프링 빈으로 등록할 때 사용합니다. @ComponentScan을 사용하면 해당 패키지 내의 @Component가 붙은 클래스들이 자동으로 빈으로 등록됩니다.
✅ @Component 사용 방법
@Component
public class MyService {
public void doSomething() {
System.out.println("MyService 실행");
}
}
🔹 @Component의 특징
- 클래스 수준에서 사용됨 (메서드 X)
- 자동으로 빈 등록 가능 (@ComponentScan 필요)
- @Service, @Repository, @Controller 등과 같은 스테레오타입 어노테이션과 함께 사용
✅ @ComponentScan과 함께 사용하기
@Configuration
@ComponentScan(basePackages = "com.example.service")
public class AppConfig {}
위 코드처럼 @ComponentScan을 사용하면 com.example.service 패키지 내의 @Component가 붙은 모든 클래스가 자동으로 빈으로 등록됩니다.
5. @Bean vs @Component 비교
구분 | @Bean | @Component |
적용 대상 | 메서드 | 클래스 |
등록 방식 | 개발자가 직접 등록 | 자동 스캔 (@ComponentScan 필요) |
외부 라이브러리 | O | X |
싱글톤 보장 | O (@Configuration 필요) | O |
- 일반적으로는 @Component를 사용
- 개발자가 직접 제어가 불가능한 라이브러리를 활용할 때 → @Bean + @Configuration
- 애플리케이션 전 범위적으로 사용되는 클래스를 등록할 때 → @Bean + @Configuration
- 다형성을 활용하여 여러 구현체를 등록해야 할 때 → @Bean + @Configuration
[ @Configuration 내부에서 @Bean을 사용해야 하는 이유 ]
- @Configuration 내부에서 @Bean을 사용하면 Spring이 CGLIB 프록시를 활용하여 싱글톤을 보장함.
- @Component + @Bean을 사용할 경우 싱글톤이 깨질 가능성이 있음.
- @Bean 메서드를 직접 호출하지 말고, 생성자 주입을 통해 의존성을 해결하는 것이 올바른 방법.
1. CGLIB 프록시를 통한 싱글톤 보장
- @Configuration 클래스는 내부적으로 CGLIB을 이용한 프록시 객체로 등록됩니다.
- 이 프록시 객체는 @Bean 메서드가 여러 번 호출되더라도 동일한 인스턴스를 반환하도록 보장합니다.
- 즉, @Configuration 내부에서 @Bean을 선언하면 Spring 컨테이너에서 관리하는 싱글톤 객체로 등록됩니다.
2. 직접 @Component + @Bean 사용 시 문제
@Component
public class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
- 위와 같이 @Component 안에서 @Bean을 선언하면 CGLIB 프록시가 적용되지 않음.
- myService() 메서드가 여러 번 호출될 때마다 새로운 객체가 생성될 수 있음.
3. 잘못된 사용 예시
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
@Bean
public AnotherService anotherService() {
return new AnotherService(myService()); // myService()가 직접 호출됨
}
}
- myService()를 직접 호출하면 CGLIB 프록시를 거치지 않기 때문에 새로운 객체가 생성됨.
- @Configuration 내부에서 @Bean을 호출하면 프록시를 통해 싱글톤이 유지됨.
4. 해결 방법
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService();
}
@Bean
public AnotherService anotherService(MyService myService) { // 생성자 주입
return new AnotherService(myService);
}
}
- @Bean 메서드끼리 의존성을 주입할 때는 직접 호출하지 말고 생성자 주입을 활용해야 함

- @Bean은 개발자가 직접 제어할 수 있는 빈 등록 방법
- @Configuration은 설정 클래스이며 @Bean 메서드를 포함
- @Component는 자동으로 빈 등록이 필요한 경우 사용
'Back_End > Spring' 카테고리의 다른 글
스프링 의존성 주입(Dependency Injection, DI) 완전 정복 (1) | 2025.05.21 |
---|---|
Spring Boot(스프링부트) Bean 생명주기 관리 (1) | 2025.05.14 |
스프링 @Controller와 @RestController의 차이점 (1) | 2025.03.28 |
비밀번호 해싱(Hashing) (1) | 2025.03.27 |
@Component와 @Configuration 비교 (1) | 2024.12.26 |