스케줄러는 크게 공부하지 않아도 되었는데... 쿼츠는 진짜 공부해야 구현 가능할 것 같아서 정리해보려고 한다..!
일단, 처음에 난 gpt가 만들어준 코드가 애초에 흐름이 이해가 잘 안되었다..
우리는 알림 테이블이 따로 있는데 스케줄러에 따로 저장시킨다는게 무슨의미인지..? 하지만 이 둘은 목적과 역할이 다르다!
Quartz는 작업 스케줄링을 처리하는 라이브러리이고, 알림 테이블은 알림 데이터를 저장하고 관리하는 곳입니다. Quartz는 스케줄링 라이브러리로, 단순히 특정 시간에 작업(Job)을 자동으로 실행하도록 예약하는 역할을 합니다. 알림 테이블은 그 알림의 내용과 상태를 저장하는 역할을 합니다.
즉, Quartz는 알림을 보내는 작업을 예약하는 스케줄러로서 동작하고, 알림 테이블은 알림의 내용을 관리하는 데이터베이스로 동작하는 것입니다.
Java 기반의 오픈 소스 작업 '스케줄링 라이브러리'를 의미합니다. 이를 사용하면 특정시간에 작업을 실행하거나 특정 간격으로 작업을 수행할 수 있습니다.
실행할 작업을 정의하는 인터페이스
실행될 작업을 정의하고구성하는 인터페이스 << 나머지는 모두 이걸 구성하기 위한 클래스 인터페이스들이다.
JobDetail 인스턴스를 생성하는데 사용되는 유틸리티 클래스
작업의 생명 주기 동안 발생하는 이벤트를 처리하는 인터페이스
작업 실행시 필요한 데이터를 저장하는 맵

작업의 실행 시간을 결정하는 인터페이스
복잡한 실행 스케줄을 정의할 수 있는 Trigger 인터페이스
Trigger 인스턴스를 생성하는데 사용되는 유틸리티 클래스
: trigger도 job도 scheduler도 모두 생성하는 builder클래스가 따로 존재한네..!
작업과 트리거를 관리하고 실행하는 인터페이스
간단한 실행 스케줄을 정의할 수 있는 클래스
복잡한 실행 스케줄을 cron 표현식으로 정의할 수 있는 클래스
Scheduler 인스턴스를 생성하는 클래스
Quarz에서 ‘실행 할 작업을 정의’하는 인터페이스입니다. 실행할 작업은 클래스를 생성하고 해당 Job 인터페이스의 구현체로 작업을 정의하여 사용합니다.
Quatz 스케줄러에 의해 실행되는 작업을 정의합니다. 해당 객체는 JobBuilder를 통해 구성하며 실행하려는 Job의 이름, 그룹, 클래스 타입 등의 정보를 구성합니다.
사용예시
JobDetail jobDetail = JobBuilder
.newJob(MyJob.class)
.withIdentity("myJob", "group1")
.build();
JobBuilder로 구성하며 newJob()메서드를 통해 MyJob라는 Job(사용자가 구현한 job 클래스)을 추가하고 withIdentity()를 통해 그룹을 지정하여 객체를 구성합니다.
Quartz 스케줄러에서 사용하는 유용한 유틸리티 클래스로 JobDetail 인스턴스를 생성합니다. JobDetail 객체를 쉽게 생성하고 작업의 이름, 그룹, 클래스 타입 등의 세부 정보를 설정할 수 있습니다.
[참고] JobBuilder API Document

ex)
JobDetail jobDetail = JobBuilder
.newJob(MyJob.class) // Job의 구현 클래스 설정
.withIdentity("myJob", "group1") // Job의 identity 설정
.withDescription("This is my job") // Job의 설명 설정
.ofType(MyJob.class) // Job의 구현 클래스 설정
.requestRecovery(true) // Job이 실패한 경우 다시 실행하도록 설정
.storeDurably(true) // Job이 지속적으로 저장되도록 설정
.usingJobData("key", "value") // Job의 data map 설정
.build(); // 설정된 정보를 바탕으로 JobDetail 인스턴스 생성
Job의 생명주기를 관리하며 해당 job의 실행 전/중/후에 이벤트를 일어나게 할 수 있다. 대충 그런 의미?로 이해함.

