Spring

Spring batch + 스케쥴러 사용 예제

Clearing 2022. 12. 6. 19:58
728x90

출처) https://jojoldu.tistory.com/324?category=902551 

 

1. Spring Batch 가이드 - 배치 어플리케이션이란?

Spring Batch In Action이 2011년 이후 개정판이 나오지도 않고 (2019.03 기준), 한글 번역판도 없고, 국내 Spring Batch 글 대부분이 튜토리얼이거나 공식 문서 중 일부분을 짧게 번역한 내용들이라 대용량 시

jojoldu.tistory.com

 

배치란 일괄처리라는 의미를 가지고 있으며 다음의 조건을 만족해야만 한다.

 

1) 대용량 데이터 - 배치 어플리케이션은 대량의 데이터를 가져오거나, 전달, 계산하는 등의 처리를 할 수 ​​있어야 한다.

2) 자동화 - 배치 어플리케이션은 심각한 문제 해결을 제외하고는 사용자 개입 없이 실행되어야 한다.

3) 견고성 - 배치 어플리케이션은 잘못된 데이터를 충돌/중단 없이 처리할 수 있어야 한다.

4) 신뢰성 - 배치 어플리케이션은 무엇이 잘못되었는지를 추적할 수 있어야 한다. (로깅, 알림)

5) 성능 - 배치 어플리케이션은 지정한 시간 안에 처리를 완료하거나 동시에 실행되는 다른 어플리케이션을 방해하지

              않도록 수행되어야 한다.

 

Job

 -> 배치 처리 과정을 하나의 단위로 만들어 표현한 객체이고 여러 Step 인스턴스를 포함하는 컨테이너

Step

 -> 실질적인 배치 처리를 저의 하고 제어하는데 필요한 모든 정보가 있는 도메인 객체

Tasklet

 -> Step안에서 수행될 비즈니스 로직 전략의 인터페이스

 

jobInstance

-> job의 실행 단위이며, job 실행 시 하나의 instance가 생성
    실패하여 재 실행할 경우 해당 instance에 관련된 데이터만 처리

jobParameters

-> jobInstance에 전달되는 매개변수로 jobInstance를 구분하는 객체로 사용

JobLauncher

-> job과 jobParameters를 사용하여 job을 실행하는 객체

Execution

-> jopExecution, stepExecution이 있으며 실행 시도에 대한 객체를 나타내며
    상태,시작시간, 종료시간, 생성시간 등의 정보를 담고 있다.

 

Quartz는 스케줄러의 역할이지, Batch와 같이 대용량 데이터 배치 처리에 대한 기능을 지원하지 않는다.
반대로 Batch 역시 Quartz의 다양한 스케줄 기능을 지원하지 않아서 보통은 Quartz + Batch를 조합해서 사용한다.
정해진 스케줄마다 Quartz가 Spring Batch를 실행하는 구조라고 볼 수 있다.

 

build.gradle에 dependency 추가

dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
   implementation 'org.springframework.boot:spring-boot-starter-batch'
   implementation 'org.springframework.boot:spring-boot-starter-quartz'
   compileOnly 'org.projectlombok:lombok'
   runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
   annotationProcessor 'org.projectlombok:lombok'

   testImplementation 'org.springframework.boot:spring-boot-starter-test'
   testImplementation 'org.springframework.batch:spring-batch-test'

   annotationProcessor 'org.projectlombok:lombok'
   testAnnotationProcessor 'org.projectlombok:lombok'
}

 

resources 폴더 하위 application.yml에 설정

spring:
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://localhost:3306/test
    username: root
    password: 1234

  batch:
    jdbc:
      initialize-schema: "always"

      batch.job.enabled: false # CommandLineRunner 설정 해제 // 스케줄러를 사용하기 떄문에 구동시 동작 해제

  jpa:
    hibernate:
      ddl-auto: create

 

Job과 Step을 구성하는 Config

package com.example.batch.jobs;

...

@Configuration
@RequiredArgsConstructor
@Transactional
public class TutorialConfig {

    @Autowired
    @Qualifier("JpaUserRepository")
    UserRepository userRepository;

    private final JobBuilderFactory jobBuilderFactory; // Job 빌더 생성용
    private final StepBuilderFactory stepBuilderFactory; // Step 빌더 생성용

    // JobBuilderFactory를 통해서 tutorialJob을 생성
    @Bean
    public Job tutorialJob() {
        return jobBuilderFactory.get("tutorialJob")
                .start(tutorialStep())  // Step 설정
                .build();
    }

    // StepBuilderFactory를 통해서 tutorialStep을 생성
    @Bean
    public Step tutorialStep() {

        return stepBuilderFactory.get("tutorialStep")
                .tasklet(new TutorialTasklet(userRepository)) // Tasklet 설정
                .build();
    }
}

tasklet으로 step을 구성 -> 구성된 step으로 job을 구성

@RequiredArgsConstructor 어노테이션에 의해 생성자 주입

 

로직을 실행하는 Tasklet

package com.example.batch.tasklets;

...

@Slf4j
@RequiredArgsConstructor
public class TutorialTasklet implements Tasklet {


    final UserRepository userRepository;

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        log.info("executed tasklet !!");

        insertUser();

        return RepeatStatus.FINISHED;
    }

    public void insertUser(){
        UserEntity user = new UserEntity();
        user.setPw("1234");
        user.setName("1111");

        System.out.println(user);
        System.out.println(userRepository);

        userRepository.save(user);
    }
}

 

위에서 구성한 Batch를 실행하는 스케쥴러

package com.example.batch.schedulers;

...

import java.time.LocalDateTime;

@Component
@RequiredArgsConstructor
public class TutorialScheduler {

    private final Job job;  // tutorialJob
    private final JobLauncher jobLauncher;

    // 5초마다 실행
    @Scheduled(fixedDelay = 5 * 1000L)
    public void executeJob () {
        try {
            jobLauncher.run(
                    job,
                    new JobParametersBuilder()
                            .addString("datetime", LocalDateTime.now().toString())
                            .toJobParameters()  // job parameter 설정
            );
        } catch (JobExecutionException ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace();
        }
    }

}
728x90

'Spring' 카테고리의 다른 글

Spring Scheduler 정리 (Spring Scheduler, Quartz)  (0) 2023.02.13
스프링 부트 - JPA 연동  (0) 2022.12.05
스프링 부트 - MyBatis 연동  (0) 2022.12.04
스프링 부트 - Validator 검증  (0) 2022.10.26
스프링 부트 - 의존 주입  (0) 2022.10.25