본문 바로가기
IT 프로젝트 수행

Spring Boot와 Quartz: 강력한 스케줄링 통합

by 별프로 2025. 1. 13.
반응형

Quartz는 Java 기반의 오픈소스 스케줄링 라이브러리로, 정교한 작업 스케줄링을 제공합니다. Spring Boot와 Quartz를 결합하면 간단한 설정으로 강력한 스케줄링 기능을 활용할 수 있습니다. 이 글에서는 Quartz의 기본 개념과 Spring Boot에서의 구현 방법을 설명합니다.

1. Quartz란?

Quartz는 반복 작업, 예약 작업 등을 효율적으로 처리하기 위한 스케줄링 라이브러리입니다. 주요 특징은 다음과 같습니다:

  • Job: 실행할 작업을 정의합니다.
  • Trigger: Job의 실행 시점을 정의합니다.
    • SimpleTrigger: 일정 간격 반복.
    • CronTrigger: 복잡한 스케줄 관리.
  • Scheduler: Job과 Trigger를 관리하고 실행합니다.

 

2. Spring Boot와 Quartz 연동

의존성 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
    

기본 설정

spring.quartz.job-store-type=jdbc # JDBC를 통해 Job 저장
spring.quartz.jdbc.initialize-schema=always # Quartz 테이블 초기화
spring.quartz.scheduler-name=MyQuartzScheduler
    

 

3. Job과 Trigger 정의

Job 클래스 구현

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class SampleJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Sample Job 실행: " + System.currentTimeMillis());
    }
}
    

JobDetail과 Trigger 설정

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail sampleJobDetail() {
        return JobBuilder.newJob(SampleJob.class)
                .withIdentity("sampleJob")
                .storeDurably()
                .build();
    }

    @Bean
    public Trigger sampleJobTrigger() {
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10)
                .repeatForever();

        return TriggerBuilder.newTrigger()
                .forJob(sampleJobDetail())
                .withIdentity("sampleTrigger")
                .withSchedule(scheduleBuilder)
                .build();
    }
}
    

 

4. CronTrigger로 복잡한 스케줄링

@Bean
public Trigger cronJobTrigger() {
    return TriggerBuilder.newTrigger()
            .forJob(sampleJobDetail())
            .withIdentity("cronTrigger")
            .withSchedule(CronScheduleBuilder.cronSchedule("0/15 * * * * ?")) // 15초마다 실행
            .build();
}
    

Cron 표현식 구조:

[초] [분] [시간] [일] [월] [요일] [연도 (옵션)]

예: 0 0 9 * * ? (매일 오전 9시에 실행)

 

5. 동적 Job 생성과 제어

Dynamic Job Scheduler 서비스

import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DynamicJobSchedulerService {

    @Autowired
    private Scheduler scheduler;

    public void scheduleJob(String jobName, String jobGroup, String cronExpression) throws SchedulerException {
        JobDetail jobDetail = JobBuilder.newJob(SampleJob.class)
                .withIdentity(jobName, jobGroup)
                .build();

        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(jobName + "Trigger", jobGroup)
                .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
                .build();

        scheduler.scheduleJob(jobDetail, trigger);
    }

    public void pauseJob(String jobName, String jobGroup) throws SchedulerException {
        scheduler.pauseJob(JobKey.jobKey(jobName, jobGroup));
    }

    public void resumeJob(String jobName, String jobGroup) throws SchedulerException {
        scheduler.resumeJob(JobKey.jobKey(jobName, jobGroup));
    }

    public void deleteJob(String jobName, String jobGroup) throws SchedulerException {
        scheduler.deleteJob(JobKey.jobKey(jobName, jobGroup));
    }
}
    

Controller를 통한 API 연동

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

    @Autowired
    private DynamicJobSchedulerService schedulerService;

    @PostMapping("/schedule")
    public String scheduleJob(@RequestParam String jobName,
                              @RequestParam String jobGroup,
                              @RequestParam String cronExpression) {
        try {
            schedulerService.scheduleJob(jobName, jobGroup, cronExpression);
            return "Job scheduled successfully!";
        } catch (SchedulerException e) {
            return "Error scheduling job: " + e.getMessage();
        }
    }

    @PostMapping("/pause")
    public String pauseJob(@RequestParam String jobName, @RequestParam String jobGroup) {
        try {
            schedulerService.pauseJob(jobName, jobGroup);
            return "Job paused successfully!";
        } catch (SchedulerException e) {
            return "Error pausing job: " + e.getMessage();
        }
    }

    @PostMapping("/resume")
    public String resumeJob(@RequestParam String jobName, @RequestParam String jobGroup) {
        try {
            schedulerService.resumeJob(jobName, jobGroup);
            return "Job resumed successfully!";
        } catch (SchedulerException e) {
            return "Error resuming job: " + e.getMessage();
        }
    }

    @DeleteMapping("/delete")
    public String deleteJob(@RequestParam String jobName, @RequestParam String jobGroup) {
        try {
            schedulerService.deleteJob(jobName, jobGroup);
            return "Job deleted successfully!";
        } catch (SchedulerException e) {
            return "Error deleting job: " + e.getMessage();
        }
    }
}
    

 

6. Listener를 활용한 Job/Trigger 모니터링

JobListener 구현

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.listeners.JobListenerSupport;
import org.springframework.stereotype.Component;

@Component
public class SampleJobListener extends JobListenerSupport {

    @Override
    public String getName() {
        return "SampleJobListener";
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        System.out.println("Job 실행 준비: " + context.getJobDetail().getKey());
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        System.out.println("Job 실행 완료: " + context.getJobDetail().getKey());
        if (jobException != null) {
            System.out.println("Job 실행 중 오류: " + jobException.getMessage());
        }
    }
}
    

Listener 등록

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class QuartzListenerConfig {

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private SampleJobListener sampleJobListener;

    @PostConstruct
    public void addListeners() throws SchedulerException {
        scheduler.getListenerManager().addJobListener(sampleJobListener);
    }
}
    

 

7. Quartz의 데이터베이스 설정

Quartz는 JDBC를 통해 Job과 Trigger를 영구적으로 저장할 수 있습니다. 데이터베이스에 Quartz 테이블을 생성하려면 Quartz 배포판의 SQL 스크립트를 사용하십시오. 스크립트는 Quartz 공식 사이트에서 확인할 수 있습니다.

 

Quartz Enterprise Job Scheduler

 

Quartz Enterprise Job Scheduler

What is the Quartz Job Scheduling Library? Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can

www.quartz-scheduler.org

 

반응형

'IT 프로젝트 수행' 카테고리의 다른 글

shell 작업 스케줄 수행, Crontab의 개념  (0) 2025.01.10

댓글