5주차 Unit 8.1 — 빈 팩토리와 ApplicationContext

Psj·2026년 5월 27일

F-lab

목록 보기
178/239

Unit 8.1 — 빈 팩토리와 ApplicationContext

F-LAB JAVA · 5주차 · Phase 8 · Spring 컨테이너
🌱 Phase 8 시작 — 5주차 마지막 Phase, Spring 컨테이너 실체


📌 학습 목표

이 Unit을 끝내면 다음을 답할 수 있어야 한다.

  • 빈 (Bean) 이란 무엇인가?
  • BeanFactory 의 역할은?
  • ApplicationContext 가 BeanFactory 확장인 이유는?
  • @Configuration / @Bean 으로 빈 정의는?
  • @Bean 메서드 이름 = 빈 ID 인가?
  • ApplicationContext 의 추가 기능 은?
  • 빈 등록 방식 들은?
  • 컴포넌트 스캔 이란?
  • 컨테이너와 빈의 관계 는?

🎯 핵심 한 문장

빈 (Bean) 은 Spring 컨테이너가 생성·관리하는 객체이고, BeanFactory 는 빈을 생성·관리하는 기본 인터페이스이며, ApplicationContext 는 BeanFactory 를 확장해 부가 기능 (i18n·이벤트 등) 을 더한 실무 표준 컨테이너다.
은 일반 자바 객체 중 Spring 컨테이너가 관리하는 것으로, 직접 new 하지 않고 컨테이너가 생성·주입·관리한다.
BeanFactory 는 빈을 생성하고 의존성을 주입하며 제공 (getBean) 하는 가장 기본적인 컨테이너 인터페이스다.
ApplicationContext 는 BeanFactory 를 상속·확장하여 국제화 (i18n), 이벤트 발행, 리소스 로딩, AOP 등 부가 기능을 더한 것으로, 실무에서 표준으로 쓰인다.
빈은 @Configuration 클래스 안의 @Bean 메서드로 정의하며 이때 메서드 이름이 빈의 ID (이름) 가 되고, @Component + 컴포넌트 스캔으로도 등록할 수 있다.

비유 — 부품 창고와 조립 공장

빈 / BeanFactory / ApplicationContext = 창고/공장:

빈 (Bean):
  - 창고가 관리하는 부품
  - 직접 안 만들고 창고가 보관
  - 필요하면 창고에서 받음

BeanFactory (기본 창고):
  - 부품 보관·제공
  - 기본 기능
  - "부품 주세요" (getBean)

ApplicationContext (스마트 공장):
  - 기본 창고 + α
  - 부품 제공 (창고 기능)
  - + 다국어 안내 (i18n)
  - + 알림 (이벤트)
  - + 자동화 (AOP)
  - 실무 표준

@Bean 메서드 이름 = 부품 라벨:
  - 메서드 이름 = 빈 ID
  - "shipmentDao" 라벨로 찾음

→ 빈 = 컨테이너 관리 객체, BeanFactory(기본) → ApplicationContext(확장, 실무).


🧭 9개 섹션 로드맵

1. 빈(Bean)이란
2. BeanFactory
3. ApplicationContext (확장)
4. @Configuration / @Bean
5. @Bean 메서드 이름 = 빈 ID
6. ApplicationContext 추가 기능
7. 빈 등록 방식 (컴포넌트 스캔)
8. 컨테이너와 빈
9. 면접 + 자기 점검

1️⃣ 빈(Bean)이란

1.1 빈

빈 (Bean):

  Spring 컨테이너가
  생성·관리하는 객체.

  - new 직접 X
  - 컨테이너가 생성
  - 컨테이너가 관리

1.2 일반 객체와 차이

일반 객체 vs 빈:

일반 객체:
  - new 로 생성
  - 내가 관리

빈:
  - 컨테이너 생성
  - 컨테이너 관리
  - DI 대상

1.3 빈의 특징

빈 특징:

  - 컨테이너 관리
  - 기본 싱글톤 (Unit 8.3)
  - DI 받음/제공
  - 생명주기 관리

1.4 ILIC 의 맥락

