Spring Quartz 재사용 가능한 스케줄링 구조 만들기
이전 포스팅에 Quartz 구현 관련 글을 쓰긴했는데, 재사용을 염두하지 않고 구현했던거라 이번에 스케줄링 작업 몇개 추가하면서 코드를 조금 수정했다.
QuartzService
기존에 있던 QuartzService를 추상 클래스로 만들어 상속 받을 수 있도록 했다. 이렇게 되면 이제 각 도메인이나 필요한 곳에서 가져다 사용할 수 있다.
public abstract class QuartzBaseService {
private final Scheduler scheduler;
public QuartzBaseService(Scheduler scheduler) {
this.scheduler = scheduler;
init();
}
// 추상 메서드
public abstract void initJob();
private void init() {
try {
scheduler.clear();
scheduler.getListenerManager().addJobListener(new QuartzJobListener());
scheduler.getListenerManager().addTriggerListener(new QuartzTriggerListener());
initJob();
if (!scheduler.isStarted()) {
scheduler.start();
}
} catch (Exception e) {
log.error("Quartz 스케줄러 초기화 중 오류 발생", e);
}
}
public void addJob(Class<? extends Job> jobClass, String jobName, String jobDescription,
Map<String, Object> jobDataMap, String cronExpression) {
try {
JobDetail jobDetail = buildJobDetail(jobClass, jobName, jobDescription, jobDataMap);
Trigger trigger = buildCronTrigger(cronExpression, jobName + "Trigger");
if (scheduler.checkExists(jobDetail.getKey())) {
scheduler.deleteJob(jobDetail.getKey());
}
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
log.error("잡 스케줄링 중 SchedulerException 발생: {}", jobName, e);
}
}
private JobDetail buildJobDetail(Class<? extends Job> job, String name, String desc,
Map<String, Object> paramsMap) {
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.putAll(paramsMap);
return JobBuilder.newJob(job)
.withIdentity(name)
.withDescription(desc)
.usingJobData(jobDataMap)
.build();
}
}
그리고 스케줄링 해야 하는 곳에서 initJob()을 구현하면 되는데, 이제는 여러 작업을 관리해야 하다보니 enum으로 만드는게 다른 팀원들과 일할 때도 편할 거 같아 enum으로 작업 내용을 정리햇다.
public enum UserAccountQuartzInfo {
USER_ACCOUNT_DELETE(
"UserAccountDeleteJob",
"회원탈퇴 후 5년이 지난 유저 Hard Delete",
"0 0 * * * ",
UserAccountDeleteJob.class
);
private final String quartzJabName;
private final String quartzJabDescription;
private final String quartzJabCron;
private final Class<? extends Job> jobClass;
UserAccountQuartzInfo(String quartzJabName, String quartzJabDescription, String quartzJabCron,
Class<? extends Job> jobClass) {
this.quartzJabName = quartzJabName;
this.quartzJabDescription = quartzJabDescription;
this.quartzJabCron = quartzJabCron;
this.jobClass = jobClass;
}
public String getQuartzJabName() {
return quartzJabName;
}
public String getQuartzJabDescription() {
return quartzJabDescription;
}
public String getQuartzJabCron() {
return quartzJabCron;
}
public Class<? extends Job> getJobClass() {
return jobClass;
}
}
enum으로 만들었으면 아래와 같이 initJob을 구현하면 Quartz 구현이 끝난다.
public class UserAccountDeleteQuartzService extends QuartzBaseService {
public UserAccountDeleteQuartzService(Scheduler scheduler) {
super(scheduler);
}
@Override
public void initJob() {
Map<String, Object> paramsMap = new HashMap<>();
addJob(UserAccountQuartzInfo.USER_ACCOUNT_DELETE.getJobClass(),
UserAccountQuartzInfo.USER_ACCOUNT_DELETE.getQuartzJabName(),
UserAccountQuartzInfo.USER_ACCOUNT_DELETE.getQuartzJabDescription(),
paramsMap,
UserAccountQuartzInfo.USER_ACCOUNT_DELETE.getQuartzJabCron());
}
}
이렇게 한번 기본 틀을 만들면 이제 어느 도메인에서도 쉽게 상속 받아서 initJob만 구현하면 되기 때문에 여러 작업을 관리하기 편하다.