로컬에서는 정상 작동하던 크론잡이 EC2 서버에서는 정상적으로 실행되지 않았다.
크론잡(@Scheduled)은 서버 시간대(Timezone)를 기준으로 작동한다.
로컬은 'Asia/Seoul', EC2는 'UTC' 시간대를 사용하고 있었다. 즉, 크론 표현식 기준 시간이 달라져 실행되지 않은 것처럼 보인 것이다.
EC2 인스턴스의 시간대 설정
EC2 인스턴스에 접속하여 시간대 설정이 어떻게 되어있는지 확인해본다. ('timedatectl' 명령어로 가능)
현재 'UTC' 시간대로 설정되어있는 모습을 확인할 수 있었다.
'sudo timedatectl set-timezone Asia/Seoul' 명령어로 시간대를 현지 지역과 시간에 맞게 변경해주었다.
Docker 컨테이너의 시간대를 호스트와 동기화
docker-compose.yml 스크립트를 수정하여 컨테이너가 EC2의 시간대와 동일하게 작동하도록 설정하였다.
services:
app:
...
volumes:
- /etc/localtime:/etc/localtime:ro
@Scheduled(cron = "0 0 8 * * ?", zone = "Asia/Seoul")
public void sendDailyEmailToSubscribers() {
log.info("일일 이메일 발송 작업 시작: {}", LocalDateTime.now());
List<Subscriber> subscribers = subscribeService.getAllSubscribers();
if (subscribers.isEmpty()) {
log.info("구독자가 없습니다. 이메일 발송을 건너뜁니다.");
return;
}
String subject = "마이니치 니홍고 - 오늘의 일본어 학습";
String content = contentService.generateDailyContent();
int successCount = 0;
int failCount = 0;
for (Subscriber subscriber : subscribers) {
boolean sent = emailService.sendEmail(subscriber.getEmail(), subject, content);
if (sent) {
successCount++;
} else {
failCount++;
}
}
log.info("일일 이메일 발송 완료 - 성공: {}, 실패: {}", successCount, failCount);
}
결국 이번 문제는 코드상에 문제가 있다기 보다는 배포 환경의 시간대 설정이 문제였다.
크론잡을 사용할 때는 항상 시간대를 명시하거나 서버의 시간대를 확인하자