Spring Boot 3 에서 동적 스케줄링이 필요해 어떤 방법으로 할까 고민하다가 비동기 형태의 방식으로
ThreadPool 을 만들어 실행했다.
어플리케이션의 메인쓰레드, TaskScheduler 의 쓰레드, TaskExecutor 쓰레드는 각각 다른
Thread Pool 을 만들어놓고 사용한다.
여기서 @Async 는 TaskExecutor 의 쓰레드를 사용해 비동기 처리한다.
1. @Async 사용을 위한 Config 설정
package com.deotis.wisevoiceweb.system.config;
import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
@Bean(name = "taskExecutor")
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2); // 기본 스레드 수
executor.setMaxPoolSize(5); // 최대 스레드 수
executor.setQueueCapacity(100); // 대기 큐 크기
executor.setThreadNamePrefix("async-executor-");
// 종료 시 대기 설정 추가
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(30);
executor.initialize();
return executor;
}
}
Executor 는 멀티쓰레드 작업을 효율적이고 유연하게 처리하기 위해 사용된다.
TaskExecutor 쓰레드 풀을 사용하기 위해 ThreadPoolTaskExecutor 를 사용해 설정했다.
중요한 설정
// 종료 시 대기 설정 추가
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(30);
executor.setWaitForTasksToCompleteOnShutdown(true);
Spring Context 가 종료될 때 설정된 ThreadPoolTaskExecutor 가 관리하는 쓰레드들 중 아직 실행중인 작업이 있으면
작업이 끝날 때까지 기다리겠다는 설정이다. (true 일 경우 기다리고 false 일 경우 강제 종료)
executor.setAwaitTerminationSeconds(30);
위 설정인 .setWaitForTasksToCompleteOnShutdown(true) 가 true 설정일 경우 Spring 이
얼마나 오래 기다릴 것인지 설정하는값이다.
위 설정처럼 30초면 30초까지 기다리고 그 이후에는 강제 종료한다.
✅ 요약 정리
설정 항목 |
의미 |
디폴트 |
실무 중요도 |
setWaitForTasksToCompleteOnShutdown(true) |
앱 종료 시 남아 있는 작업이 끝날 때까지 기다림 |
false |
매우 중요 |
setAwaitTerminationSeconds(30) |
기다리는 최대 시간 설정 |
0 |
중요 (너무 짧으면 작업 중단됨) |
2. @Async 어노테이션 사용하기
ThreadPoolTaskExecutor 에 미리 만들어둔 쓰레드를 사용해 비동기 작업을 진행한다.
@Service
public class BatchService {
@Async("taskExecutor")
public void executeJob(BatchEntity b) {
...필요한 비동기 로직 수행
}
}