ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Framework 시리즈 9화 – ApplicationContext의 역할과 이벤트 처리 구조
    기술과 산업/언어 및 프레임워크 2025. 5. 28. 15:20
    728x90

    Spring의 ApplicationContext는 단순한 Bean 팩토리가 아닙니다. 이 글에서는 ApplicationContext가 제공하는 기능과, 이를 기반으로 구현되는 Spring 이벤트 시스템의 구조와 활용법을 실제 코드 예제 중심으로 설명합니다.

    ApplicationContext는 BeanFactory의 확장판이다

    초기에는 모든 DI 컨테이너가 BeanFactory였습니다. 하지만 현재 실무에서는 거의 모든 Spring 기반 프로젝트가 ApplicationContext를 사용합니다.

    ApplicationContext는 BeanFactory의 모든 기능을 포함하면서, 다음과 같은 부가 기능을 제공합니다:

    기능 설명

    메시지 국제화 처리 MessageSource
    이벤트 퍼블리싱 ApplicationEventPublisher
    애플리케이션 리소스 접근 ResourceLoader
    다양한 Bean 후처리 기능 BeanPostProcessor, Aware 계열 등

    ApplicationContext의 대표 구현체

    구현체 사용 환경

    ClassPathXmlApplicationContext XML 설정 기반 프로젝트
    AnnotationConfigApplicationContext Java Config 기반, CLI 애플리케이션
    WebApplicationContext Spring MVC 환경
    GenericApplicationContext 유연한 커스텀 컨텍스트 구성
    ApplicationContext (Spring Boot) 기본적으로 AnnotationConfigServletWebServerApplicationContext로 구현

    ApplicationContext 사용 예제

    ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService service = context.getBean(MyService.class);
    service.doSomething();
    
    • 설정 클래스나 XML로부터 전체 구성 로딩
    • 모든 Bean, 메시지, 이벤트, 환경 속성 등 통합 관리

    이벤트 퍼블리싱 시스템의 이해

    ApplicationContext의 강력한 기능 중 하나는 **이벤트 기반 구조(Event Publishing)**입니다.
    Observer Pattern을 기반으로 한 이 구조는 Spring 내부에서도 빈 초기화, 컨텍스트 시작/종료 등의 작업에 활용되며, 우리도 이를 그대로 사용할 수 있습니다.


    1. ApplicationEventPublisher를 통한 이벤트 발행

    @Component
    public class OrderService {
    
        private final ApplicationEventPublisher publisher;
    
        public OrderService(ApplicationEventPublisher publisher) {
            this.publisher = publisher;
        }
    
        public void placeOrder(String orderId) {
            System.out.println("주문 처리 완료: " + orderId);
            publisher.publishEvent(new OrderCreatedEvent(this, orderId));
        }
    }
    
    public class OrderCreatedEvent extends ApplicationEvent {
        private final String orderId;
    
        public OrderCreatedEvent(Object source, String orderId) {
            super(source);
            this.orderId = orderId;
        }
    
        public String getOrderId() {
            return orderId;
        }
    }
    

    2. 이벤트 리스너 등록 – @EventListener

    @Component
    public class OrderNotificationListener {
    
        @EventListener
        public void handleOrderCreated(OrderCreatedEvent event) {
            System.out.println("알림 전송 – 주문 생성됨: " + event.getOrderId());
        }
    }
    
    • 이벤트 클래스는 POJO여도 무방 (ApplicationEvent 상속 생략 가능)
    • @EventListener는 메서드 단위로 등록되며, 스프링 컨텍스트에 등록된 Bean에서만 작동
    • 동기 방식으로 작동하지만, 비동기 이벤트도 가능

    3. 이벤트 비동기 처리 – @Async

    @Component
    public class AsyncListener {
    
        @Async
        @EventListener
        public void onAsyncEvent(OrderCreatedEvent event) {
            System.out.println("비동기 처리: " + event.getOrderId());
        }
    }
    
    • @EnableAsync 활성화 필요
    • 이벤트 처리 중 타 컴포넌트와의 비동기 통신 (예: 이메일 발송, 알림 전송 등)에 적합

    4. 스프링 내부의 주요 이벤트

    이벤트 클래스 설명

    ContextRefreshedEvent ApplicationContext 초기화 완료 시
    ContextClosedEvent 컨텍스트 종료 직전
    ApplicationReadyEvent Spring Boot 앱이 완전히 실행된 시점
    ServletRequestHandledEvent HTTP 요청 처리 후 (Spring MVC)

    이 이벤트들도 @EventListener로 구독 가능하며, 리소스 초기화, 통계 로깅, 종료 알림 등에 사용됩니다.


    실무 예제 – 주문 생성 → 이벤트 발행 → 알림 전송

    1. OrderService가 주문을 생성하면
    2. OrderCreatedEvent를 발행하고
    3. OrderNotificationListener가 이메일/SMS 전송 등 후처리를 담당

    이점:

    • 주문 로직과 알림 로직을 완전히 분리 → 낮은 결합도
    • 이벤트 핸들러는 개별 테스트 가능
    • 필요 시 비동기 처리로 확장 가능

    마무리 – ApplicationContext는 프레임워크의 심장이다

    ApplicationContext는 단순한 빈 컨테이너가 아닙니다. 스프링 생명주기를 관리하고, 설정, 메시지, 이벤트, 리소스까지 통합 관리하는 프레임워크의 핵심 오케스트레이터입니다.

    또한 이벤트 시스템은 작은 프로젝트에도 적용 가능한 유연한 구조 설계 전략으로, 비즈니스 로직과 후처리 로직을 분리해 유지보수성과 확장성을 획기적으로 높여줍니다.


    다음 10화에서는 지금까지 학습한 개념들을 통합해, 간단한 DI 기반 미니 프로젝트 – 계산기 시스템 구현을 실습합니다. @Component, @Autowired, 설정값 주입, 이벤트 활용까지 종합적으로 정리합니다.

     

    728x90
Designed by Tistory.