@Scheduled

코딩냥이·2024년 9월 10일

Annotation

목록 보기
17/34

@Scheduled

@Scheduled 어노테이션은 스프링 프레임워크에서 메소드를 주기적으로 실행하도록 스케줄링하는 데 사용됩니다.

기능

  • 메소드를 일정한 간격으로 반복 실행하게 합니다.
  • 특정 시간에 메소드를 실행하도록 설정할 수 있습니다.
  • Cron 표현식을 사용하여 복잡한 스케줄링 패턴을 지정할 수 있습니다.

사용 방법

기본적인 사용 방법은 다음과 같습니다:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

    @Scheduled(fixedRate = 5000)
    public void reportCurrentTime() {
        System.out.println("현재 시간: " + new Date());
    }
}

주요 특징

  1. 다양한 스케줄링 옵션: 고정 지연, 고정 비율, Cron 표현식 등 다양한 스케줄링 옵션을 제공합니다.
  2. 메소드 레벨 어노테이션: 개별 메소드에 적용되어 해당 메소드만 스케줄링합니다.
  3. 스프링 관리: 스프링 컨테이너에 의해 관리되므로 다른 스프링 기능과 잘 통합됩니다.
  4. 비동기 실행 지원: @Async와 함께 사용하여 비동기적으로 작업을 실행할 수 있습니다.

스케줄링 옵션

1. 고정 지연 (Fixed Delay)

작업 완료 후 지정된 시간만큼 대기한 후 다음 작업을 시작합니다.

@Scheduled(fixedDelay = 5000) // 5초 지연
public void scheduleFixedDelayTask() {
    // 작업 내용
}

2. 고정 비율 (Fixed Rate)

이전 작업의 시작 시간으로부터 지정된 시간이 지나면 새 작업을 시작합니다.

@Scheduled(fixedRate = 5000) // 5초마다
public void scheduleFixedRateTask() {
    // 작업 내용
}

3. 초기 지연 (Initial Delay)

애플리케이션 시작 후 첫 실행까지의 지연 시간을 설정합니다.

@Scheduled(fixedRate = 5000, initialDelay = 1000) // 1초 후 시작, 이후 5초마다
public void scheduleFixedRateWithInitialDelayTask() {
    // 작업 내용
}

4. Cron 표현식

복잡한 스케줄링 패턴을 지정할 수 있습니다.

@Scheduled(cron = "0 15 10 * * ?") // 매일 오전 10시 15분에 실행
public void scheduleTaskUsingCronExpression() {
    // 작업 내용
}

스케줄링 활성화

스케줄링을 사용하려면 @EnableScheduling 어노테이션을 구성 클래스에 추가해야 합니다:

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class SchedulerConfig {
}

동적 스케줄링

런타임에 스케줄을 변경해야 하는 경우, SchedulingConfigurer를 구현할 수 있습니다:

@Configuration
@EnableScheduling
public class DynamicSchedulerConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
            () -> {
                // 실행할 작업
            },
            triggerContext -> {
                // 다음 실행 시간을 결정하는 로직
                return new CronTrigger("0 15 10 * * ?").nextExecutionTime(triggerContext);
            }
        );
    }
}

비동기 실행

@Async와 함께 사용하여 스케줄된 작업을 비동기적으로 실행할 수 있습니다:

@EnableAsync
@Configuration
@EnableScheduling
public class SchedulerConfig {
}

@Component
public class AsyncScheduledTasks {

    @Async
    @Scheduled(fixedRate = 1000)
    public void scheduleFixedRateTaskAsync() throws InterruptedException {
        System.out.println("Fixed rate task async - " + System.currentTimeMillis() / 1000);
        Thread.sleep(2000);
    }
}

테스트

스케줄된 작업을 테스트할 때는 awaitility 라이브러리를 사용하면 편리합니다:

import static org.awaitility.Awaitility.*;
import static java.util.concurrent.TimeUnit.*;

@SpringBootTest
class ScheduledTasksTest {

    @Test
    void testScheduledTask() {
        await().atMost(10, SECONDS).untilAsserted(() -> {
            // 스케줄된 작업이 실행되었는지 확인하는 로직
        });
    }
}

주의사항

  1. 동시성 고려: 기본적으로 스케줄된 작업은 단일 스레드에서 실행됩니다. 장기 실행 작업은 다른 스케줄된 작업을 지연시킬 수 있습니다.
  2. 예외 처리: 스케줄된 메소드에서 발생한 예외는 해당 실행을 중단시키지만, 이후 스케줄링은 계속됩니다.
  3. 시간 드리프트: fixedRate를 사용할 때 작업 실행 시간이 간격보다 길어지면 시간 드리프트가 발생할 수 있습니다.

베스트 프랙티스

  1. 적절한 간격 선택: 너무 짧은 간격은 시스템에 부담을 줄 수 있으므로 적절한 간격을 선택하세요.
  2. 오류 처리: 스케줄된 작업 내에서 발생할 수 있는 예외를 적절히 처리하세요.
  3. 로깅: 스케줄된 작업의 시작, 종료, 소요 시간 등을 로깅하여 모니터링하세요.
  4. 트랜잭션 관리: 데이터베이스 작업을 포함하는 경우 적절한 트랜잭션 관리를 고려하세요.
  5. 테스트: 스케줄된 작업에 대한 단위 테스트와 통합 테스트를 작성하세요.

결론

@Scheduled 어노테이션은 스프링 애플리케이션에서 반복적인 작업을 쉽게 구현할 수 있게 해줍니다. 데이터 정리, 보고서 생성, 알림 전송 등 다양한 주기적 작업에 활용될 수 있습니다. 그러나 동시성, 성능, 오류 처리 등을 신중히 고려하여 사용해야 합니다.

연관 포스팅

@EnableScheduling
@Async
@Configuration
@Component
@EnableAsync

profile
HelloMeow~!

0개의 댓글