Spring

[Spring Boot] @Scheduled 을 통해 간단한 스케줄링 작업 처리하기

다아빈 2025. 3. 19. 21:25
728x90
반응형

안녕하세요.

 

혼자 프로젝트를 진행하는 도중, 일정 시간마다 특정 로직을 수행해야 하는 부분이 있었습니다. 

저는 스프링 부트에서 제공하는 Scheduler를 이용하여 간단하게 작업을 처리하도록 하였으며, 제가 공부한 내용을 공유하려고 블로그를 작성하게 되었습니다! 

 

아직 바보라.. 만약 틀린 부분이 있다면 친절하게 알려주세요! 감사합니다.

 

ps. 제 프로젝트에서 스케줄러를 적용한 이야기는 나중에 다루도록 하겠습니다 :)! 아직 많이 부족하지만 기대해주세요..!


Spring Scheduler 

Spring Scheduler 는 스프링 프레임워크에서 제공하는 기능으로, 특정 시간이나 주기에 맞춰 특정 작업을 실행하도록 도와줍니다. 

주로 백그라운드에서 반복적으로 수행해야하는 작업이나 정해진 시간에 처리해야 하는 작업을 처리하는 데 사용됩니다.

@Scheduled 어노테이션을 사용하여 간단하게 스케줄링 작업을 설정할 수 있답니다!

스케줄러 활성화

스케줄링 기능은 Spring Boot Starter 패키지에는 내장되어 있습니다. 따라서 프로젝트에 spring-boot-starter 가 포함되어 있다면 별도의 의존성을 추가할 필요는 없습니다.

(대신 API 요청과 함께 스케줄링 기능을 사용하려면 spring-boot-starter-web을 추가해야겠지요?)

 

@EnableScheduling 어노테이션을 사용하여 스케줄링 기능을 사용한다고 명시해줍니다.

@EnableScheduling
@SpringBootApplication
public class CoreApplication {

    public static void main(String[] args) {
        SpringApplication.run(CoreApplication.class, args);
    }

}

 

@EnableScheduling 어노테이션은 클래스 레벨에서 사용되며, 일반적으로 @SpringBootApplication 어노테이션이 붙은 클래스 또는 별도의 @Configuration 클래스 내에 위치합니다.

 

이 어노테이션은 내부적으로 @Scheduled 어노테이션이 붙은 메서드를 찾고, 이를 스케줄러에 등록하는 역할을 합니다.

따라서 이 어노테이션을 붙이지 않는다면  @Scheduled 가 자동으로 감지되지 않아 정상적으로 실행되지 않습니다.

스케줄링할 대상 지정

다음으로 @Scheduled 어노테이션을 통해 스케줄링할 대상을 지정할 것인데, 이때 주의해야할 점이 두 가지가 있습니다.

  • 스케줄링할 메서드가 포함된 클래스는 반드시 스프링 빈으로 등록되어 있어야 합니다. 즉, @Component, @Repository, @Service 와 같은 스프링 빈 등록 어노테이션이 선언된 클래스에서만 사용할 수 있습니다.
  • 일반적으로 @Scheduled 어노테이션이 붙은 메서드는 void 반환 타입을 가져야 합니다. 반환 타입이 void 가 아닌 경우에는 반환 값은 무시됩니다.

다음은 @Scheduled 을 사용하여 10초마다 실행 횟수를 출력하는 간단한 예제입니다.

@Service
public class ScheduledTaskExample {

    private int count = 0;

    @Scheduled(fixedRate = 10000) // 10초마다 실행
    public void executeTask() {
        count++; // 실행 횟수 증가
        System.out.println("실행 횟수: " + count + " (time: " + LocalDateTime.now() + ")");
    }
}

 

이런 식으로 사용하면 된답니다!

@Scheduled 속성

@Scheduled 는 다양한 속성이 있으며, 이를 통해 실행 주기를 설정할 수 있습니다.

fixedRate (고정 실행 주기)

  • 이전 작업이 끝났는지와는 상관없이 설정한 시간 간격으로 작업을 실행합니다.
  • 실행 시간이 길어지더라도 설정된 주기마다 새로운 실행이 시작됩니다.
@Scheduled(fixedRate = 5000) // 5초마다 실행
public void runFixedRateTask() {
}

예를 들어, 실행 시간이 6초가 걸리는 메서드가 있다고 가정하고, 실행 주기는 5초로 설정하겠습니다.

  • 첫 번째 실행: 0초
  • 두 번째 실행: 5초
  • 세 번째 실행: 10초

