빈이란 컨테이너 빈 등록 빈 스코프 생명주기 📝 문제풀이
◀ 이전 📋 목차 CH 04 ▶
🫘 CHAPTER 03 · 입문

빈(Bean)과 컨테이너 — 스프링이 관리하는 객체들

CH 02에서 IoC·DI로 "스프링이 객체를 대신 만들고 연결해준다"는 걸 봤어요. 그럼 스프링이 관리하는 그 객체는 뭐라 부르고, 어디에 담겨 있을까요? 이번 장의 주인공은 빈(Bean)컨테이너예요.

🎯 이 장을 끝내면
🫘
빈이란
빈(Bean)이 뭔가요?
한 문장으로 먼저 잡아요.

빈(Bean)은 "스프링 컨테이너가 생성하고 관리하는 객체"예요. 내가 코드에서 직접 new로 만들어 쓰는 일반 객체와 달리, 빈은 스프링이 대신 만들어 보관하고 필요한 곳에 주입해줘요. CH 02에서 본 IoC/DI의 대상이 바로 이 빈이에요.

🆚 일반 객체 vs 빈(Bean) 일반 객체는 개발자가 new로 직접 생성하고 직접 관리해요.
스프링이 생성하고 관리해요. 개발자는 new 하지 않고, 컨테이너에서 꺼내 쓰거나 주입받아요. 즉, 어떤 객체가 "빈이다"라는 말은 그 객체의 생성·관리 주도권을 스프링이 가진다는 뜻이에요. 여기서 "빈이다 / 빈이 아니다"의 기준은 스프링에 등록됐는지예요.
// 일반 객체 — 내가 직접 만들고 관리
UserService s1 = new UserService();

// 빈 — 스프링이 만들어 보관, 나는 주입받아 씀 (직접 new 안 함)
@Service
class UserService { }   // 스프링이 이 객체를 빈으로 등록·관리
Bean 컨테이너 ApplicationContext @Component @Bean 싱글톤 스코프 생명주기
🧭
연결고리. CH 02에서 "스프링이 객체를 대신 만들어 넣어준다(DI)"고 했죠? 그 만들어지는 객체가 빈이고, 그 빈들을 담아두는 통이 컨테이너예요. 이번 장은 그 둘을 자세히 봐요.
🪣
컨테이너
스프링 컨테이너(IoC 컨테이너)
빈을 담아두는 "통"이자, 빈을 관리하는 관리자예요.

스프링 컨테이너는 빈을 생성·보관·주입·소멸까지 책임지는 "통"이에요. IoC(제어의 역전)를 실제로 담당하기 때문에 IoC 컨테이너라고도 불러요. 개발자는 컨테이너에게 "이 빈이 필요해"라고 표시만 하면, 컨테이너가 필요한 빈을 꺼내주거나 주입해줘요.

📦 대표 구현: ApplicationContext 스프링 컨테이너를 나타내는 대표 인터페이스가 ApplicationContext예요. 우리가 흔히 말하는 "스프링 컨테이너"는 보통 이 ApplicationContext를 가리켜요. 빈 조회, 국제화, 이벤트 발행 같은 부가 기능까지 제공하는 강화된 컨테이너예요.
// 컨테이너를 만들고, 등록된 빈을 꺼내 쓰는 예
ApplicationContext ctx =
    new AnnotationConfigApplicationContext(AppConfig.class);

UserService service = ctx.getBean(UserService.class);
service.join();
실무에서는 Spring Boot가 이 컨테이너를 자동으로 만들어 실행해줘서, 위처럼 직접 getBean을 호출하는 일은 드물어요. 대부분은 주입(DI)으로 빈을 받아 써요.
🔤
ApplicationContext — 이름이 길어 겁나지만, 그냥 스프링 컨테이너의 정식 이름표라고 보면 돼요. "스프링 컨테이너"라고 말할 때 실제로 가리키는 대상이 대부분 이거예요. 빈을 담아 관리하는 것에 더해, 메시지 번역·이벤트 같은 편의 기능까지 갖춘 큰 창고예요.
🙋
개발자
"이 빈 필요해" 표시
🪣
컨테이너
빈 생성·보관·주입·소멸
주입받음
바로 사용
📝
빈 등록
빈을 등록하는 두 가지 방법
자동 등록(@Component)과 수동 등록(@Bean)이에요.
🔤
어노테이션(Annotation) — 코드에 붙이는 @이름 형태의 표식이에요. 스프링에게 "이 클래스·메서드를 이렇게 다뤄줘"라고 알려주는 메모라고 보면 돼요.
① @Component — 자동 등록 (컴포넌트 스캔) 클래스에 @Component를 붙이면 스프링이 스캔해서 자동으로 빈으로 등록해줘요. 역할에 따라 @Service·@Repository·@Controller를 쓰는데, 이들은 모두 @Component의 특수한 형태예요. 내가 만든 클래스를 등록할 때 주로 써요.
@Component
public class UserService {
    // @Component 덕분에 스프링이 이 클래스를 빈으로 자동 등록
}

