이번에는 1탄의 Spring Scheduler 사용에 이어서 Spring Quartz 사용에 대해 알아보고자 한다.
Spring Scheduler와 Quartz 별개이므로 Quartz를 바로 사용하고자 한다면 다시 참고할 필요는 없다.
▼ 아래는 1탄의 링크이다. 간단한 Scheduler의 기능만 사용하고 싶다면 아래의 방식으로 하는 것이 가장 빠르다.
[ 환경 설정 ]
그럼 이제 Spring Quartz를 다루어 보겠다.
Spring Quartz는 Spring Scheduler와는 달리 세부적인 통제를 위해 여러가지 설정이 가능하다.
그 중에서도 제일 중요한 기능은 클러스터링인 것 같지만, 아직 Legacy 프로젝트에서 클러스터링 설정 후 제대로 동작하는지는 확인하지 못했다. 그래도 하단부에서 에러가 뜨지 않은 설정까지는 작성해서 공유해보고자 한다.
일단, 기본적인 환경은 1탄과 동일하며 다음과 같다.
- Java : 1.8
- Spring Fremawork version : 3.1.1
- slf4j : 1.6.6
[ 적용 방법 ]
1. pom.xml 설정 추가
<!-- Scheduler를 위한 Quartz 의존성 추가 -->
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz-jobs -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.0</version>
</dependency>
<!-- spring-context-support - Quartz 지원 스프링 라이브러리 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework-version}</version>
</dependency>
2. xml 파일 설정
<context:component-scan base-package="" />
1탄과 마찬가지로 위의 base-package의 위치를 스캔하는 코드가 있는 xml에 적용하면 될 것 같다.
base-package 자체는 보통 base-package를 프로젝트의 가장 윗단으로 해두기 때문에 그대로 두면 되고,
글쓴이의 경우는 해당 코드가 servlet-context.xml에 있기에 해당 파일에 아래의 코드를 추가하였다.
<!-- Spring Quartz Start -->
<!-- Job -->
<!-- bean의 id인 job은 원하는 이름으로 설정 가능 -->
<beans:bean id="job" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- property의 ref는 스케줄러 서비스 구현 객체(ServiceImpl)의 bean 이름(다음 코드블럭 참고) -->
<beans:property name="targetObject" ref="ScheduleJob" />
<!-- property의 value는 스케줄러 서비스 구현 객체에서 스케줄러를 사용할(주기적으로 실행할) 메소드 -->
<beans:property name="targetMethod" value="saveTest" />
<!-- 동시 실행 방지 기능(단일 서버에서 작동하는 기능으로 보임) -->
<beans:property name="concurrent" value="false" />
</beans:bean>
<!-- Trigger -->
<!-- bean의 id인 jobTrigger는 원하는 이름으로 설정 가능 -->
<beans:bean id="jobTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- property의 ref는 job의 id와 일치시켜야 함 -->
<beans:property name="jobDetail" ref="job" />
<!-- cron표현식으로 스케줄러가 주기적으로 실행될 기간 설정 가능, 현재 value의 크론식은 1시간마다 -->
<beans:property name="cronExpression" value="0 0 0/1 1/1 * ?" />
</beans:bean>
<!-- Scheduler -->
<!-- bean의 id인 jobScheduler는 원하는 이름으로 설정 가능 -->
<beans:bean id="jobScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!-- 스케줄러로 작동시킬 트리거 목록 지정(여러 개의 트리거를 등록해 사용 가능) -->
<beans:property name="triggers">
<!-- list안에 작성한 트리거를 추가 -->
<beans:list>
<!-- ref의 bean 값은 트리거 id값 -->
<beans:ref bean="jobTrigger" />
</beans:list>
</beans:property>
<!-- quartzProperties를 설정 가능한 곳(name 안에서 자동완성(ctrl + space) 기능을 실행해보면 그 외 여러가지 항목이 있음 -->
<beans:property name="quartzProperties">
<beans:props>
<!-- 클러스터링 설정(동작 여부는 제대로 확인되지 않음) -->
<beans:prop key="org.springframework.scheduling.quartz.jobStore.isClustered">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<!-- Spring Quartz End -->
나머지 코드는 주석을 참고하면 되는데, 클러스터링을 설정하는 부분은 구글링을 해보았으나 찾을 수 없었다.
그래서 추측을 통해 작성해보았는데 name에 quartzProperties 항목이 뜨고 에러가 발생하지 않았기에 해당 방식이 맞지 않을까 조심스레 예상해본다.
* 특히, scheduler에서 서버 간 중복 실행 방지를 위해 '@configuration nor does it declare any @bean methods ~~' 에러를 만났다면 클러스터링까지 넘어왔을 수 있는데 참고하면 될 것 같다. 하지만 아직 해당 현상은 프로젝트 일정 상 보류한 채 해결하지 못했다.
** 크론 표현식은 하단의 CronMaker 사이트에서 변환하여 사용하면 되며, 1탄에서 설명하였지만 표현식에서 6자리까지만 사용해야 에러가 발생하지 않는다. (CronMaker에선 7자리 => 마지막 뒷자리 제외해서 사용)
▼ CronMaker 사이트
3. Service, ServiceImpl (Java) 작성
/** ScheduleService(interface) **/
public interface ScheduleService {
void saveTest();
}
/** ScheduleServiceImpl(class) **/
@Service("ScheduleJob") //xml파일 job의 targetObject에 설정하는 bean 값
@DisallowConcurrentExecution //동시 실행 방지 어노테이션 => 구글링 참조
//클러스터링에서는 동작하지 않는다는 글을 보아서 연구가 더 필요
public class ScheduleServiceImpl implements ScheduleService {
@Autowired
private TestDao testDao;
//스케줄러로 작동할 메소드(xml파일 job의 targetMethod 부분에 설정)
@Override
public void saveTest(){
TestVO testVO = new TestVO();
{ 중략 }
testDao.addTest(testVO);
}
}
이렇게 하면 Spring Quartz 설정은 끝났다. Spring Scheduler에 비해서 설정하는 부분이 조금 더 많지만, 막상 해보면 그렇게 많거나 어렵지는 않다. 자료가 없어서 헤매는 시간이 많을 뿐이기에, 이 글이 시간을 줄이는 것에 많은 도움이 되었으면 좋겠다.
어쨌거나 위와 같은 단계를 통해 코드를 작성하면, Spring Quartz로 스케줄러가 정상 동작하는 것을 확인할 수 있다!
🤞 도움이 되셨기를 바랍니다. 한 번의 클릭과 댓글은 어딘가의 누군가에게 진실로 큰 힘이 됩니다. 🐱🏍
댓글