서론
예전에 커뮤니티 사이트에서 글목록을 수집하고 DB에 저장하는 크롤러를 만든적이 있었다. 이 때, 주기적으로 실행하기 위해서 crontab이나 Windows 작업 스케줄러를 사용했다. 이 두개의 스케줄러는 사용하기는 편하지만 프로그램과 스케줄을 별도로 관리해야하기 때문에 관리포인트가 늘어나는 단점이 있다.
그래서, 이번에는 스케줄러를 직접 만들어보려고 하는데 Spring Batch는 써본적이 있기 때문에 이번에는 Quartz로 만들어 보려고 한다.
개발환경
- jdk-11.0.5
- quartz-2.3.2
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.3.2</version>
</dependency>
Quartz란?
    - Java Scheduling 라이브러리. 
    - 일련의 작업들을 단발성, 주기성으로 실행할 수 있음.
구성요소
1. JOB
- 실제 작업을 수행하는 객체
- org.quartz.Job 인터페이스를 상속받아 execute 메소드에 수행 로직을 구현
- 같은 그룹에는 동일한 이름을 가진 Job을 생성할 수 없음
2. Trigger
    - Job을 수행하기위한 조건(스케줄)을 정의한 객체
    - 특정시간, 횟수, 반복주기 등을 설정할 수 있음
* 특정시간 및 횟수: SimpleTrigger
* 주기적으로 반복: CronTrigger
    - 같은 그룹에는 동일한 이름을 가진 Job을 생성할 수 없음
    - Job : Trigger = 1 : N
      
3. Listener
- 작업의 시작, 중간, 끝, 에러를 처리할 수 있는 객체
- ScheduleListener와 TriggerListener
소스코드
1. SampleJobExecutor.java
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 
100 
101 
102 
103 
104 
105 
106 
107 
 | 
 import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.HashSet; 
import java.util.Set; 
import org.quartz.CronExpression; 
import org.quartz.CronScheduleBuilder; 
import org.quartz.CronTrigger; 
import org.quartz.Job; 
import org.quartz.JobBuilder; 
import org.quartz.JobDataMap; 
import org.quartz.JobDetail; 
import org.quartz.JobExecutionContext; 
import org.quartz.JobExecutionException; 
import org.quartz.Scheduler; 
import org.quartz.SchedulerException; 
import org.quartz.SchedulerFactory; 
import org.quartz.SimpleScheduleBuilder; 
import org.quartz.SimpleTrigger; 
import org.quartz.Trigger; 
import org.quartz.TriggerBuilder; 
import org.quartz.impl.StdSchedulerFactory; 
import sch.listeners.MyScheduleListener; 
import sch.listeners.MyTriggerListener; 
/** 
 * Quartz Job 
 */ 
public class SampleJobExecutor implements Job { 
    private static final SimpleDateFormat TIMESTAMP_FMT = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSSS");  
    @Override 
    public void execute(JobExecutionContext ctx) throws JobExecutionException { 
        JobDataMap jobDataMap = ctx.getJobDetail().getJobDataMap(); 
        String currentDate = TIMESTAMP_FMT.format(new Date()); 
        String triggerKey = ctx.getTrigger().getKey().toString(); 
        String message = jobDataMap.getString("message"); 
        System.out.println(String.format("[%s][%s] %s", currentDate, triggerKey, message )); 
    } 
} 
/** 
 * Quartz Scheduler 실행 
 */ 
class JobLuacher { 
    public static void main(String[] args) { 
        try { 
            // Scheduler 생성 
            SchedulerFactory factory = new StdSchedulerFactory(); 
            Scheduler scheduler = factory.getScheduler(); 
            scheduler.getListenerManager().addJobListener(new MyScheduleListener()); 
            scheduler.getListenerManager().addTriggerListener(new MyTriggerListener()); 
            // Scheduler 실행 
            scheduler.start(); 
            // JOB Data 객체 생성 
            JobDataMap jobDataMap = new JobDataMap(); 
            jobDataMap.put("message", "Hello, Quartz!!!"); 
            // JOB Executor Class 
            Class<? extends Job> jobClass = SampleJobExecutor.class; 
            // JOB 생성 
            JobDetail jobDetail = JobBuilder.newJob(jobClass) 
                                    .withIdentity("job_name", "job_group") 
                                    .setJobData(jobDataMap) 
                                    .build(); 
            // SimpleTrigger 생성 
            // 4초마다 반복하며, 최대 5회 실행 
            SimpleScheduleBuilder simpleSch = SimpleScheduleBuilder.repeatSecondlyForTotalCount(5, 4); 
            SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger() 
                                            .withIdentity("simple_trigger", "simple_trigger_group") 
                                            .withSchedule(simpleSch) 
                                            .forJob(jobDetail) 
                                            .build(); 
            // CronTrigger 생성 
            // 15초주기로 반복( 0, 15, 30, 45 ) 
            CronScheduleBuilder cronSch = CronScheduleBuilder.cronSchedule(new CronExpression("0/15 * * * * ?")); 
            CronTrigger cronTrigger = (CronTrigger) TriggerBuilder.newTrigger() 
                                        .withIdentity("cron_trigger", "cron_trigger_group") 
                                        .withSchedule(cronSch) 
                                        .forJob(jobDetail) 
                                        .build(); 
            // JobDtail : Trigger = 1 : N 설정 
            Set<Trigger> triggerSet = new HashSet<Trigger>(); 
            triggerSet.add(simpleTrigger); 
            triggerSet.add(cronTrigger); 
            // Schedule 등록 
            scheduler.scheduleJob(jobDetail, triggerSet, false); 
        } catch (ParseException | SchedulerException e) { 
            e.printStackTrace(); 
        } 
    } 
} 
 | 
cs | 
실행결과

마치며
이것으로 간단하게 Quartz로 스케줄러를 만들고 실행하는 방법에 대해서 알아보았다. 만들어보니 Spring Batch보다 훨씬 간단했다. 다만, 스케줄을 Annotation으로 등록할 수 있는 Spring Batch와는 다르게 Trigger 객체를 생성해야하는 번거로움이 있다. 그래도, Quartz가 좀 더 직관적이라 마음에 든다.
'Back-end > JAVA' 카테고리의 다른 글
| [JAVA] Quartz 스케줄러 만들기 (3) - Job 강제 종료 (0) | 2020.11.11 | 
|---|---|
| [JAVA] Quartz 스케줄러 만들기 (2) - Listener (0) | 2020.11.10 | 
| [JAVA] 간단한 HTTP 서버 구축하기 (0) | 2020.11.05 | 
| [JAVA] 파일 분할 - 용량 단위, 아래에서 위로 ↑ (0) | 2020.10.22 | 
| [JAVA] 파일 분할 - 용량 단위, 위에서 아래로 ↓ (0) | 2020.10.22 | 
										
									
										
									
										
									
										
									
댓글