
이번에 Spring을 이용한 프로젝트에서 스케쥴링 기능을 도입해야하는 순간이 생겼다.
그래서 이번에 Spring Quartz를 통해서 스케쥴링 기능을 구현하였다.
실제 구현 코드에 대해서 이야기 하기 이전에 스케쥴링에 대해서 알면 좋을 것 같다.
스케쥴링이란 일정한 시간 간격으로 반복적인 작업을 수행하는 도구를 의미한다.
나도 마찬가지고, 많은 사람들이 스케쥴링과 배치 프로그램에 대해서 많이 헷갈려 하는 것 같다.
배치 프로그램은 대용량 데이터를 일괄 처리를 위한 프로그램이며, 정해진 시간에 실행되는 것이 아니라 사용자의 명령이 있을 때 실행된다.
이 두 장점을 합쳐서 배치 스케쥴링이라는 프로그램을 사용한다.
배치 스케쥴링은 대량의 데이터를 처리하는 배치 프로그램을 정해진 시간을 기준으로 자동화 처리하는 것을 의미한다.
그렇다면 위에서 이야기한 Spring Quartz 프로그램은 이 중 어떤 것일까?
Spring Quartz은 JAVA 기반의 오픈 소스 작업 ‘스케쥴링 라이브러리’를 의미한다. 이를 사용하면 특정 시간에 작업을 실행하거나 특정 간격으로 작업을 수행할 수 있다.
자 이제 내가 구현했던 코드들에 대해서 설명을 해보겠다.
<!-- 1. 대상이 되는 클래스 정의 -->
<bean name="targetJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"
p:jobClass="com.aimir.nondemand.ModmTargetJob"
p:durability="true">
<property name="jobDataAsMap">
<map>
<entry key="systemDAO" value-ref="SystemDAO"/>
</map>
</property>
</bean>
<!-- 2. Cron 시간 설정 -->
<bean id="targetTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"
p:jobDetail-ref="targetJob"
p:startDelay="1000"
p:cronExpression="0 * * * * ?"/> <!-- 매분 마다 실행 for Modm 관리 -->
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="targetTrigger"/>
</list>
</property>
</bean>
</beans>
위 설정 파일에 대해서 각 단계별로 먼저 이야기해보자.
먼저 1번 단계로 JobDetailFactoryBean 객체에 대한 설정을 한다.
<!-- 1. 대상이 되는 클래스 정의 -->
<bean name="targetJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"
p:jobClass="com.aimir.nondemand.ModmTargetJob"
p:durability="true">
<property name="jobDataAsMap">
<map>
<entry key="systemDAO" value-ref="SystemDAO"/>
</map>
</property>
</bean>
JobDetailFactoryBean 객체는 JobDetail 객체를 만드는 역할을 가지고 있다.
그리고 jopClass Property를 통해서 Job 역할을 수행할 클래스를 지정한다.
jopDataAsMap Property는 Job 역할을 수행할 클래스에게 전달할 파라미터(Bean 객체)를 전달한다.
→ 이 때 당연하게도 Job 클래스에게 전달 될 객체는 Bean 등록이 되어있어야 한다.
→ 추가적으로 Job 클래스는 설정 파일을 통해서 Bean 등록을 하기 때문에, 별도로 @Component 어노테이션등을 통해 Bean 등록을 할 필요는 없다.
2번 단계로는 CronTriggerFactoryBean 객체에 대해 설정을 한다.
<!-- 2. Cron 시간 설정 -->
<bean id="targetTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"
p:jobDetail-ref="targetJob"
p:startDelay="1000"
p:cronExpression="0 * * * * ?"/> <!-- 매분 마다 실행 for Modm 관리 -->
CronTriggerFactoryBean 객체는 작업을 수행할 조건을 정의하고 있는 Trigger 객체에 대한 설정을 한다.
cronExpression 을 통해서 작업을 수행할 조건을 Cron Expression으로 정의한다.
이렇게 설정들을 모두 작성하면 위에서 Bean으로 등록한 Job 클래스를 작성하여야 한다.
public class ModmTargetJob extends QuartzJobBean {
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
try{
SystemDAO systemDAO = (SystemDAO) context.getMergedJobDataMap().get("systemDAO");
Map<String, Object> targets = systemDAO.getModmTarget();
} catch(Exception e){
e.printStackTrace();
}
}
}
QuartzJobBean 클래스를 상속받고, executeInternal 메서드를 오버라이딩한다.
그 후 설정 파일을 통해서 주입해주었던 Bean 객체를 getMergedJobDataMap() 메서드를 통해 주입받을 수 있다.
→ setter()를 통해서 주입 받는 방법도 존재한다고 한다.
Job을 구현한 모든 클래스는 execute method를 구현한다. 그리고 메서드에서 넘어온 JobExecutionContext를 통해 Spring의 ApplicationContext를 찾는다.
이로써 빈 객체를 주입 받을 수 있는 것이다.