본문 바로가기
BackEnd/Spring

[Spring] Quartz 를 통한 스케줄링 등록

by 성은2 2024. 9. 3.

스프링의 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 애플리케이션 컨텍스트에 빈으로 등록합니다.

 

컨테이너가 빈을 등록하고 관리하는 과정에 대해서 헷갈린다면 아래 블로그를 추천하며 출처 남깁니다.

  1. 먼저 @Configuration이 붙은 클래스를 찾습니다. 이 클래스들이 설정 정보를 담고 있습니다.
  2. 그다음 @Component, @Controller, @Service, @Repository 등의 어노테이션이 붙은 클래스들을 찾아서 빈으로 등록합니다.
  3. @Bean이 붙은 메서드들을 찾아 그 메서드가 반환하는 객체들도 빈으로 등록합니다.
  4. 이렇게 등록된 빈들의 의존관계를 분석하고 필요한 경우 자동으로 주입해 줍니다.

출처: 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이 스케줄러의 생명주기를 관리하므로, 별도의 코드로 스케줄러를 시작하거나 종료할 필요가 없다.