che01 님의 블로그
Spring @EnableScheduling과 @Scheduled 동작 원리 본문
@EnableScheduling 애너테이션의 역할
@EnableScheduling을 설정 클래스에 추가하면 Spring은 내부적으로 스케줄링 관련 인프라를 자동으로 구성한다.
@SpringBootApplication
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
내부 동작 메커니즘
1. ScheduledExecutorService 등록
Spring은 @EnableScheduling이 활성화되면 ScheduledExecutorService를 빈으로 등록한다. 기본적으로 단일 스레드 풀을 사용하는 ThreadPoolTaskScheduler를 생성한다.
2. @Scheduled 메서드 스캔 및 등록
애플리케이션 컨텍스트 초기화 시점에 Spring은 모든 빈을 스캔하여 @Scheduled 애너테이션이 붙은 메서드를 찾는다. 이후 각 메서드의 스케줄링 정보를 추출하여 ScheduledTaskRegistrar에 등록한다.
3. 백그라운드 스레드 실행
등록된 스케줄링 작업들은 메인 애플리케이션 로직과는 완전히 분리된 별도의 스레드에서 실행된다. 이 스레드는 애플리케이션이 종료될 때까지 지속적으로 유지된다.
@Scheduled 사용 예시
@Component
public class ScheduledTasks {
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
System.out.println("Current time: " + new Date());
}
@Scheduled(fixedDelay = 3000)
public void doSomething() {
// 이전 실행 완료 후 3초 대기
}
@Scheduled(cron = "0 0 12 * * ?")
public void dailyTask() {
// 매일 12시에 실행
}
}
기본 실행 방식의 특징
순차 실행
기본적으로 여러 @Scheduled 메서드가 있다면 하나의 스레드에서 순차적으로 실행된다. 이는 한 작업이 오래 걸리면 다른 작업의 실행이 지연될 수 있음을 의미한다.
예외 처리
@Scheduled 메서드에서 예외가 발생하면 해당 작업만 중단되고 다른 스케줄링 작업에는 영향을 주지 않는다. 하지만 반복 실행되는 작업의 경우 예외 발생 시 해당 작업의 이후 실행이 중단될 수 있다.
TaskExecutor 커스터마이징
멀티스레드 환경에서 스케줄링 작업을 실행하려면 TaskExecutor 를 커스터마이징할 수 있다.
@Configuration
@EnableScheduling
public class SchedulingConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean
public Executor taskExecutor() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(10);
scheduler.setThreadNamePrefix("scheduled-task-");
scheduler.initialize();
return scheduler;
}
}
스레드 풀 관리
생명주기
- 애플리케이션 시작 시: 스레드 풀 생성 및 초기화
- 런타임: 백그라운드에서 지속적으로 스케줄링 작업 실행
- 애플리케이션 종료 시: 스레드 풀 정리 및 리소스 해제
리소스 관리
Spring은 애플리케이션 종료 시 스케줄링 스레드를 자동으로 정리한다. 하지만 커스텀 TaskScheduler를 사용하는 경우 적절한 shutdown 로직을 구현해야 한다.
주의사항
동시성 문제
여러 스케줄링 작업이 동일한 자원에 접근하는 경우 동시성 문제가 발생할 수 있다. 이런 경우 동기화 메커니즘을 적용해야 한다.
메모리 누수
장기간 실행되는 스케줄링 작업에서 메모리 누수가 발생하지 않도록 주의해야 한다. 특히 정적 참조나 캐시 사용 시 주의가 필요하다.
트랜잭션 처리
@Scheduled 메서드에서 데이터베이스 작업을 수행하는 경우 @Transactional을 함께 사용하여 트랜잭션 경계를 명확히 해야 한다.
'Spring' 카테고리의 다른 글
| Spring @Async 비동기 처리와 프록시 (4) | 2025.07.10 |
|---|---|
| 트랜잭션 격리수준 (Transaction Isolation Levels) (0) | 2025.07.01 |
| Self-invocation Problem (0) | 2025.06.24 |
| JPA N+1 문제 완벽 해결하기 - EntityGraph를 활용한 성능 최적화 (0) | 2025.06.10 |
| JPA 상속관계 매핑 전략 완전 정리 (2) | 2025.06.09 |