본문 바로가기
★ 프로젝트 + 트러블 슈팅 ★

[JAVA] Spring @Scheduled

by 리승우 2022. 11. 24.

스케줄링 사용하기

스프링에서 스케줄링을 사용하기 위해서는 Main 클래스에 @EnableScheduling 어노테이션을 붙여줘야 한다.

@SpringBootApplication
@EnableScheduling
public class Application {
	
    public static void main(String[] args) {
    	SpringApplication.run(Application.class, args);
    }
}

5초마다 현재 시간을 출력하는 코드를 작성해 보면 아래와 같다.

@Component
public class TestScheduler {

	@Scheduled(cron = "0/5 * * * * *")
	public void test() {
		System.out.println("now: " + LocalDateTime.now());
	}
}

코드를 작성하고 실행을 누르면 아래와 같이 5초마다 현재시각이 출력되는 것을 볼 수 있다.

 

 

1. cron 표현식

1
@Scheduled(cron = "0 30 23 * * *")
cs

위의 시간은 매일 23시 30분으로 표현된 식이다.

문자열의 좌측부터 우측까지 순서대로 의미가 있고 각 항목은 space 문자로 구분한다.

자세한 사항은 아래와 같다.

순서  필드명 표현 가능한 값
1 seconds 0~59 , - * /
2 minutes 0~59 , - * / 
3 hours 0~23 , - * /
4 day of month 1~31 , - * ? / L W
5 month 1~12 or JAN-DEC , - * /
6 day of week 1-7 or SUN-SAT , - * ? / L #
7 years (optional) 1970~2099 , - * /

위처럼 자리수 마다 쓸수 있는 값들이 있다.

 

2. 특수문자 의미

특수문자  의미  사용예 
*  모든 수를 의미  seconds에서 사용하면 매초, minutes에서 사용하면 매분, hours에서 사용하면 매시간 
?  해당 항목을 사용하지 않음   day of month에서 사용하면 월중 날짜를 지정하지 않음. 
 day of week에서 사용하면 주중 요일을 지정하지 않음 
-  기간을 설정  hours에서 10-12이면 10시, 11시, 12시에 동작
 minutes에서 58-59이면 58분, 59분에 동작
,  특정 시간을 지정  day of week에서 2,4,6이면 월,수,금에만 동작함 
/  시작시간과 반복 간격 설정  seconds위치에 0/15로 설정하면 0초에 시작해서 15초 간격으로 동작 
 minutes위치에 5/10으로 설정하면 5분에 시작해서 10분 간격으로 동작 
L  마지막 기간에 동작
 day of month, day of week에서만 사용
 day of month에서 사용하면 해당월 마지막 날에 수행
 day of week에서 사용하면 토요일에 수행
W  가장 가까운 평일 동작
 day of month에만 사용
 15W로 설정하면 15일이 토요일이면 가장 가까운 14일 금요일에 실행
 15W로 설정하고 15일이 일요일이면 16일에 실행
 15W로 설정하고 15일이 평일이면 15일에 실행
LW  L과 W의 조합  그달의 마지막 평일에 동작
#  몇 번째 주와 요일 설정
 day of week에 사용
 6#3이면 3 번째 주 금요일에 동작 
 4#2이면 2번째 주 수요일에 동작

 

3. 사용예

 표현식  의미
 0 0 12 * * *  매일 12시에 실행
 0 15 10 * * *   매일 10시 15분에 실행
 0 * 14 * * *   매일 14시에 0분~59분까지 매분 실행
 0 0/5 14 * * *  매일 14시에 시작해서 5분 간격으로 실행
 0 0/5 14,18 * * *   매일 14시, 18시에 시작해서 5분 간격으로 실행
 0 0-5 14 * * *  매일 14시에 0분, 1분, 2분, 3분, 4분, 5분에 실행
 0 0 20 ? * MON-FRI  월~금일 20시 0분 0초에 실행
 0 0/5 14 * * ?   아무요일, 매월, 매일 14:00부터 14:05분까지 매분 0초 실행 (6번 실행됨) 
 0 15 10 ? * 6L   매월 마지막 금요일 아무날이나 10:15:00에 실행 
 0 15 10 15 * ?  아무요일, 매월 15일 10:15:00에 실행  
 * /1 * * * *  매 1분마다 실행 
 * /10 * * * *  매 10분마다 실행  

 

 

4. fixedRate, fixedDelay

1
@Scheduled(fixedDelay = 3600000// 1000 * 60 * 60, 즉 1시간마다 실행한다.
cs

위의 예저처럼 사용할수있는데요. 5000 -> 5초이다.

fixedDelay : 지정된 시간 간격으로 작업을 실행 이전 수행이 시작된 시점부터 delay후에 재호출 (이전 수행이 완료된 시점부터 delay후에 재호출)

fixedRate : 지정한 시간 주기로 작업을 실행 (* 이전 수행의 종료를 기다리지 않고 수행됨)

예제 ) @Scheduled(fixedRate=5000) <- 이런경우 종료되기전에 5초마다 계속 수행된다.

두 가지의 차이점은 종료 후 실행되느냐 종료되기 전에 실행되느냐 차이!

 

예시

  • 0  0  14   *   *   *             : 매일 오후 2시
  • 0  0  0  1   *   *                : 매달 1일 0시
  • 0  5  1  ?  7  MON-WEB : 매년 7월 월-수 1시 5분

내가 적용한 코드

매월 21 ~ 30일, 8시 41분 0초에 실행되게 설정하였다.

 

Scheduler의 아쉬운점

1. void형식만 지원한다.

2. 매개변수를 넣을 수 없다.

    @Scheduled(cron = "0 41 20 21-30 * *")
    public void test() {

        long rand = (long)(Math.random() * productRepository.count()) + 1;

        LocalDateTime dateTime = LocalDateTime.now();

        Product findProduct = productRepository.findById(rand).orElseThrow(
                () -> new CustomCommonException(ErrorCode.NOT_FOUND_PRODUCT));

        Event event = new Event(findProduct.getTitle(), "깜짝세일", "오늘만 특가예요", 100L, dateTime, dateTime.plusDays(1));
        eventRepository.saveAndFlush(event);
    }
}

 

댓글