티스토리 뷰
일정한 시간간격 또는 일정한 시각에 특정 로직을 돌리기 위해서 사용하는 것을 Scheduler라고 합니다. 이런 Scheduler는 Spring에서 Spring Scheduler와 Spring Quartz라는 2가지 방식으로 제공됩니다.
제가 했던 프로젝트에서는 Spring Scheduler 를 사용하여 1일 1주일 1달 별 랭킹을 구하는 예시로 사용했던 적이 있습니다.
Spring Scheduler
Spring Scheduler는 별도의 추가적인 의존성이 필요하지 않습니다. Spring Boot starter에 기본적인 의존성으로 제공됩니다. 사용하기 위해서는 @EnableScheduling 어노테이션을 붙여주면 됩니다.
package com.nice.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication
public class NiceApplication {
public static void main(String[] args) {
SpringApplication.run(NiceApplication.class, args);
}
}
@Scheduled 어노테이션 메서드에 붙여 주기만 하면 됩니다. 해당 어노테이션의 내부 값으로 scheduler가 실행 될 타이밍을 정할 수 있습니다. scheduling을 할 메서드는 2개의 조건을 가집니다.
- method는 void의 return 타입을 가진다. ❗
- method는 파라미터를 가질 수 없습니다.❗
@Scheduled(fixedDelay = 1000) // scheduler 끝나는 시간 기준으로 1초 간격으로 실행
@Component
public class SpringScheduler {
@Scheduled(fixedDelay = 1000)
public void test1() throws InterruptedException{
System.out.println("test1 : Park");
Thread.sleep(5000); // 5초 지연
}
@Scheduled(fixedDelay = 1000)
public void test2() {
System.out.println("test2 : Jin");
}
@Scheduled(fixedDelay = 1000)
public void test3() {
System.out.println("test3 : Min");
}
}
1초마다 스케쥴러가 실행되는 메소드를 만들었습니다.
5초간 대기 시간이 있는 test1과 별개로 test2 test3 메소드는 1초마다 수행될 것 같지만 test1이 끝나야 test2, test3가 실행됩니다.
실행결과 화면을 보면 실제 스레드는 하나만 사용하고 있습니다.
Scheduler는 기본적으로 thread 1개를 이용하여 동기 형식으로 진행됩니다.
즉 1번 스케줄이 끝나지 않으면 2번 스케줄이 시작시간이 되었다고 하더라도 시작되지 않습니다. 비동기 형식으로 진행하시고 싶으시다면 @EnableAsync 어노테이션을 이용할 수 있습니다
@Async 비동기로 구현
Main에 @EnableAsync 붙이기
@EnableAsync
@EnableScheduling
@SpringBootApplication
public class NiceApplication {
...
}
@Component
public class SpringScheduler {
@Async
@Scheduled(fixedDelay = 1000)
public void test1() throws InterruptedException {
System.out.println("start Park : " + Thread.currentThread().getName());
Thread.sleep(3000);
System.out.println("end Park : " + Thread.currentThread().getName());
}
@Async
@Scheduled(fixedDelay = 1000)
public void test2() {
System.out.println("start Jin : " + Thread.currentThread().getName());
System.out.println("end Jin : " + Thread.currentThread().getName());
}
@Async
@Scheduled(fixedDelay = 1000)
public void test3() {
System.out.println("start Min : " + Thread.currentThread().getName());
System.out.println("end Min : " + Thread.currentThread().getName());
}
}
1초마다 스케쥴러가 실행되면서 각각의 스레드를 실행하는 것을 볼 수 있습니다.
동기 실행
즉 @Ascyn 어노테이션을 달지 않고 동기적으로 구현한다면 그림 1처럼 구현되고
비동기 방법을 사용한다면 작업 1이 수행되는 동안 작업2 작업 3도 수행됩니다.
Scheduler Cron 식
cron = "* * * * * *"
* 초 *분 *시 *일 *월 *요일 *년도
<!-- 5분 마다 실행 ex) 00:05, 00:10. 00:15.... -->
@Scheduled(cron = "0 0/5 * * * *")
<!-- 1시간 마다 실행 ex) 01:00, 02:00, 03:00.... -->
@Scheduled(cron = "0 0 0/1 * * *")
<!-- 매일 오후 18시마다 실행 ex) 18:00 -->
@Scheduled(cron = "0 0 18 * * *")
<!-- 2018년도만 매일 오후 18시마다 실행 ex) 18:00 -->
@Scheduled(cron = "0 0 18 * * * 2018")
<!-- 매일 오후 18시00분-18시55분 사이에 5분 간격으로 실행 ex) 18:00, 18:05.....18:55 -->
@Scheduled(cron = "0 0/5 18 * * *")
<!-- 매일 오후 9시00분-9시55분, 18시00분-18시55분 사이에 5분 간격으로 실행 -->
@Scheduled(cron = "0 0/5 9,18 * * *")
<!-- 매일 오후 9시00분-18시55분 사이에 5분 간격으로 실행 -->
@Scheduled(cron = "0 0/5 9-18 * * *")
<!-- 매달 1일 00시에 실행 -->
@Scheduled(cron = "0 0 0 1 * *")
<!-- 매년 3월내 월-금요일 10시 30분에만 실행 -->
@Scheduled(cron = "0 30 10 ? 3 MON-FRI")
<!-- 매월 마지막날 저녁 10시에 실행 -->
@Scheduled(cron = "0 0 10 L * ?")
<!-- cron에 TimeZone 설정 추가 -->
@Scheduled(cron = "0 15 10 15 * ?", zone = "Asia/Seoul") // cron에 TimeZone 설정 추가
'Spring Boot' 카테고리의 다른 글
Spring Boot + Redis 적용 (2) | 2022.03.22 |
---|---|
JUnit5 Test Code 작성 (0) | 2021.12.17 |
Spring Boot 프로젝트 생성하기 (0) | 2021.06.27 |
롬복(Lombock) 어노테이션 (0) | 2021.05.06 |
Vue.js ,Springboot 로 구현하는 다중 파일 업로드 심화 (0) | 2021.05.04 |