// 빈 (Spring 관리 객체)
@Repository   // 빈 등록
public class ShipmentDao {
    // Spring 이 생성·관리
}

@Service   // 빈 등록
public class ShipmentService {
    private final ShipmentDao shipmentDao;   // 빈 주입
    public ShipmentService(ShipmentDao dao) {
        this.shipmentDao = dao;   // 컨테이너가 주입
    }
}
// ShipmentDao, ShipmentService = 빈
// new 안 함, 컨테이너가 생성·주입

1.5 자기 점검 답변

빈 (Bean) 이란 무엇인가?

:
1. :

  • 컨테이너 관리 객체
  1. 차이:

    • new X, 컨테이너가
  2. 특징:

    • 싱글톤, DI
  3. 관리:

    • 생명주기

2️⃣ BeanFactory

2.1 BeanFactory

BeanFactory:

  빈을 생성·관리하는
  가장 기본적인 인터페이스.

  - 빈 생성
  - DI
  - getBean 제공

2.2 기본 기능

BeanFactory 기본 기능:

  - getBean(name/type)
  - 빈 생성 (요청 시, lazy)
  - 의존성 주입
  - 싱글톤 관리

2.3 지연 로딩

지연 로딩 (Lazy):

  BeanFactory:
    - 빈 요청 시 생성
    - getBean 호출 시

  → 메모리 효율 (필요 시)
  → 하지만 오류 늦게 발견

2.4 인터페이스

// BeanFactory 인터페이스 (개념)
public interface BeanFactory {
    Object getBean(String name);
    <T> T getBean(Class<T> requiredType);
    boolean containsBean(String name);
    // ...
}
// 빈 제공 계약

2.5 ILIC 의 맥락

// BeanFactory 사용 (기본)
public class BeanFactoryExample {
    public void use() {
        // BeanFactory (지연 로딩)
        // DefaultListableBeanFactory factory = ...;
        // ShipmentDao dao = factory.getBean(ShipmentDao.class);
        // → 이때 생성 (lazy)
        
        // 실무는 ApplicationContext (다음)
    }
}
// BeanFactory: 기본 컨테이너
// 실무: ApplicationContext (확장)

2.6 자기 점검 답변

BeanFactory의 역할은?

:
1. BeanFactory:

  • 빈 생성·관리 기본
  1. 기능:

    • getBean, DI
  2. 지연 로딩:

    • 요청 시 생성
  3. 인터페이스:

    • 빈 제공 계약

3️⃣ ApplicationContext (확장)

3.1 ApplicationContext

ApplicationContext:

  BeanFactory 를 확장한
  실무 표준 컨테이너.

  - BeanFactory 기능 +
  - 부가 기능

3.2 BeanFactory 확장

BeanFactory 확장:

  ApplicationContext extends BeanFactory:
    - 빈 생성·DI (상속)
    - + 부가 기능

  → 상위 호환

3.3 추가 기능

추가 기능:

  - 국제화 (i18n)
  - 이벤트 발행
  - 리소스 로딩
  - AOP
  - 환경 (프로파일)

3.4 즉시 로딩

즉시 로딩 (Eager):

  ApplicationContext:
    - 시작 시 싱글톤 빈 생성
    - 미리 (eager)

  → 시작 시 오류 발견
  → 실무 선호

3.5 구현체

// ApplicationContext 구현체들
// 1. 애노테이션 기반
ApplicationContext ctx1 = 
    new AnnotationConfigApplicationContext(AppConfig.class);

// 2. XML 기반
// ApplicationContext ctx2 = 
//     new ClassPathXmlApplicationContext("beans.xml");

// 3. Spring Boot (자동)
// SpringApplication.run(App.class, args);

3.6 ILIC 의 맥락

// ApplicationContext (ILIC)
@Configuration
public class IlicConfig {
    @Bean
    public ConnectionMaker connectionMaker() {
        return new CustomerAConnectionMaker();
    }
    @Bean
    public ShipmentDao shipmentDao() {
        return new ShipmentDao(connectionMaker());
    }
}

