ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Boot 고급 시리즈 6편 – 비동기 처리와 이벤트 기반 아키텍처 전략
    기술과 산업/언어 및 프레임워크 2025. 4. 22. 12:21
    728x90

    Spring Boot에서 @Async와 이벤트 기반 아키텍처를 활용한 비동기 처리 전략을 정리했습니다. 도메인 이벤트 설계와 ApplicationEventPublisher 실전 적용 예제를 소개합니다.


    Spring Boot 고급 시리즈 6편 – 비동기 처리와 이벤트 기반 아키텍처 전략

    실무에서 이메일 발송, 알림 전송, 로그 저장, 외부 API 호출 등은 사용자의 주 흐름과 분리된 비동기 작업이 필요합니다.
    이러한 작업을 처리할 때 Spring Boot에서는 **@Async**와 **ApplicationEventPublisher**를 활용한 이벤트 기반 설계를 통해
    코드를 더 유연하고 유지보수 가능하게 만들 수 있습니다.


    📌 1. 비동기 처리를 왜 해야 할까?

    • 응답 지연 최소화: 클라이언트가 기다릴 필요 없는 작업을 별도로 처리
    • 실패 전파 차단: 보조 작업의 실패가 전체 트랜잭션에 영향을 주지 않도록 분리
    • 수평 확장 유리: 이벤트 큐나 메시징 시스템으로 발전 가능

    ✅ 2. Spring의 비동기 처리 – @Async 기본 사용법

    1️⃣ 설정: 비동기 활성화

    @SpringBootApplication
    @EnableAsync
    public class MyApp {
        public static void main(String[] args) {
            SpringApplication.run(MyApp.class, args);
        }
    }
    

    2️⃣ 비동기 메서드 선언

    @Service
    public class EmailService {
    
        @Async
        public void sendWelcomeEmail(String email) {
            // 이메일 전송 로직
            log.info("이메일 전송 시작: {}", email);
            try {
                Thread.sleep(3000); // 전송 지연 시뮬레이션
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            log.info("이메일 전송 완료");
        }
    }
    
    • 호출하는 쪽에서 기다리지 않고, 별도 쓰레드에서 실행됨
    • 반환 타입으로 void, Future, CompletableFuture 등 사용 가능
    • 주의: 동일 클래스 내부에서 호출 시 비동기 동작 안 함 (프록시 미적용)

    🧩 3. 이벤트 기반 아키텍처란?

    비즈니스 로직에서 직접 서비스 호출을 하지 않고,
    “무슨 일이 발생했다”는 이벤트를 발행하고, 리스너가 이를 처리하는 구조입니다.

    ✅ 장점

    • 결합도 ↓: 발행자와 처리자 간 의존성 제거
    • 책임 분리 ↑: 하나의 이벤트에 다수 리스너 대응 가능
    • 비동기 전환 용이: 리스너에 @Async 적용만으로 비동기 가능

    📦 4. Spring의 ApplicationEvent 기반 이벤트 처리


    1️⃣ 도메인 이벤트 정의

    public class UserRegisteredEvent {
        private final String email;
        public UserRegisteredEvent(String email) {
            this.email = email;
        }
        public String getEmail() { return email; }
    }
    

    2️⃣ 이벤트 발행

    @Service
    @RequiredArgsConstructor
    public class UserService {
    
        private final ApplicationEventPublisher eventPublisher;
    
        public void registerUser(String email) {
            // 회원 가입 로직...
            eventPublisher.publishEvent(new UserRegisteredEvent(email));
        }
    }
    

    3️⃣ 이벤트 리스너 등록

    @Component
    public class WelcomeEmailEventListener {
    
        @Async
        @EventListener
        public void handleUserRegistered(UserRegisteredEvent event) {
            // 이메일 발송 처리
            log.info("Welcome email sent to: {}", event.getEmail());
        }
    }
    
    • @EventListener를 사용하면 명시적인 인터페이스 구현 없이 이벤트를 처리할 수 있음
    • @Async와 함께 사용하면 비동기 이벤트 처리 가능

    🧠 실무 설계 팁

    항목 전략

    트랜잭션 타이밍 이벤트 발행은 트랜잭션 커밋 이후로 지연하는 것이 안전 → @TransactionalEventListener 활용
    실패 처리 이벤트 리스너 내부의 예외는 로깅 후 무시하거나 별도 에러 큐로 분기 처리
    테스트 전략 이벤트 발행 여부 테스트 → @SpyBean 또는 ApplicationListener 사용
    확장 가능성 Kafka 등 외부 메시징 시스템으로 이벤트 구조 확장 가능

    ✅ 마무리 요약

    항목 정리

    @Async 빠르고 간단한 비동기 처리
    이벤트 발행 ApplicationEventPublisher 사용
    이벤트 처리 @EventListener, @Async 결합 가능
    장점 결합도 ↓, 확장성 ↑, 유지보수성 ↑
    확장 방향 Kafka, RabbitMQ 등 메시지 큐 기반 구조로 전환 용이

    📌 다음 편 예고

    Spring Boot 고급 시리즈 7편: REST API 통합 테스트 전략 – MockMvc부터 RestAssured까지

     

    728x90
Designed by Tistory.