SimpleTrigger는 Trigger로 인스턴스화 해야합니다.
이는 TriggerBuilder를 통해 구성하며 withSchedule() 메서드를 통해서 SimpleScheduleBuilder를 구성합니다.
SimpleScheduleBuilder > TriggerBuilder > Trigger 인스턴스
💡 SimpleScheduleBuilder 사용예시
- Trigger를 인스턴스화 할때 TriggerBuilder를 사용하여 구성합니다.
- TriggerBuilder에서는 simpleSchedule을 사용하여 구성하였고 10초마다 영원히 반복되는 트리거를 사용하였습니다.
// Trigger 생성
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10)
.repeatForever())
.build();
CroneScheduleBuilder > TriggerBuilder > Trigger 인스턴스
CroneScheduleBuilder + DateBuilder > TriggerBuilder > CronTrigger 인스턴스
💡 CronScheduleBuilder 사용예시
- Trigger를 인스턴스화 할때 TriggerBuilder를 사용하여 구성합니다.
- TriggerBuilder에서는 cronSchedule을 사용하여 구성하였고 10초마다 반복되는 트리거를 사용하였습니다.
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("fcmSendTrigger", "fcmGroup") // Trigger 이름, 그룹 지정
.withDescription("FCM 처리를 위한 조회 Trigger") // Trigger 설명
.startNow()
.withSchedule(
CronScheduleBuilder
.cronSchedule("0/10 * * * * ?")
)
.build();
Trigger는 간단히 말해 작업이 언제 실행될지를 정의하는 것입니다.

스케줄러를 구성하는 과정을 정의한 클래스입니다. Job, Trigger, Scheduler 인스턴스를 생성하여 일정 시간마다 수행하도록 구성합니다.
package com.adjh.multiflexapi.scheduler;
import com.adjh.multiflexapi.scheduler.job.MyJob;
import com.adjh.multiflexapi.scheduler.job.MyJobListener;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* 스케줄러의 설정을 관리합니다.
*
* @author : lee
* @fileName : ScheduleConfig
* @since : 2/28/24
*/
@Configuration
public class SchedulerConfig {
private Scheduler scheduler;
public SchedulerConfig(Scheduler scheduler) {
this.scheduler = scheduler;
}
/**
* 스케줄러의 실제 처리 과정을 담당합니다.
*/
@PostConstruct
private void jobProgress() throws SchedulerException {
cronScheduler();
}
/**
* SimpleScheduler 구성 메서드
*
* @throws SchedulerException
*/
private void simpleScheduler() throws SchedulerException {
// [STEP1] Job 생성
JobDetail job = JobBuilder
.newJob(MyJob.class) // Job 구현 클래스
.withIdentity("myJob", "myGroup") // Job 이름, 그룹 지정
.withDescription("FCM 처리를 위한 조회 Job") // Job 설명
.build();
// [STEP2] Trigger 생성
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("myTrigger", "myGroup") // Trigger 이름, 그룹 지정
.withDescription("FCM 처리를 위한 조회 Trigger") // Trigger 설명
.startNow()
.withSchedule(
SimpleScheduleBuilder
.simpleSchedule()
.withIntervalInSeconds(5)
.repeatForever())
.build();
// [STEP3] 스케줄러 생성 및 Job, Trigger 등록
scheduler = new StdSchedulerFactory().getScheduler();
MyJobListener myJobListener = new MyJobListener();
scheduler.getListenerManager().addJobListener(myJobListener);
scheduler.start();
scheduler.scheduleJob(job, trigger);
}
/**
* CronScheduler 구성 메서드
*/
private void cronScheduler() throws SchedulerException {
// [STEP1] Job 생성
JobDetail job = JobBuilder
.newJob(MyJob.class) // Job 구현 클래스
.withIdentity("myJob", "myGroup") // Job 이름, 그룹 지정
.withDescription("FCM 처리를 위한 조회 Job") // Job 설명
.build();
CronTrigger cronTrigger = TriggerBuilder
.newTrigger()
.withIdentity("fcmSendTrigger", "fcmGroup") // Trigger 이름, 그룹 지정
.withDescription("FCM 처리를 위한 조회 Trigger") // Trigger 설명
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")).build();
// [STEP3] 스케줄러 생성 및 Job, Trigger 등록
scheduler = new StdSchedulerFactory().getScheduler();
MyJobListener myJobListener = new MyJobListener();
scheduler.getListenerManager().addJobListener(myJobListener);
scheduler.start();
scheduler.scheduleJob(job, cronTrigger);
}
}