public class IlicApp {
    public static void main(String[] args) {
        // ApplicationContext (실무 표준)
        ApplicationContext ctx = 
            new AnnotationConfigApplicationContext(IlicConfig.class);
        
        // 빈 사용
        ShipmentDao dao = ctx.getBean(ShipmentDao.class);
        // 시작 시 빈 미리 생성 (eager)
        // + i18n, 이벤트 등 부가 기능 가능
    }
}
class ShipmentDao { ShipmentDao(ConnectionMaker cm) {} }
interface ConnectionMaker { Connection makeConnection(); }
class CustomerAConnectionMaker implements ConnectionMaker {
    public Connection makeConnection() { return null; }
}

3.7 자기 점검 답변

ApplicationContext가 BeanFactory 확장인 이유는?

:
1. ApplicationContext:

  • BeanFactory 확장
  1. 확장:

    • 빈 기능 + 부가
  2. 추가:

    • i18n, 이벤트, AOP
  3. 즉시 로딩:

    • 시작 시 생성

4️⃣ @Configuration / @Bean

4.1 자바 설정

// @Configuration + @Bean
@Configuration
public class AppConfig {
    
    @Bean
    public ConnectionMaker connectionMaker() {
        return new NConnectionMaker();   // 빈 정의
    }
    
    @Bean
    public ShipmentDao shipmentDao() {
        return new ShipmentDao(connectionMaker());   // 의존성
    }
}

4.2 @Configuration

@Configuration:

  설정 클래스 표시:
    - 빈 정의 모음
    - 컨테이너가 읽음

→ 자바 기반 설정

4.3 @Bean

@Bean:

  메서드가 빈 생성:
    - 반환 객체 = 빈
    - 컨테이너가 호출
    - 결과 등록

→ 빈 정의 메서드

4.4 XML 과 비교

XML vs 자바 설정:

XML (전통):
  <bean id="dao" class="...">

자바 설정 (현대):
  @Bean
  public Dao dao() { ... }

→ 타입 안전, 리팩토링 용이 (자바)

4.5 ILIC 의 맥락

// ILIC 자바 설정
@Configuration
public class IlicConfig {
    
    @Bean
    public ConnectionMaker connectionMaker() {
        return new CustomerAConnectionMaker();
    }
    
    @Bean
    public ShipmentDao shipmentDao() {
        return new ShipmentDao(connectionMaker());   // 의존성 연결
    }
    
    @Bean
    public BookingDao bookingDao() {
        return new BookingDao(connectionMaker());   // 같은 연결 재사용
    }
    
    @Bean
    public ShipmentService shipmentService() {
        return new ShipmentService(shipmentDao());   // 서비스 조립
    }
}
// 컨테이너가 이 설정 읽고 빈 생성·연결
class ShipmentDao { ShipmentDao(ConnectionMaker cm) {} }
class BookingDao { BookingDao(ConnectionMaker cm) {} }
class ShipmentService { ShipmentService(ShipmentDao dao) {} }
interface ConnectionMaker { Connection makeConnection(); }
class CustomerAConnectionMaker implements ConnectionMaker {
    public Connection makeConnection() { return null; }
}

4.6 자기 점검 답변

@Configuration / @Bean으로 빈 정의는?

:
1. @Configuration:

  • 설정 클래스
  1. @Bean:

    • 빈 생성 메서드
  2. 자바 설정:

    • 타입 안전
  3. vs XML:

    • 리팩토링 용이

5️⃣ @Bean 메서드 이름 = 빈 ID

5.1 메서드 이름 = ID

@Configuration
public class AppConfig {
    @Bean
    public ShipmentDao shipmentDao() {   // 메서드 이름 = 빈 ID
        return new ShipmentDao();
    }
}

// 빈 ID = "shipmentDao"
// ctx.getBean("shipmentDao")

5.2 기본 규칙

기본 규칙:

  @Bean 메서드 이름:
    - 빈의 ID (이름)
    - 기본값

  shipmentDao() → "shipmentDao"

5.3 이름 지정

// 이름 명시 지정
@Bean(name = "customDao")
public ShipmentDao shipmentDao() {
    return new ShipmentDao();
}
// 빈 ID = "customDao" (메서드 이름 무시)

