티스토리 뷰

IT/Spring

Spring Scheduler & Async 처리 흐름 - 정기 작업과 비동기 실행 완전 정복

Stv 2025. 7. 15. 19:53

목차


    1. @Scheduled - 스케줄링 처리의 핵심

     

    📌기본 개념

    • @Scheduled는 정해진 주기마다 메서드를 실행하는 어노테이션이다.
    • 백그라운드에서 자동으로 실행되며 주로 배치 작업, 통계 집계, 외부 API 호출 등 반복 작업에 사용

    🔧 사용 전 설정

    @Configuration
    @EnableScheduling
    public class SchedulerConfig {
    }
    @Component
    public class SampleScheduler {
        @Scheduled(fixedDelay = 5000)
        public void task() {
            System.out.println("5초마다 실행");
        }
    }

    2. 다양한 실행 옵션

    속성 설명
    fixedRate 메서드 시작 시점 기준 반복 (밀리초)
    fixedDelay 메서드 종료 시점 기준 반복 (밀리초)
    initialDealy 최초 실행 지연 시간
    cron CRON 표현식 기반

     

    @Scheduled(fixedRate = 10000) // 10초마다
    @Scheduled(fixedDelay = 10000, initialDelay = 2000)
    @Scheduled(cron = "0 0 * * * *") // 매 정시 실행

     


    3. cron 표현식 완전 정리

    ┌───────────── 초 (0-59)
    │ ┌───────────── 분 (0-59)
    │ │ ┌───────────── 시 (0-23)
    │ │ │ ┌───────────── 일 (1-31)
    │ │ │ │ ┌───────────── 월 (1-12)
    │ │ │ │ │ ┌───────────── 요일 (0-6, 일=0)
    │ │ │ │ │ │
    │ │ │ │ │ │
    * * * * * *

     

    예시:

    • 0 0/5 * * * * ->매 5분마다 실행
    • 0 0 9 * * MON-FRI -> 평일 오전 9시 실행
    • 0 0 2 1 * * -> 매월 1일 새벽 2시

    4. @Async - 비동기 처리 핵심

     

    ✅ 기본 사용법

    @EnableAsync
    @Configuration
    public class AsyncConfig {}
    
    @Component
    public class AsyncService {
        @Async
        public void asyncTask() {
            // 별도 스레드에서 실행
            System.out.println("비동기 작업 수행");
        }
    }
    • 별도의 스레드에서 병렬로 실행 
    • 리턴값이 있는 경우 @Async + CompletableFuture<T>로 사용

    ⚙️ 5.  작동원리 - 프록시 기반

    • @Async는 내부적으로 Spring AOP 프록시를 사용
    • 호출자가 같은 클래스 내의 메서드를 직접 호출하면 비동기 작동하지 않음
    • 반드시 다른 Bean이 호출해야 작동함

    6. @Scheduled + @Async 병렬 실행

    • 기본적으로 @Scheduled는 싱글 스레드로 작동
    • 작업이 오래 걸리면 병렬 처리 불가

    ✅ 병렬 실행 방법

    @Scheduled(fixedRate = 1000)
    @Async
    public void doWork() {
        System.out.println(Thread.currentThread().getName());
    }

     

    ⚠️ 주의

    • @EnableScheduling과 @EnableAsync 모두 선언해야 함
    • 비동기 실행 시 Exception은 별도 처리 필요

    7. Custom Executor 설정 

    @Configuration
    @EnableAsync
    public class AsyncExecutorConfig implements AsyncConfigurer {
        @Override
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(5);
            executor.setMaxPoolSize(10);
            executor.setQueueCapacity(100);
            executor.setThreadNamePrefix("AsyncExecutor-");
            executor.initialize();
            return executor;
        }
    }
    • Async는 여기서 정의한 Executor를 사용함

    8. 예외 처리 전략

    • 비동기 작업에서 발생한 예외는 @AsyncUncaughtExceptionHandler로 처리 가능
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) -> {
            log.error("Async Error in {}: {}", method.getName(), ex.getMessage());
        };
    }

    9. 실무 적용 사례

    • 특정 시간마다 로그 정리 or 메일 발송 (@Scheduled)
    • 다량의 알림 발송 (@Async)
    • 외부 API 비동기 호출 (@Async)
    • 실시간 분석 작업 분산 처리

    ✅ 정리

    항목 핵심 요약
    @Scheduled 주기적 실행 (기본은 싱글 스레드)
    @Async 별도 스레드에서 비동기 실행
    병렬 처리 @Scheduled + @Async 조합 필수
    실무 적용 대용량 처리, 외부 연동, 백그라운드 작업
    확장 방법 Custom Executor 설정, 예외 핸들러 구성

    🔜 다음 포스팅 예고

    Spring Batch 핵심 개념 완전 정복 - Step, Job, Reader/Processor/Writer 구조부터 실무 적용까지