일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- mariadb
- local
- duplicate lines
- spring
- install maven
- ^M바꾸기
- jdbc
- Jenkins
- Java
- install
- pkgutil
- not to accept jdbcUrl
- Change port
- svn backup
- maven
- 전송포맷
- ubuntu
- JavaScript
- gradle
- object
- driverspy
- spring boot
- 줄복사
- key bindings
- docker
- ADB
- change file content
- remove
- JAR
- javaascript
- Today
- Total
Simplify
Spring에서 스케줄 기능 사용하기 How to use scheduled task in Spring 본문
Spring에서 스케줄 기능 사용하기 How to use scheduled task in Spring
Simplify - Jonghun 2019. 12. 27. 11:33스프링 프레임워크 처럼 서버 측 개발을 진행하는 동안, 자연스럽게 스케줄된 작업이 필요한 경우가 있습니다. 물론 여러가지 방법으로 이를 구현할 수 있고, 리눅스 환경에서는 간단한 프로그램이나 쉘(shell) 명령어를 crontab 에 등록해서 사용할 수 있습니다.
별도의 배치 프로그램을 사용하는 경우는, 서로 독립적인 프로세스로 동작하기 때문에 개발로 실행되고 관리될 수 있고, 따라서 프로그램들간에 서로 영향을 주지 않고 실행될 수 있습니다. 하지만 별도로 관리되므로 중복 코드가 발생하고 업데이트 하는 데 있어서 불편한 점 등 당연한 장단점이 존재합니다.
어느 하나의 방법이 좋다 라기 보다는, 어떤 상황이든 각 상황에 맞게 취사선택하여 개발 및 구현하는게 맞습니다. 여기서는 서버 온라인 프로그램 내에 스케줄로 등록하여 배치 실행을 할 수 있는 @Scheduled annotation 에 대해 살펴볼 예정입니다.
기본사항
기본적으로 다음 조건들을 만족하고 있어야 합니다.
- 메소드는 void 리턴을 해야하고,
- 어떠한 파라메터도 받을 수 없습니다.
이러한 전제조건 때문에 어렵게 느껴질 수도 있겠지만, 특정 상황에서 단독으로 동작하는 기능이기 때문에 이해가 가는 부분입니다.
스케줄 기능 사용 활성화
@Scheduled annotation 을 사용하려면, 다음과 같이 활성화해주는 작업이 필요합니다. 다음의 두 가지 방법으로 활성화할 수 있습니다.
Java 의 enable-style annotation 이용
@Configuration
@EnableScheduling
public class SpringConfig {
...
}
xml 설정을 이용
<task:annotation-driven>
사실 저는 xml 을 이용해서 설정하는 것 보다는 annotation 을 이용하는 것을 더 선호합니다. 다른 이유는 없고, code 를 통하는 것이 xml 등의 config 파일을 이용하는 것 보다 컴파일에러나 잘못 설정한 부분 등을 더 명확하게 잡아낼 수 있기 때문입니다. 각자 선호하는 방식으로 하면 될 것 같습니다.
일정 간격으로 실행하기
다음과 같은 설정으로 일정 간격으로 실행할 수 있습니다.
@Scheduled(fixedDelay = 1000)
public void scheduleFixedDelayTask() {
System.out.println(
"Fixed delay task - " + System.currentTimeMillis() / 1000);
}
여기서 주의해야 할 점이 몇 가지가 있습니다.
- 이 '간격' 이라고 하는 'fixed delay' 는 앞선 task 의 종료부터 다음 task 의 시작 까지의 간격을 의미합니다. 따라서 앞의 task 가 오래 걸렸다면, 다음 task 의 실행 역시 늦게 실행될 수 밖에 없습니다.
- 위와 같은 이유로, 이 설정으로 실행되는 task 는 동기화된 형태로 실행됩니다. (synchronous)
앞선 동작의 종료가 보장되어야 하는 작업에서 유리합니다. (예. 통계 데이터 생성)
일정 주기로 실행하기
다음 설정으로 일정 주기로 실행하는 것이 가능합니다.
@Scheduled(fixedRate = 1000)
public void scheduleFixedRateTask() {
System.out.println(
"Fixed rate task - " + System.currentTimeMillis() / 1000);
}
이 설정은 각각의 task들이 독립적인(independent) 경우에 사용합니다.
여기서 주의해야 할 사항은 각각의 task 들이 병렬(parallel)로 실행되지 않는다는 점 입니다. 따라서 앞선 작업이 종료되지 않으면 앞선 작업의 종료를 기다리게 됩니다.
만약 병룔로 실행 - 즉, Asynchronous 하게 - 실행하고 싶다면, 다음과 같이 @async annotation 을 넣어줍니다.
@EnableAsync
public class ScheduledFixedRateExample {
@Async
@Scheduled(fixedRate = 1000)
public void scheduleFixedRateTaskAsync() throws InterruptedException {
System.out.println(
"Fixed rate task async - " + System.currentTimeMillis() / 1000);
Thread.sleep(2000);
}
}
이 task는 매 초마다(1000ms = 1s) 실행되며, 앞선 task 의 종료 여부에 영향을 받지 않습니다.
fixedRate vs. fixedDelay
일정 간격으로 실행(fixedDelay) 하는 것은 앞선 task가 종료된 뒤 일정 시간 이후에 실행되므로 얼마나 자주 실행되지 여부를 판단하기 쉽지 않다. 반면에 일정 주기로 실행하는 것은 일정 간격으로 task 가 trigger되므로 메모리 leak 등을 신경쓰지 않아도 됩니다.
하지만 메모리 문제등을 야기할 가능성이 있다면 'out of memory' 에러가 발생할 것이다.
최초 지연시간을 두고 task 실행하기
아래 설정으로 최초에 지연시간을 설정할 수 있습니다.
@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void scheduleFixedRateWithInitialDelayTask() {
long now = System.currentTimeMillis() / 1000;
System.out.println(
"Fixed rate task with one second initial delay - " + now);
}
cron expression을 이용한 설정
@Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression() {
long now = System.currentTimeMillis() / 1000;
System.out.println(
"schedule tasks using cron jobs - " + now);
}
스케줄 설정을 변수화하기
properties 파일에 설정된 정보를 이용하여 다음과같이 설정할 수 있습니다.
고정 지연시간
@Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds}")
일정 간격
@Scheduled(fixedRateString = "${fixedRate.in.milliseconds}")
cron expression 이용
@Scheduled(cron = "${cron.expression}")
xml 파일에 설정하기
다음과 같이 xml 파일에 설정할 수 있습니다.
<!-- Configure the scheduler -->
<task:scheduler id="myScheduler" pool-size="10" />
<!-- Configure parameters -->
<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="beanA" method="methodA"
fixed-delay="5000" initial-delay="1000" />
<task:scheduled ref="beanB" method="methodB"
fixed-rate="5000" />
<task:scheduled ref="beanC" method="methodC"
cron="*/5 * * * * MON-FRI" />
</task:scheduled-tasks>
출처/참고자료