[Project] 프로젝트에 Spring Batch 적용하기 !

현주·2023년 6월 7일
0

📌 Spring Batch에 대한 자세한 개념들은 아래 포스팅을 참고해주세요.
<스프링 배치(Spring batch)란?>

1. build.gradle에 의존성 추가

  • Spring batch 사용을 위해
  • batch 작업 실행을 위한 scheduler 사용을 위해
    ( 이 프로젝트에서는 Quartz를 사용함 )

2. application.yml에 DB 스키마 생성 전략 설정

➜ DB 스키마 생성 SQL을 항상 실행
➜ RDBMS 설정이 되어 있을 경우, 내장 DB보다 우선적으로 실행됨


3. 애플리케이션 시작 클래스에 @EnableBatchProcessing, @EnableScheduling 애너테이션 붙이기


4. YataBatchConfig 클래스 작성
( 우리 프로젝트에서는 Yata라는 게시물의 마감 상태 변경을 위해 Spring Batch를 사용하기 때문에 YataBatchConfig를 작성하였다. )

@Configuration // Spring에 의해 구성 클래스로 인식
// Spring Batch의 모든 Job은 @Configuration으로 등록해서 사용해야 함
@Slf4j
@EnableBatchProcessing // Spring Batch 기능을 사용할 수 있도록 활성화
public class YataBatchConfig {
    public final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;
    private final JpaYataRepository yataRepository;
    private final JpaYataRequestRepository yataRequestRepository;

    public YataBatchConfig(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, JpaYataRepository yataRepository, JpaYataRequestRepository yataRequestRepository) {
        this.jobBuilderFactory = jobBuilderFactory;
        this.stepBuilderFactory = stepBuilderFactory;
        this.yataRepository = yataRepository;
        this.yataRequestRepository = yataRequestRepository;
    }

    @Bean
    public Job yataJob() {
        return jobBuilderFactory.get("yataJob")
                .start(yataStep()).next(yataRequestStep())
                .build();
    } ⠀
    ⠀
	@Bean
    public Step yataStep() {
        return stepBuilderFactory.get("yataStep")
                .tasklet((contribution, chunkContext) -> {
                    yataRepository.updateYataOverDepartureTime();
                    return RepeatStatus.FINISHED;
                })
                .build();
    }public Step yataRequestStep() {
        return stepBuilderFactory.get("yataRequestStep")
                .tasklet((contribution, chunkContext) -> {
                    yataRequestRepository.updateExpiredYataRequest();
                    return RepeatStatus.FINISHED;
                })
                .build();
    }
}

✔️ JobBuilderFactory / StepBuilderFactory

  • Spring Batch에서 제공하는 빌더 클래스
  • 각각 Job과 Step을 생성하는 데에 사용

✔️ yataJob()

  • 생성한 스텝들을 어떤 순서로 실행시킬지 묶어서 하나의 Job으로 만듦

✔️ yataStep()

  • tasklet 기반으로 StepBuilderFactory를 사용하여 스텝을 생성
  • yataRepository.updateYataOverDepartureTime(); 작업을 수행
  • tasklet의 execute 메서드로 RepeatStatus.FINISHED를 사용하여 종료

✔️ yataRequestStep()

  • tasklet 기반으로 StepBuilderFactory를 사용하여 스텝을 생성
  • yataRequestRepository.updateExpiredYataRequest(); 작업을 수행
  • tasklet의 execute 메서드로 RepeatStatus.FINISHED를 사용하여 종료

❗ 보통 Chunk 방식을 대다수 사용하지만,
우리 프로젝트에서는 비교적 간단한 Step들을 정의하고 있기 때문에 Tasklet 방식을 사용함 !


5. YataBatchScheduler 클래스 작성

@Component // 컴포넌트로 등록
@Slf4j
public class YataBatchScheduler {
    private final JobLauncher jobLauncher;
    private final YataBatchConfig yataBatchConfig;public YataBatchScheduler(JobLauncher jobLauncher, YataBatchConfig yataBatchConfig) {
        this.jobLauncher = jobLauncher;
        this.yataBatchConfig = yataBatchConfig;
    }// 10분 마다 실행
    //@Scheduled(cron = "0 0/10 * * * *")
    // 1분 마다 실행
    @Scheduled(fixedDelay = 1000 * 60 * 20) // 20분 마다 실행
    public void runExpiredYataBatch() {
        Map<String, JobParameter> jobParameter = new HashMap<>();
        jobParameter.put("yataJobExpire", new JobParameter(System.currentTimeMillis()));
        JobParameters jobParameters = new JobParameters(jobParameter);try {
            jobLauncher.run(yataBatchConfig.yataJob(), jobParameters);
            log.info("YataBatchScheduler runExpiredYataBatch");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("YataBatchScheduler Error :{}", e.getMessage());
        }
    }
}

✔️ @Scheduled(fixedDelay = 1000 * 60 * 20)

  • 작업이 실행될 시간의 단위를 정하는 애너테이션
  • 위는 해당 작업이 모두 끝난 후 20 후에 작업 다시 실행
  • fixedDelay = 해당 작업이 끝난 시점부터 시간을 셈
  • fixedRate = 해당 작업의 시작 시점부터 시간을 셈

    Ex. 만약 @Scheduled(fixedRate = 1000 * 60 * 20)라고 한다면,
    해당 작업이 시작한 시점부터 20분 후에 작업이 다시 실행되는 것

✔️ runExpiredYataBatch()

  • @Scheduled를 사용하여 스케줄링
  • 작업 실행 시간마다 새로운 JobParameters를 생성하여 파라미터로 전달하고,
    jobLauncher를 사용하여 잡 실행
  • 배치 작업이 정상적으로 실행되면 "YataBatchScheduler runExpiredYataBatch"라는 로그를 남기고, 예외가 발생한다면 해당 예외를 출력하고 에러 메시지를 로그에 남김

✔️ jobLauncher.run()

  • 해당 Job(yataBatchConfig의 yataJob())을 실행하고, 앞서 설정한 JobParameters를 전달

여기까지 우리 프로젝트에 적용하고 서버를 돌린 후에 postman으로 Test를 해보면,

콘솔창에서 아래와 같이 스케줄러가 정상적으로 작동되는 것을 알 수 있고 !

우리 프로젝트에서도 마감된 게시물을 자동으로 20분마다 한꺼번에 신청마감 상태로 처리하게 되는 것을 알 수 있다 !

0개의 댓글