본문 바로가기
  • 개발하는 곰돌이
Development/Spring & Spring Boot

[Spring Boot] Scheduler를 사용하여 정해진 시간마다 메소드 실행시키기

by 개발하는 곰돌이 2022. 12. 30.

목차

    기본 환경

    • IntelliJ Ultimate 2022.3
    • Spring Boot 2.7.6
    • Kotlin 1.7.21(JDK 11)
    • MySQL 8
    • Swagger 3.0.0
    • MyBaitis 2.3.0
    Spring Boot 프로젝트에 Swagger 3.0.0을 적용하는 방법, MyBatis 설정 방법은 아래 포스트를 참고하면 된다.

    [Spring Boot] Kotlin 기반 Spring Boot 프로젝트에 Swagger 3.0.0 적용하기

    [Oracle] Spring Boot 프로젝트에서 Mybatis 세팅하기 with Kotlin

    개요

    프로젝트를 진행하다보면 정해진 시간마다 특정 동작을 수행해야할 때가 있다. 이 때 Spring Boot에서 제공하는 Scheduler를 사용하면 손쉽게 정해진 시간에 특정 동작을 수행하게 할 수 있다. 본 포스트에서는 스케쥴러를 통해 매분마다 DB에 값을 추가하는 동작을 구현한다.

    Scheduler 활성화

    Scheduler는 기본적으로 Spring Boot에 포함되어 있기 때문에 추가적으로 Gradle에 의존성을 추가할 필요는 없고, Application 클래스에 @EnableScheduling를 추가하여 Scheduler를 활성화한다.

    // Java
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @EnableScheduling
    @SpringBootApplication
    public class SchedulerExampleApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SchedulerExampleApplication.class, args);
        }
    
    }
    // Kotlin
    import org.springframework.boot.autoconfigure.SpringBootApplication
    import org.springframework.boot.runApplication
    import org.springframework.scheduling.annotation.EnableScheduling
    
    @EnableScheduling
    @SpringBootApplication
    class SchedulerExampleApplication
    
    fun main(args: Array<String>) {
        runApplication<SchedulerExampleApplication>(*args)
    }

    Mapper 작성

    다음과 같이 Mapper를 작성한다.

    <!-- Mapper.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
    <mapper namespace="com.colabear754.scheduler_example.mappers.SchedulerMapper">
        <insert id="insertData">
            INSERT INTO scheduler_test
            VALUES (NOW(), '스케쥴러로 추가된 데이터입니다.')
        </insert>
    
        <select id="selectData" resultType="DataDTO">
            SELECT *
            FROM scheduler_test
            ORDER BY inserted_time DESC
        </select>
    </mapper>
    // Java
    import com.colabear754.scheduler_example.dto.DataDTO;
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    interface SchedulerMapper {
        public void insertData();
        public List<DataDTO> selectData();
    }
    // Kotlin
    import com.colabear754.scheduler_example.dto.DataDTO
    import org.apache.ibatis.annotations.Mapper
    
    @Mapper
    interface SchedulerMapper {
        fun insertData()
        fun selectData(): List<DataDTO?>
    }

    Controller 작성

    Scheduler를 사용하기 위해선 Controller 클래스에 @Component 어노테이션을 추가하고, 메소드에 @Scheduled 어노테이션을 추가한다. @Scheduled가 추가된 메소드는 파라미터와 반환값을 사용할 수 없다는 점에 주의해야 한다. @Scheduled의 속성에는 다음과 같은 것들이 있다.

    • fixedDelay : 메소드의 실행이 끝난 시간을 기준으로 하여, 설정된 밀리세컨드 간격마다 실행.
    • fixedRate : 메소드의 실행이 시작하는 시간을 기준으로 하여, 설정된 밀리세컨드 간격마다 실행. 이전 작업이 완료될 때까지 다음 작업은 실행되지 않음
    • initialDelay : 설정된 밀리세컨드 시간 후부터 fixedDelay 간격마다 실행.
    • cron : Cron 표현식을 사용하여 설정한 시간에 실행.
    Cron 표현식
    cron = "* * * * * *"와 같은 형태로 작성하여 첫번째값부터 초(0~59), 분(0~59), 시(0~23), 일(1~31), 월(1~12), 요일(0~6)을 나타낸다. Cron 표현식에 대한 정보는 다음 링크를 참조하길 바란다.
    •  zone : 타임존 설정. 미설정 시 로컬 시간대를 사용한다.

    본 예제에서는 분 단위로 실행시키기 위해 cron 속성을 설정했다.

    // Java
    import com.colabear754.scheduler_example.mappers.SchedulerMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class SchedulerController {
        @Autowired
        private SchedulerMapper schedulerMapper;
        
        @Scheduled(cron = "0 * * * * * *", zone = "Asia/Seoul")
        @GetMapping("/insert")
        public void scheduledInsert() {
            schedulerMapper.insertData();
        }
    
        @GetMapping("/select")
        public List<DataDTO> getData() {
            schedulerMapper.selectData();
        }
    }

     

    // Kotlin
    import com.colabear754.scheduler_example.mappers.SchedulerMapper
    import org.springframework.scheduling.annotation.Scheduled
    import org.springframework.stereotype.Component
    import org.springframework.web.bind.annotation.GetMapping
    import org.springframework.web.bind.annotation.RestController
    
    @RestController
    class SchedulerController(private val schedulerMapper: SchedulerMapper) {
    
        @Scheduled(cron = "0 * * * * * *", zone = "Asia/Seoul")
        @GetMapping("/insert")
        fun scheduledInsert() = schedulerMapper.insertData()
    
        @GetMapping("/select")
        fun getData() = schedulerMapper.selectData()
    }

    테스트 결과

    스웨거를 통해 select API를 실행해보면 정상적으로 1분 단위로 추가된 것을 볼 수 있다. 초 단위가 어긋난 것은 로컬과 DB 서버의 시간차이에 의한 것이다.

    Github

     

    https://github.com/Colabear754/scheduler_example

    댓글