CH 02에서 IoC·DI로 "스프링이 객체를 대신 만들고 연결해준다"는 걸 봤어요. 그럼 스프링이 관리하는 그 객체는 뭐라 부르고, 어디에 담겨 있을까요? 이번 장의 주인공은 빈(Bean)과 컨테이너예요.
빈(Bean)은 "스프링 컨테이너가 생성하고 관리하는 객체"예요. 내가 코드에서 직접 new로 만들어 쓰는 일반 객체와 달리, 빈은 스프링이 대신 만들어 보관하고 필요한 곳에 주입해줘요. CH 02에서 본 IoC/DI의 대상이 바로 이 빈이에요.
new로 직접 생성하고 직접 관리해요.new 하지 않고, 컨테이너에서 꺼내 쓰거나 주입받아요.
즉, 어떤 객체가 "빈이다"라는 말은 그 객체의 생성·관리 주도권을 스프링이 가진다는 뜻이에요. 여기서 "빈이다 / 빈이 아니다"의 기준은 스프링에 등록됐는지예요.
// 일반 객체 — 내가 직접 만들고 관리
UserService s1 = new UserService();
// 빈 — 스프링이 만들어 보관, 나는 주입받아 씀 (직접 new 안 함)
@Service
class UserService { } // 스프링이 이 객체를 빈으로 등록·관리
스프링 컨테이너는 빈을 생성·보관·주입·소멸까지 책임지는 "통"이에요. IoC(제어의 역전)를 실제로 담당하기 때문에 IoC 컨테이너라고도 불러요. 개발자는 컨테이너에게 "이 빈이 필요해"라고 표시만 하면, 컨테이너가 필요한 빈을 꺼내주거나 주입해줘요.
// 컨테이너를 만들고, 등록된 빈을 꺼내 쓰는 예
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
UserService service = ctx.getBean(UserService.class);
service.join();
실무에서는 Spring Boot가 이 컨테이너를 자동으로 만들어 실행해줘서, 위처럼 직접 getBean을 호출하는 일은 드물어요. 대부분은 주입(DI)으로 빈을 받아 써요.
@이름 형태의 표식이에요. 스프링에게 "이 클래스·메서드를 이렇게 다뤄줘"라고 알려주는 메모라고 보면 돼요.@Component를 붙이면 스프링이 스캔해서 자동으로 빈으로 등록해줘요. 역할에 따라 @Service·@Repository·@Controller를 쓰는데, 이들은 모두 @Component의 특수한 형태예요. 내가 만든 클래스를 등록할 때 주로 써요.
@Component
public class UserService {
// @Component 덕분에 스프링이 이 클래스를 빈으로 자동 등록
}
@Service // @Component의 한 종류 (서비스 계층)
public class OrderService { }
@Repository // @Component의 한 종류 (데이터 접근 계층)
public class UserRepository { }
@Component 계열이 붙은 클래스를 찾아 자동으로 빈 등록하는 과정이에요.@Configuration을 붙인 설정 클래스의 메서드에 @Bean을 붙이면, 그 메서드가 반환하는 객체가 빈으로 등록돼요. 주로 내가 코드를 수정할 수 없는 외부 라이브러리 객체를 등록할 때 써요.
@Configuration
public class AppConfig {
@Bean
public ObjectMapper objectMapper() {
// 외부 라이브러리 객체를 직접 만들어 빈으로 등록
return new ObjectMapper();
}
}
정리하면 — 내 클래스는 @Component(자동), 외부 라이브러리 객체는 @Bean(수동)이 일반적인 선택이에요.
@Component는 클래스에, @Bean은 메서드에 붙여요. 둘 다 결과는 "컨테이너에 빈이 등록된다"로 같아요. 방법이 다를 뿐이에요.스프링 빈의 기본 스코프는 싱글톤(singleton)이에요. 스코프란 "빈이 몇 개 만들어지고 얼마나 살아있는가"를 뜻하는데, 싱글톤은 컨테이너당 인스턴스를 딱 하나만 만들어 모두가 공유하는 방식이에요.
new를 할 때마다 새 붕어빵(인스턴스)이 생겨요.UserService a = ctx.getBean(UserService.class);
UserService b = ctx.getBean(UserService.class);
System.out.println(a == b); // true — 같은 인스턴스(싱글톤)
| 스코프 | 설명 |
|---|---|
| singleton (기본) | 컨테이너당 인스턴스 1개를 만들어 공유해요. |
| prototype | 요청(주입·조회)할 때마다 새 인스턴스를 만들어줘요. |
| request / session | 웹 요청·세션 단위로 살아있는 스코프(웹 환경에서만). |
빈은 컨테이너가 시작될 때 만들어져, 필요한 의존성이 주입되고, 초기화 작업을 거쳐 사용되다가, 컨테이너가 종료될 때 소멸돼요. 이 전체 흐름을 컨테이너가 관리해요.
@PostConstruct·@PreDestroy 같은 어노테이션을 쓰는데, 이런 어노테이션 설정은 CH 04에서 자세히 다뤄요.new 하지 않아요.ApplicationContext.