본문 바로가기
Web Development/Spring Legacy

[Spring / Legacy] Spring 스케줄러 사용하기 - 2탄. Spring Quartz

by 감자맹고우 2022. 3. 23.
728x90
반응형

이번에는 1탄의 Spring Scheduler 사용에 이어서 Spring Quartz 사용에 대해 알아보고자 한다.

Spring Scheduler와 Quartz 별개이므로 Quartz를 바로 사용하고자 한다면 다시 참고할 필요는 없다.

 

▼ 아래는 1탄의 링크이다. 간단한 Scheduler의 기능만 사용하고 싶다면 아래의 방식으로 하는 것이 가장 빠르다.

 

[Spring / Legacy] Spring 스케줄러 사용하기 - 1탄. Spring Scheduler

Spring Scheduler, Spring Quartz에 대한 정보는 많다. 하지만 대부분 Boot 환경에 대한 정보이고, Legacy 환경에서 구축된 정보는 거의 없다. 그래서 그에 대한 정보를 공유하고자 한다. 일단 기본적인 환경

devlifetestcase.tistory.com

 

[ 환경 설정 ]

 

그럼 이제 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 사이트

 

CronMaker

 

www.cronmaker.com

 

 

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로 스케줄러가 정상 동작하는 것을 확인할 수 있다!

 

🤞 도움이 되셨기를 바랍니다. 한 번의 클릭과 댓글은 어딘가의 누군가에게 진실로 큰 힘이 됩니다. 🐱‍🏍

 

728x90
반응형

댓글