Develop

Spring Framework의 Scheduled 스케줄 동적으로 실행 방법

issuemaker99 2025. 2. 17. 15:19
728x90

Spring에서 @Scheduled을 동적으로 시작/중지하려면 TaskScheduler ScheduledFuture를 사용해야 합니다.

기본적으로 @Scheduled은 고정된 스케줄로 실행되므로 실행 중지나 동적 시작이 어렵습니다. 하지만 ScheduledExecutorService 또는 ThreadPoolTaskScheduler를 사용하면 동적으로 스케줄을 제어할 수 있습니다.


🔹 동적으로 스케줄 시작 및 중지하는 방법

1️⃣ ThreadPoolTaskScheduler 사용

Spring의 ThreadPoolTaskScheduler를 활용하여 동적으로 작업을 실행 및 중단할 수 있습니다.
이 방법을 사용하면 REST API 또는 UI 버튼을 통해 스케줄링을 제어할 수 있습니다.


 1. 설정: TaskScheduler 빈 생성

먼저, 동적 스케줄링을 제어할 ThreadPoolTaskScheduler 빈을 설정합니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class SchedulerConfig {

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(5);  // 최대 5개의 스레드 사용 가능
        scheduler.setThreadNamePrefix("DynamicScheduler-");
        scheduler.initialize();
        return scheduler;
    }
}

 2. 동적 스케줄링을 관리할 서비스 클래스

이제 TaskScheduler를 활용하여 스케줄을 동적으로 관리하는 서비스를 만듭니다.

import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;

import java.util.concurrent.ScheduledFuture;

@Service
public class DynamicSchedulerService {

    private final ThreadPoolTaskScheduler taskScheduler;
    private ScheduledFuture<?> scheduledTask;

    public DynamicSchedulerService(ThreadPoolTaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
    }

    // ✅ 스케줄 시작
    public void startSchedule() {
        if (scheduledTask == null || scheduledTask.isCancelled()) {
            scheduledTask = taskScheduler.schedule(this::runTask, new CronTrigger("0/5 * * * * *")); // 5초마다 실행
            System.out.println("스케줄이 시작되었습니다.");
        }
    }

    // ✅ 스케줄 중단
    public void stopSchedule() {
        if (scheduledTask != null) {
            scheduledTask.cancel(false);
            System.out.println("스케줄이 중단되었습니다.");
        }
    }

    // 실행할 작업
    private void runTask() {
        System.out.println("동적 스케줄 실행: " + System.currentTimeMillis());
    }
}

 

설명

  • ThreadPoolTaskScheduler를 사용하여 동적으로 스케줄링 작업을 실행 및 취소합니다.
  • ScheduledFuture<?> scheduledTask를 통해 현재 실행 중인 작업을 추적합니다.
  • startSchedule() → 크론 표현식 (0/5 * * * * *)으로 5초마다 작업 실행
  • stopSchedule() → 실행 중인 작업을 취소

 3. REST API로 스케줄 제어

위의 DynamicSchedulerService를 활용하여 스케줄을 시작/중지하는 컨트롤러를 추가합니다.

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/scheduler")
public class SchedulerController {

    private final DynamicSchedulerService schedulerService;

    public SchedulerController(DynamicSchedulerService schedulerService) {
        this.schedulerService = schedulerService;
    }

    // ✅ 스케줄 시작
    @PostMapping("/start")
    public String startScheduler() {
        schedulerService.startSchedule();
        return "스케줄이 시작되었습니다.";
    }

    // ✅ 스케줄 중단
    @PostMapping("/stop")
    public String stopScheduler() {
        schedulerService.stopSchedule();
        return "스케줄이 중단되었습니다.";
    }
}

 

테스트 방법

# 스케줄 시작
curl -X POST http://localhost:8080/scheduler/start

# 스케줄 중지
curl -X POST http://localhost:8080/scheduler/stop

 

또는 Postman에서 POST 요청을 보내도 됩니다.


📌 결과 확인

🔹 /scheduler/start 호출 후

스케줄이 시작되었습니다.
동적 스케줄 실행: 1700000000000
동적 스케줄 실행: 1700000005000
동적 스케줄 실행: 1700000010000
...

5초마다 작업 실행

🔹 /scheduler/stop 호출 후

스케줄이 중단되었습니다.

실행이 중단됨


🔥 추가 기능

1️⃣ UI에서 시작/중지 버튼 추가

  • 프론트엔드(React/Vue)에서 버튼을 만들어 API를 호출하면 쉽게 스케줄을 제어할 수 있습니다.
<button onclick="fetch('/scheduler/start', { method: 'POST' })">스케줄 시작</button>
<button onclick="fetch('/scheduler/stop', { method: 'POST' })">스케줄 중단</button>

 정리

방법 설명
@Scheduled 기본적인 스케줄링이 가능하지만 동적 제어 불가능
ThreadPoolTaskScheduler 동적으로 스케줄 시작/중단 가능, 크론 표현식 활용 가능
LIST