이런 식으로 실행 시간이 몇 초인지와는 관계없이 5초마다 실행이 시작되는 것입니다! 즉, 중첩 실행이 가능한 거지요.

만약 실행 시간이 실행 주기보다 길어지면 중첩 실행이 될 수 있어, 성능 저하가 발생할 수 있습니다.

fixedDelay (고정 지연 주기)

  • 이전 작업이 끝난 후 일정 시간이 지난 뒤 실행합니다.
@Scheduled(fixedDelay = 5000) // 이전 실행이 끝난 후 5초 후에 실행
public void runFixedDelayTask() {
}

 

똑같이 실행 시간이 6초가 걸리는 메서드가 있다고 가정하고, 실행 주기는 5초로 설정하겠습니다.

  • 첫 번째 실행: 0초, 실행 완료: 6초
  • 두 번째 실행: 6초 (이전 작업이 끝난 시간) + 5초 = 11초, 실행 완료: 17초
  • 세 번째 실행: 17초 (이전 작업이 끝난 시간) + 5초 = 22초

이런 식으로 다음 작업의 실행 시점은 이전 실행이 종료된 시점 + 실행 주기 가 되는 것입니다. 즉, 중첩 실행은 발생하지 않겠지요.

대신 실행 시간이 길어지는 경우, 실행 주기가 점점 밀릴 수 있답니다.

initialDelay (초기 지연 실행)

  • 애플리케이션 시작 후, 일정 시간이 지난 후에 첫 번째 실행이 수행됩니다.
  • 이는 fixedRate, fixedDelay와 함께 사용할 수 있습니다.
@Scheduled(fixedRate = 5000, initialDelay = 10000) // 애플리케이션 시작 후 10초 후 실행, 이후 5초마다 실행
public void runInitialDelayTask() {
}

위의 예시처럼 initialDelay 를 10초로 설정해보겠습니다.

  • 애플리케이션의 시작: 0초
  • 첫 번째 실행: 10초 
  • 두 번째 실행: 15초
  • 세 번째 실행: 20초
  • 이후 5초마다 실행 (fixedRate 로 설정하여 메서드 실행 시간과는 상관없음)

이렇게 initialDelay를 설정하면, 애플리케이션의 시작하고 10초 후부터 실행을 하게됩니다. 

서버가 시작되자마자 작업을 수행하면 부하가 걸릴 수 있어, 이를 방지하기 위해 initialDelay를 설정하기도 한답니다.

cron

  • Cron 표현식을 사용하여 특정 시간에 실행하도록 설정할 수 있습니다. 
  • "초 분 시 일 월 요일" 형식으로 설정할 수 있습니다.
@Scheduled(cron = "0 0 12 * * ?") // 매일 12시 정각에 실행
public void runCronTask() {
}

위의 "0(초) 0(분) 12(시) *(일) *(월) ?(요일)" 은 매일 12시 정각에 실행시키겠다는 뜻입니다.

먼저 왼쪽부터 각각 무엇을 의미하는지 설명드리겠습니다.

필드 값의 범위 예시
0-59 0
0-59 0
0-23 12
1-31 *
1-12 또는 JAN-DEC *
요일 1-7 또는 SUN-SAT ?

 

크론 표현식에서는 *, ? 와 같은 다양한 특수 문자도 사용할 수 있습니다

기호 의미 예시
* 모든 값 0 * * * * * → 매 분 0초마다 실행
, 여러 개 값 지정 0 0,15,30 * * * * → 매시 0분, 15분, 30분마다 실행
- 범위 지정 0 0 9-18 * * * → 9시부터 18시까지 매 정각마다 실행
/ 간격 지정 0 0/10 * * * * → 매 10분마다 실행
? 특정 값을 지정하지 않음 (일, 요일 필드에서 사용) 0 0 12 * * ? → 매일 12시 정각 실행
L 마지막 날 0 0 12 L * ? → 매월 마지막 날 12시에 실행
W 가장 가까운 평일 0 0 9 15W * ? → 매월 15일에 가장 가까운 평일 오전 9시에 실행
# 특정 요일 지정 (요일 필드에서만 사용) 0 0 10 ? * 2#1 → 매월 첫 번째 월요일 오전 10시에 실행

 

유닉스의 크론 표현식과 스프링 부트에서 사용하는 크론 표현식은 필드 개수, 요일 값 등의 다른 점이 있으므로 사용하실 때 주의하셔야 합니다!

 

728x90
반응형