5.4 ID 로 조회

// ID 로 빈 조회
ApplicationContext ctx = ...;

// 메서드 이름으로
ShipmentDao dao = (ShipmentDao) ctx.getBean("shipmentDao");

// 타입으로 (더 권장)
ShipmentDao dao2 = ctx.getBean(ShipmentDao.class);

5.5 ILIC 의 맥락

@Configuration
public class IlicConfig {
    
    // 메서드 이름 = 빈 ID
    @Bean
    public ShipmentDao shipmentDao() {   // ID: "shipmentDao"
        return new ShipmentDao(connectionMaker());
    }
    
    @Bean
    public ConnectionMaker connectionMaker() {   // ID: "connectionMaker"
        return new CustomerAConnectionMaker();
    }
    
    // 이름 지정
    @Bean(name = "primaryConnection")
    public ConnectionMaker mainConnection() {   // ID: "primaryConnection"
        return new CustomerAConnectionMaker();
    }
}

// 조회
// ctx.getBean("shipmentDao")        // 메서드 이름
// ctx.getBean("primaryConnection")  // 지정 이름
// ctx.getBean(ShipmentDao.class)    // 타입 (권장)
class ShipmentDao { ShipmentDao(ConnectionMaker cm) {} }
interface ConnectionMaker { Connection makeConnection(); }
class CustomerAConnectionMaker implements ConnectionMaker {
    public Connection makeConnection() { return null; }
}

5.6 자기 점검 답변

@Bean 메서드 이름 = 빈 ID인가?

:
1. 기본:

  • 메서드 이름 = ID
  1. 규칙:

    • shipmentDao() → "shipmentDao"
  2. 지정:

    • @Bean(name=...)
  3. 조회:

    • 이름 또는 타입

6️⃣ ApplicationContext 추가 기능

6.1 추가 기능들

ApplicationContext 추가 기능:

1. 국제화 (i18n)
2. 이벤트 발행/구독
3. 리소스 로딩
4. 환경/프로파일
5. AOP

6.2 국제화 (i18n)

// 국제화 (MessageSource)
@Autowired
private MessageSource messageSource;

public String getMessage(Locale locale) {
    return messageSource.getMessage(
        "shipment.created", null, locale);
    // 언어별 메시지
}
// ILIC Vue 3 i18n 과 연계 (백엔드 메시지)

6.3 이벤트

// 이벤트 발행/구독
@Component
public class ShipmentEventPublisher {
    private final ApplicationEventPublisher publisher;
    
    public void publish(Shipment s) {
        publisher.publishEvent(new ShipmentCreatedEvent(s.getId()));
    }
}

@EventListener
public void onCreated(ShipmentCreatedEvent e) {
    // 구독 (컨테이너가 호출)
}
record ShipmentCreatedEvent(Long id) {}

6.4 리소스 로딩

// 리소스 로딩
@Autowired
private ResourceLoader resourceLoader;

public void loadConfig() {
    Resource resource = resourceLoader.getResource(
        "classpath:freight-rates.json");
    // 파일/클래스패스/URL 통합
}

6.5 ILIC 의 맥락

// ApplicationContext 부가 기능 활용 (ILIC)
@Service
public class ShipmentService {
    private final MessageSource messageSource;          // i18n
    private final ApplicationEventPublisher publisher;  // 이벤트
    
    public ShipmentService(MessageSource ms, 
                           ApplicationEventPublisher pub) {
        this.messageSource = ms;
        this.publisher = pub;
    }
    
    public void createShipment(Shipment shipment, Locale locale) {
        // 비즈니스
        save(shipment);
        
        // i18n 메시지
        String msg = messageSource.getMessage(
            "shipment.created", null, locale);
        
        // 이벤트 발행 (4주차 audit 시스템 연계)
        publisher.publishEvent(new ShipmentCreatedEvent(shipment.getId()));
    }
    
    private void save(Shipment s) { }
}
record ShipmentCreatedEvent(Long id) {}
// ApplicationContext 가 i18n, 이벤트 등 제공

6.6 자기 점검 답변

ApplicationContext의 추가 기능은?