@Service      // @Component의 한 종류 (서비스 계층)
public class OrderService { }

@Repository   // @Component의 한 종류 (데이터 접근 계층)
public class UserRepository { }
🔤
컴포넌트 스캔 — 스프링이 시작할 때 지정한 패키지를 훑어 @Component 계열이 붙은 클래스를 찾아 자동으로 빈 등록하는 과정이에요.
② @Bean — 수동 등록 @Configuration을 붙인 설정 클래스의 메서드@Bean을 붙이면, 그 메서드가 반환하는 객체가 빈으로 등록돼요. 주로 내가 코드를 수정할 수 없는 외부 라이브러리 객체를 등록할 때 써요.
@Configuration
public class AppConfig {

    @Bean
    public ObjectMapper objectMapper() {
        // 외부 라이브러리 객체를 직접 만들어 빈으로 등록
        return new ObjectMapper();
    }
}
정리하면 — 내 클래스는 @Component(자동), 외부 라이브러리 객체는 @Bean(수동)이 일반적인 선택이에요.
🧲
@Component · 자동
클래스에 붙여요. 컴포넌트 스캔이 알아서 빈으로 등록해줘요. 내가 만든 클래스에 주로 써요.
✍️
@Bean · 수동
설정 클래스의 메서드에 붙여요. 반환하는 객체가 빈으로 등록돼요. 외부 라이브러리 객체에 주로 써요.
💡
헷갈리지 마세요. @Component클래스에, @Bean메서드에 붙여요. 둘 다 결과는 "컨테이너에 빈이 등록된다"로 같아요. 방법이 다를 뿐이에요.
1️⃣
빈 스코프
빈의 기본 스코프는 싱글톤이에요
컨테이너당 딱 하나의 인스턴스를 만들어 공유해요.

스프링 빈의 기본 스코프는 싱글톤(singleton)이에요. 스코프란 "빈이 몇 개 만들어지고 얼마나 살아있는가"를 뜻하는데, 싱글톤은 컨테이너당 인스턴스를 딱 하나만 만들어 모두가 공유하는 방식이에요.

🔤
인스턴스(Instance) — 설계도(클래스)를 바탕으로 실제로 찍어낸 물건 하나하나예요. "붕어빵 틀(클래스)"로 구워낸 붕어빵 한 개가 인스턴스인 셈이죠. new를 할 때마다 새 붕어빵(인스턴스)이 생겨요.
🔤
싱글톤(Singleton) — 딱 하나만 만들어 모두가 나눠 쓰는 방식이에요. 사무실에 정수기 한 대를 두고 모두가 함께 쓰는 것과 같아요. 사람마다 정수기를 새로 사면 낭비니까요. 스프링도 빈을 하나만 만들어 재사용해 메모리와 성능을 아껴요.
🔂 싱글톤 — 하나를 공유 같은 타입의 빈을 여러 곳에서 주입받아도, 실제로는 컨테이너가 만든 동일한 하나의 인스턴스를 함께 써요.
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에서 자세히 다뤄요.
🧠 이 장 핵심 요약
📝
문제풀이 · 점검
배운 걸 가볍게 점검해봐요
시험이 아니라 "내가 이해했나" 확인용이에요. 틀려도 바로 해설이 나와요.
🧪
문제를 풀면 즉시 정답과 해설이 나오고, 위쪽 바에 점수가 쌓여요. 네 가지 유형(객관식 · O/X · 빈칸 · 개념)을 섞어 두었어요.
CH 04 🏷️ 어노테이션 설정 — @Autowired·@Configuration으로 빈을 다루기