반응형
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
반응형
'IT 프로젝트 수행' 카테고리의 다른 글
shell 작업 스케줄 수행, Crontab의 개념 (0) | 2025.01.10 |
---|
댓글