스프링의 Quartz 를 통해 간단히 스케줄러를 등록해봤다.
Quartz 트리거, 설정파일 부분을 기록 했으며,
실제 업무에 사용되는 실행 로직은(Job) 원하는 기능을 클래스파일에 구현하면됨. (여기서는 Myjob.class로 나온다)
1. pom.xml에서 의존성 주입
<!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.0</version>
</dependency>
2. Quartz 스케줄러 등록
예제 파일 : QuartzConfigTest.java
스케줄러를 3가지 요소로 구성해보면 스케줄러, 실행내용인 Job, Job을 실행할 Trigger 이다.
( 스케줄러를 빈으로 등록하고 트리거를 설정해 호출하며, 호출할 Job 클래스 파일을 생성하면 끝!)
스케줄러를 빈으로 등록 할 때 자바 기반으로 설정해주었다. Spring의 @Configuration 어노테이션으로 설정 클래스를 정의 하고, @Bean 어노테이션으로 SchedulerFactoryBean을 정의해 스케줄러를 빈으로 등록한다. 이렇게 생성된 스케줄러는 Spring 컨텍스트의 일부로 관리되며, 자동으로 초기화되고 애플리케이션 종료 시 자동으로 종료된다.
아래 코드를 따라가며 작업(Job)과 트리거(Trigger)를 설정하는 코드를 보면
JobDetailFactoryBean으로 Quartz 작업을 정의하고, CronTriggerFactoryBean을 사용하여 크론 표현식을 기반으로 트리거를 설정한다.
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@Configuration
public class QuartzConfigTest {
// ① JobDetailFactoryBean 으로 Quartz 작업의 세부 정보를 설정
@Bean
public JobDetailFactoryBean jobDetail() {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(MyJob.class); // 작업 클래스 설정
// 작업의 이름, 그룹, 설명, 내구성 여부(durability), 저장 여부 등을 설정
factoryBean.setDescription("Sample Quartz Job");
factoryBean.setDurability(true);
return factoryBean;
}
// ② CronTriggerFactoryBean 으로 트리거 설정(작업 실행 시점)
@Bean
public CronTriggerFactoryBean cronTrigger() {
CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail().getObject());
factoryBean.setCronExpression("0 0/5 * * * ?"); // 크론표현식으로 매 5분마다 실행 정의
return factoryBean;
}
// ③ SchedulerFactoryBean
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
Properties properties = new Properties(); // Quartz 스레드 풀 설정을 위한 Properties 객체 생성
// Quartz의 스레드 풀의 크기를 1로 지정.
// 즉, 스레드 풀에서 한 번에 하나의 스레드만 실행되도록 함.
properties.setProperty("org.quartz.threadPool.threadCount", "1"); //Singleton 스레드 처리
// ★SchedulerFactoryBean 객체 생성.
// 이 객체는 Spring에서 Quartz 스케줄러를 관리하기 위한 빈이다.
SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
// Quartz 스케줄러에 Properties 적용
scheduler.setQuartzProperties(properties);
// 트리거를 스케줄러에 설정
scheduler.setTriggers(cronTrigger().getObject());
// n개의 트리거를 설정시 쉼표로 이어서 설정 가능
// ex) firstCronTrigger().getObject(), secondCronTrigger().getObject()
return scheduler; // 설정된 SchedulerFactoryBean 객체 반환
}
}
@Configuration과 @Bean의 조합은 스프링의 핵심적인 설정 메커니즘을 제공하며, 특히 프록시를 통한 싱글톤 보장이 가능해집니다.
@Bean 메서드의 역할: 컨테이너는 @Bean 어노테이션이 붙은 메서드를 찾아 해당 메서드가 반환하는 객체를 Spring 애플리케이션 컨텍스트에 빈으로 등록합니다.
컨테이너가 빈을 등록하고 관리하는 과정에 대해서 헷갈린다면 아래 블로그를 추천하며 출처 남깁니다.
- 먼저 @Configuration이 붙은 클래스를 찾습니다. 이 클래스들이 설정 정보를 담고 있습니다.
- 그다음 @Component, @Controller, @Service, @Repository 등의 어노테이션이 붙은 클래스들을 찾아서 빈으로 등록합니다.
- @Bean이 붙은 메서드들을 찾아 그 메서드가 반환하는 객체들도 빈으로 등록합니다.
- 이렇게 등록된 빈들의 의존관계를 분석하고 필요한 경우 자동으로 주입해 줍니다.
출처: https://curiousjinan.tistory.com/entry/deep-dive-spring-container-configuration-and-bean#빈의 범위(Scope)란%3F-1 [오늘도 개발중입니다:티스토리]
3. Job.class 생성
위 예제 소스에서는 MyJob.class라는 이름으로 기능하고자 하는 로직을 구성해 생성하면 된다.
(서비스 로직.. 반복문을 돌며 db를 조회하여 쿠폰을 발급한다 등등. 스케줄러 주기 동안 수행해야 할 로직을 작성)
Scheduler 등록 방법에 대한 추가 메모
스케줄러는 Quartz의 핵심 인터페이스로, 잡(Job)을 스케줄링하고 관리하는 역할을 한다.
Quartz 스케줄러에서 Scheduler를 인스턴스화하고 사용하는 대표적 사용법이 두가지가 있는데
첫째, StdSchedulerFactory 로 직접 인스턴스화 해 사용하는 것이고
둘째, 이 포스팅에 설명한 내용으로 SchedulerFactoryBean 을 사용하여 스케줄러를 Spring 컨텍스트에 빈으로 등록하고, 관리하는 방법이다.
두번째 방법이 더 쉽게 스케줄링 작업을 설정하고 관리할 수 있다고 하여 사용했는데 실제로 코드 작성 구조가 단일화 되기 때문에 다른 사람이 작성한 코드를 알아보기도 쉬운 것 같다.
첫째, StdSchedulerFactory
StdSchedulerFactory를 사용하여 직접 Scheduler 인스턴스화 하는 방법.
이 팩토리는 내부적으로 Quartz 설정 파일을 읽어 스케줄러를 초기화 함.
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzStdSchedulerExample {
public static void main(String[] args) {
try {
// SchedulerFactory를 통해 기본 Scheduler 인스턴스를 생성합니다.
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
// 작업(Job) 정의
JobDetail job = JobBuilder.newJob(MyJob.class)
.withIdentity("myJob", "group1")
.build();
// 트리거 정의 (10초마다 실행)
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10)
.repeatForever())
.build();
// 스케줄러에 작업과 트리거를 스케줄링
scheduler.scheduleJob(job, trigger);
// 다른 작업 추가 또는 스케줄러 유지 작업 수행...
// 스케줄러 종료 (필요할 때)
scheduler.shutdown(true);
} catch (SchedulerException se) {
se.printStackTrace();
}
}
}
둘째, SchedulerFactoryBean
* Spring은 SchedulerFactoryBean을 통해 Quartz 스케줄러를 관리하며, 이 방식은 Spring 애플리케이션 내에서 Quartz 작업을 통합 관리하기에 적합함.
@Bean
public SchedulerFactoryBean scheduler(Trigger trigger, JobDetail job, DataSource quartzDataSource) {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
schedulerFactory.setJobFactory(springBeanJobFactory());
// JobDetail 및 Trigger 등록
schedulerFactory.setJobDetails(job);
schedulerFactory.setTriggers(trigger);
schedulerFactory.setDataSource(quartzDataSource);
return schedulerFactory;
}
이제 Spring 애플리케이션 컨텍스트가 시작될 때, SchedulerFactoryBean이 자동으로 Quartz 스케줄러를 초기화하고 시작한다. Spring이 스케줄러의 생명주기를 관리하므로, 별도의 코드로 스케줄러를 시작하거나 종료할 필요가 없다.
'BackEnd > Spring' 카테고리의 다른 글
@Value 애너테이션이 property 값을 null로 받아오는경우 (0) | 2024.08.14 |
---|---|
[Spring] MVC HandlerInterceptor / Interceptor를 사용하여 HTTP 요청을 가로채는 방법 (0) | 2023.06.19 |
[Spring] com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class 오류 해결 (0) | 2023.02.28 |
MVC 패턴, Dispatcher-Servlet 정리 (0) | 2023.01.05 |
[SPRING] @RequestBody / @ResponseBody / Jackson2HttpMessageConverter (0) | 2022.10.26 |