:
1. 추가 기능:

  • i18n, 이벤트, 리소스
  1. i18n:

    • MessageSource
  2. 이벤트:

    • 발행/구독
  3. 리소스:

    • 통합 로딩

7️⃣ 빈 등록 방식 (컴포넌트 스캔)

7.1 등록 방식

빈 등록 방식:

1. @Bean (자바 설정)
2. @Component 스캔
3. XML (전통)

7.2 컴포넌트 스캔

// 컴포넌트 스캔
@Configuration
@ComponentScan("com.ilic")   // 패키지 스캔
public class AppConfig { }

// 스캔 대상 (@Component 계열)
@Component   // 일반
@Service     // 서비스
@Repository  // DAO
@Controller  // 컨트롤러

7.3 스테레오타입

스테레오타입 애노테이션:

@Component: 일반 빈
@Service: 비즈니스 계층
@Repository: 데이터 계층 (예외 변환)
@Controller: 표현 계층

→ 모두 @Component 기반

7.4 @Bean vs @Component

@Bean vs @Component:

@Bean:
  - 메서드 (설정 클래스)
  - 외부 라이브러리 빈
  - 세밀한 제어

@Component:
  - 클래스 (스캔)
  - 내 클래스
  - 간편

7.5 ILIC 의 맥락

// 컴포넌트 스캔 (ILIC)
@Configuration
@ComponentScan("com.ilic")
public class IlicConfig {
    // 외부 라이브러리는 @Bean
    @Bean
    public ConnectionMaker connectionMaker() {
        return new CustomerAConnectionMaker();
    }
}

// 내 클래스는 @Component 계열 (자동 스캔)
@Repository
public class ShipmentDao {
    private final ConnectionMaker connectionMaker;
    public ShipmentDao(ConnectionMaker cm) {
        this.connectionMaker = cm;
    }
}

@Service
public class ShipmentService {
    private final ShipmentDao shipmentDao;
    public ShipmentService(ShipmentDao dao) {
        this.shipmentDao = dao;
    }
}

@RestController
public class ShipmentController {
    private final ShipmentService service;
    public ShipmentController(ShipmentService service) {
        this.service = service;
    }
}
// 스캔으로 자동 등록 + 의존성 주입
interface ConnectionMaker { Connection makeConnection(); }
class CustomerAConnectionMaker implements ConnectionMaker {
    public Connection makeConnection() { return null; }
}

7.6 자기 점검 답변

컴포넌트 스캔이란?

:
1. 등록 방식:

  • @Bean, 스캔, XML
  1. 스캔:

    • @ComponentScan
  2. 스테레오타입:

    • @Service/@Repository 등
  3. @Bean vs @Component:

    • 외부 vs 내 클래스

8️⃣ 컨테이너와 빈

8.1 관계

컨테이너와 빈:

  컨테이너:
    - 빈 생성·관리
    - 빈 보유

  빈:
    - 컨테이너 안에서
    - 관리됨

8.2 빈 등록 흐름

빈 등록 흐름:

1. 설정 읽기 (@Bean/@Component)
2. 빈 정의 등록
3. 빈 생성
4. 의존성 주입
5. 빈 저장 (컨테이너)
6. getBean 제공

8.3 빈 컨테이너 내부

빈 컨테이너 내부 (개념):

  Map<String, Object> beans:
    - "shipmentDao" → 인스턴스
    - "connectionMaker" → 인스턴스
    - ...

  → ID 로 관리

8.4 라이프사이클

빈 라이프사이클:

  생성 → 의존성 주입
   → @PostConstruct
   → 사용
   → @PreDestroy → 소멸

  컨테이너가 관리

8.5 ILIC 의 맥락

// 컨테이너와 빈 관계
@Component
public class ShipmentDao {
    @PostConstruct
    public void init() {
        // 컨테이너가 생성·주입 후 호출
        log.info("ShipmentDao 빈 초기화");
    }
    
    @PreDestroy
    public void destroy() {
        // 컨테이너 종료 시
        log.info("ShipmentDao 빈 소멸");
    }
}

