Spring Schedular 사용법과 사용 이유

비구름·2024년 12월 29일

Spring

목록 보기
2/10

Spring Schedular를 공부하게된 이유

공부용 프로젝트에서 휴지통에 1달이상 있었던 모든 Todo를 삭제한다는 기능을 만들게되며 다양한 방법을 모색하게 되었습니다.

  1. MongoDB의 TTL기능 사용하기

    해당 공부용 프로젝트는 SQL DB와의 연결을 통한 스프링 서버를 생각하고 있었으므로 해당 방법은 프로젝트의 목적에 맞지않아 넘겼습니다. 추후 NoSql DB를 공부하게 된다면 해당 방법을 사용하는 것도 좋을 것 같습니다. 하지만 2번의 이유로 결국 기존의 방법을 사용할 것 같습니다.

  2. MySQL의 EVENT를 사용하기

    이를 사용한다면 꽤 간편하게 사용이 가능하지만 추후 30일이 아닌 10일마다 고치려면 직접 DB에 접속하여 고쳐야 합니다. 하지만 평소 AWS에 서버를 구축하면 Spring서버와 연결을 시키고 나머지 연결은 보안을 위해 전부 막아두어 이 요구사항이 바뀔때 다시 DB의 연결 설정 후 바꾸는 것은 유지보수에 몹시 안좋은 영향을 끼칠것으로 예상되어 보류하였습니다.

  3. AWS Lambda를 사용한 sql문 날리기

    AWS를 사용하는 중인 프로젝트라면 AWS Lambda를 통해 sql문을 직접 날려 처리했을 것 같습니다. Lambda는 특정 시간에 해당 코드를 실행시켜주는 기능이 있는데 해당 방법을 통해 매일 특정시간에 휴지통에 30일이 지난 데이터를 지우는 쿼리를 날리도록 만들면 됩니다. 하지만 클라우드 서버가 아닌 현재 저의 컴퓨터에서만 진행하는 온 프레미스 서버를 구상중이기에 제거하였습니다.

  4. Spring Schedular를 사용한 sql문 날리기

    Spring에는 이러한 기능이 없나 생각하여 찾아보니 Spring Schedular라는 매서드로 특정 시간에 작동을 시키는 방법이 존재했습니다. 적용도 간단하고 유지보수에도 용이해 해당 방법을 채택하게 되었습니다.

Spring Schedular란

Spring Framework에서 지원하는 스케줄링 서비스로 어노테이션을 활용하여 간단하게 사용할 수 있다.

cron 표현식을 활용거나 실행 딜레이를 주어 특정 주기로 메서드를 실행시켜주는 기능입니다.

Spring Schedular 사용 방법

  1. Application에 @EnableScheduling 어노테이션 추가

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @EnableScheduling
    @SpringBootApplication
    public class TodoListApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(TodoListApplication.class, args);
    	}
    
    }

    제일 기본이되는 Application 클래스에 @EnableScheduling이라는 어노테이션을 작성하면 해당 프로젝트에 Spring Schedular를 사용할 준비를 할 수 있다.

  2. Schedular를 적용한 Config를 작성

    import lombok.RequiredArgsConstructor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.annotation.Scheduled;
    import practice.project.todo_list.dao.TodoDao;
    
    import java.time.LocalDateTime;
    import java.util.concurrent.TimeUnit;
    
    @Configuration
    @RequiredArgsConstructor
    public class SchedulerConfig {
        private final TodoDao todoDao;
    
        @Scheduled(cron = "0 0 0 * * *")
        public void deleteAll() {
            todoDao.deleteByLocalDate(LocalDateTime.now());
        }
    
        @Scheduled(cron = "30 * * * * *")
        public void test() {
            System.out.println("LocalDateTime.now().toString() = " + LocalDateTime.now().toString());
        }
    
        @Scheduled(fixedDelay = 1000)
        public void test2() {
            System.out.println("1-No timeUnit");
        }
    
        @Scheduled(fixedDelay = 1, timeUnit = TimeUnit.SECONDS)
        public void test3() {
            System.out.println("1-second");
        }
    
        @Scheduled(fixedDelay = 1, timeUnit = TimeUnit.MINUTES)
        public void test4() {
            System.out.println("1-minutes");
        }
    
        @Scheduled(fixedDelay = 1, timeUnit = TimeUnit.SECONDS, initialDelay = 3)
        public void test5() {
            System.out.println("1-minutes, 3-delay");
        }
    }
    

    @Component라는 어노테이션을 사용해도 괜찮고 @Configuration을 사용하여도 상관 없습니다.

    하지만 공식문서에서는 Configuration을 사용하니 Configuration을 사용하도록 합시다.

    @RequiredArgsConstructor는 아래의 TodoDao를 받아오기 위해 사용되었습니다.

    @Scheduled 어노테이션 밑에 메서드를 작성하여 해당 메서드가 특정 시간 혹은 주기로 실행이 되게 만듭니다.

    위 메서드를 작성하고 실행을 시켜보면 아래와 같이 결과가 나오게됩니다.

    @Scheduled의 요소

    cron

    문자열로 작성되며 cron표현식에 맞는 시간에 실행됩니다.

    예시로는

    또한 자주 사용하는 것들은 매크로로 사용이 가능합니다.

    @Scheduled(cron = "@daily")
        public void deleteAll() {
            todoDao.deleteByLocalDate(LocalDateTime.now());
        }

zone을 사용하여 cron이 사용되는 시간대의 기준을 설정할 수 있습니다.
### fixedDelay / timeUnit

fixedDelay는 매 실행 주기를 넣을 수 있으며 Long타입으로 작성됩니다.

timeUnit은 TimeUnit클래스로 들어가며 default값은 TimeUnit.MILLISECONDS로 1ms가 가준입니다.

timeUnit으로 적용된 시간 기준으로 해당 delay가 적용됩니다.

fixedDelay만 1인 경우 1ms마다 실행

fixedDelay가 1이며 TimeUnit.SECONDS라면 1초마다 실행입니다.

fixedDelay의 경우 메서드의 실행이 끝난 후 해당 딜레이 시간만큼 기다린 후 실행합니다.
만약 30초마다 실행하고 싶다면 fixedDelay 대신 fixedRated를 사용하시면 됩니다.
### initialDelay

Long타입으로 작성되며 초기 실행 딜레이를 정하는 것입니다. TimeUnit의 영향을 받으며 initialDelay가 끝난 후 해당 주기로 실행되기 시작합니다.
profile
기본부터 정리해나가는 기록용 블로그

0개의 댓글