Spring 크론 vs 유닉스 크론 vs Quartz
스케줄이 엉뚱하게 도는 경우는 대부분 다른 종류의 크론식을 그대로 가져와서입니다. 세 가지는 비슷해 보여도 자리 수, 요일 번호, 일·요일을 합치는 방식이 다릅니다.
| Spring (@Scheduled) | 유닉스 crontab | Quartz | |
|---|---|---|---|
| 자리 수 | 6 — 초부터 | 5 — 초 없음 | 6 또는 7 (연도) |
| 일요일 | 0 또는 7 | 0 또는 7 | 1 |
| 월요일 | 1 | 1 | 2 |
| 일 + 요일 지정 | 둘 다 맞아야 실행 | 하나만 맞아도 실행 | 한쪽은 ? |
L, W, # | 지원 | 미지원 | 지원 |
자주 쓰는 Spring 크론 예시
| 표현식 | 뜻 |
|---|---|
| */30 * * * * * | 30초마다 |
| 0 */5 * * * * | 5분마다 |
| 0 0 * * * * | 매시 정각 |
| 0 0 9 * * * | 매일 09:00 |
| 0 0 9 * * MON-FRI | 매주 월~금요일 09:00 |
| 0 0/30 9-18 * * MON-FRI | 매주 월~금요일 9~18시 사이 30분마다 |
| 0 0 0 1 * * | 매월 1일 00:00 |
| 0 0 23 L * * | 매월 마지막 날 23:00 |
| 0 0 10 * * MON#1 | 매월 첫째 월요일 10:00 |
| 0 0 18 * * FRIL | 매월 마지막 금요일 18:00 |
| 0 0 9 15W * * | 매월 15일에 가장 가까운 평일 09:00 |
L은 그달의 마지막 날, L-2는 말일 이틀 전, 15W는 15일에 가장 가까운 평일(달을 넘어가지 않음)입니다. 요일 자리의 FRIL은 마지막 금요일, MON#2는 둘째 월요일입니다.
운영에서 자주 겪는 문제
- 스레드가 하나뿐입니다. Spring Boot 스케줄러 풀은 기본 1개(
spring.task.scheduling.pool.size=1)라서 작업 하나가 오래 걸리면 다른 스케줄도 밀립니다. - 인스턴스마다 다 실행됩니다. 서버가 3대면 하루 한 번 보내는 메일이 3통 나갑니다. ShedLock 같은 잠금을 쓰거나 한 대에서만 돌리세요.
- 시간대가 어긋납니다. 컨테이너는 대개 UTC 입니다.
zone을 명시하세요. - 등록된 작업 확인. Spring Boot Actuator 의
/actuator/scheduledtasks에서 실제로 등록된 크론식을 볼 수 있습니다. 설정값이 의도대로 들어갔는지 확인할 때 유용합니다.