// 컨테이너:
// 1. ShipmentDao 빈 생성
// 2. 의존성 주입
// 3. init() 호출
// 4. Map 에 보관 ("shipmentDao" → 인스턴스)
// 5. 요청 시 제공
// 6. 종료 시 destroy() 호출

8.6 자기 점검 답변

컨테이너와 빈의 관계는?

:
1. 관계:

  • 컨테이너가 빈 관리
  1. 등록 흐름:

    • 설정 → 생성 → 주입 → 저장
  2. 내부:

    • Map (ID → 인스턴스)
  3. 라이프사이클:

    • 생성 ~ 소멸

9️⃣ 면접 + 자기 점검

9.1 면접 단골 질문 매핑

Q핵심 답변
빈?컨테이너 관리 객체
BeanFactory?빈 생성·관리 기본
ApplicationContext?BeanFactory 확장 (부가)
@Configuration/@Bean?자바 설정
@Bean 이름?메서드 이름 = 빈 ID
추가 기능?i18n, 이벤트, AOP
등록 방식?@Bean, 스캔, XML
컴포넌트 스캔?@ComponentScan
컨테이너-빈?생성·관리
@Bean vs @Component?외부 vs 내 클래스

9.2 자기 점검 체크리스트

  • 정의

BeanFactory

  • 기본

ApplicationContext

  • 확장

@Bean

  • 설정

빈 ID

  • 메서드 이름

추가 기능

  • i18n 등

스캔

  • @ComponentScan

9.3 추가 심화 질문

Q1: @Bean 메서드 호출 시 매번 새 객체?

답:

  • 아니오 (싱글톤)
  • @Configuration 프록시
  • 여러 번 호출해도 같은 빈
  • → Unit 8.3 싱글톤

Q2: @Component vs @Bean 선택?

답:

  • 내 클래스: @Component
  • 외부 라이브러리: @Bean
  • 세밀한 제어: @Bean
  • 간편: @Component

Q3: @Repository 의 특별함?

답:

  • DAO 표시
  • 예외 변환 (PersistenceExceptionTranslation)
  • SQLException → DataAccessException
  • 데이터 계층

Q4: Spring Boot 자동 설정?

답:

  • @SpringBootApplication
  • @ComponentScan 포함
  • 자동 빈 등록
  • 컨벤션

Q5: 빈 이름 충돌?

답:

  • 같은 이름 → 오류 (또는 덮어쓰기)
  • @Primary 우선
  • @Qualifier 지정
  • 명확한 이름

🎯 핵심 요약 — 3줄 정리

1. 빈과 컨테이너

  • 빈 = Spring 컨테이너가 생성·관리하는 객체
  • BeanFactory (기본) → ApplicationContext (확장, 실무)

2. 빈 정의

  • @Configuration + @Bean (메서드 이름 = 빈 ID)
  • @Component + 컴포넌트 스캔

3. ApplicationContext 부가 기능

  • BeanFactory + i18n, 이벤트, 리소스, AOP
  • 즉시 로딩 (시작 시 빈 생성)

📚 다음으로...

Unit 8.2 — getBean()의 동작

이번 Unit에서 빈 팩토리/ApplicationContext 를 봤다면, 다음은 getBean() 동작.

  • 빈 찾기 → 생성 → 의존 주입 → 반환
  • 처음/두번째 호출 차이 (싱글톤 예고)
  • @Bean 직접 호출 vs getBean

Phase 8 진행 상황

🌱 Phase 8 — Spring 컨테이너
  ✅ Unit 8.1 빈 팩토리와 ApplicationContext ← 여기
  ⏭ Unit 8.2 getBean()의 동작
  ⏭ Unit 8.3 싱글톤 레지스트리 ★깊이
  ⏭ Unit 8.4 의존관계 주입 DI ★깊이 (+ 졸업 시험)

5주차 누적 진행

✅ Part A — 동시성 마무리 (7 Unit)
🌱 Part B — 토비의 스프링
  ✅ Phase 3~7 (15 Unit)
  🌱 Phase 8 — Spring 컨테이너 (1/4 진행)

총: 23/26 Unit

🌱 Phase 8 시작 — Spring 컨테이너

profile
Software Developer

0개의 댓글