[Spring-batch] 2분 Tutorial

오늘내일·2024년 6월 4일
0
post-custom-banner

나처럼 스프링 배치를 처음 접하는 사람에게 도움이 될 수 있기 위해 spring-batch github에서 제공하는 Two minutes tutorial을 따라하면서 정리해본다.

Two minute tutorial

1. 의존성 추가

일단 spring-batch 의존성을 추가해야 한다. 나는 gradle을 사용하기 때문에 아래와 spring-batch-core, hsql 의존성을 추가했다.

    implementation 'org.springframework.batch:spring-batch-core'
    runtimeOnly 'org.hsqldb:hsqldb'

💡 hsql은 실습 목적으로 내장 db를 사용하기 위해 추가한다.

2. DataSource, TransationManager 설정

  • datasource는 batch의 meta-data를 저장하기 위해서도 필요한데 위에 의존성을 추가한 hsql과 연결한다.
  • transactionManager는 말 그대로 transaction을 관리하기 위한 객체인데, spring-batch는 chunk 단위로 transaction을 관리한다.
@Configuration
public class DataSourceConfiguration {

  @Bean
  public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
        .addScript("/org/springframework/batch/core/schema-hsqldb.sql")
        .build();
  }

  @Bean
  public JdbcTransactionManager transactionManager(DataSource dataSource) {
    return new JdbcTransactionManager(dataSource);
  }

}
  • spring-batch-core에서 제공하는 schema-hsqldb.sql 파일을 보면 아래와 같은데, batch 작업을 실행할 경우 필요한 meta-data를 저장하기 위해 테이블을 생성한다. JobInstance, JobExecution, StepExecution 등 생소한 단어가 많은데 아래 블로그에 용어 정리를 잘 해주셔서 참고하면 좋을 듯 하다. 참고 : https://khj93.tistory.com/entry/Spring-Batch란-이해하고-사용하기
-- Autogenerated: do not edit this file

CREATE TABLE BATCH_JOB_INSTANCE  (
	JOB_INSTANCE_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
	VERSION BIGINT ,
	JOB_NAME VARCHAR(100) NOT NULL,
	JOB_KEY VARCHAR(32) NOT NULL,
	constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ;

CREATE TABLE BATCH_JOB_EXECUTION  (
	JOB_EXECUTION_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
	VERSION BIGINT  ,
	JOB_INSTANCE_ID BIGINT NOT NULL,
	CREATE_TIME TIMESTAMP(9) NOT NULL,
	START_TIME TIMESTAMP(9) DEFAULT NULL ,
	END_TIME TIMESTAMP(9) DEFAULT NULL ,
	STATUS VARCHAR(10) ,
	EXIT_CODE VARCHAR(2500) ,
	EXIT_MESSAGE VARCHAR(2500) ,
	LAST_UPDATED TIMESTAMP(9),
	constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
	references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;

CREATE TABLE BATCH_JOB_EXECUTION_PARAMS  (
	JOB_EXECUTION_ID BIGINT NOT NULL ,
	PARAMETER_NAME VARCHAR(100) NOT NULL ,
	PARAMETER_TYPE VARCHAR(100) NOT NULL ,
	PARAMETER_VALUE VARCHAR(2500) ,
	IDENTIFYING CHAR(1) NOT NULL ,
	constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
	references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

CREATE TABLE BATCH_STEP_EXECUTION  (
	STEP_EXECUTION_ID BIGINT IDENTITY NOT NULL PRIMARY KEY ,
	VERSION BIGINT NOT NULL,
	STEP_NAME VARCHAR(100) NOT NULL,
	JOB_EXECUTION_ID BIGINT NOT NULL,
	CREATE_TIME TIMESTAMP(9) NOT NULL ,
	START_TIME TIMESTAMP(9) DEFAULT NULL ,
	END_TIME TIMESTAMP(9) DEFAULT NULL ,
	STATUS VARCHAR(10) ,
	COMMIT_COUNT BIGINT ,
	READ_COUNT BIGINT ,
	FILTER_COUNT BIGINT ,
	WRITE_COUNT BIGINT ,
	READ_SKIP_COUNT BIGINT ,
	WRITE_SKIP_COUNT BIGINT ,
	PROCESS_SKIP_COUNT BIGINT ,
	ROLLBACK_COUNT BIGINT ,
	EXIT_CODE VARCHAR(2500) ,
	EXIT_MESSAGE VARCHAR(2500) ,
	LAST_UPDATED TIMESTAMP(9),
	constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
	references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT  (
	STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
	SHORT_CONTEXT VARCHAR(2500) NOT NULL,
	SERIALIZED_CONTEXT LONGVARCHAR ,
	constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
	references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
) ;

CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT  (
	JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
	SHORT_CONTEXT VARCHAR(2500) NOT NULL,
	SERIALIZED_CONTEXT LONGVARCHAR ,
	constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
	references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

CREATE TABLE BATCH_STEP_EXECUTION_SEQ (
	ID BIGINT IDENTITY
);
CREATE TABLE BATCH_JOB_EXECUTION_SEQ (
	ID BIGINT IDENTITY
);
CREATE TABLE BATCH_JOB_SEQ (
	ID BIGINT IDENTITY
);

💡chunk

batch 작업의 일부분으로, 데이터를 읽고(ItemReader), 처리하고(ItemProcessor), 기록하는(ItemWriter) 단위이다.

3. Spring-Batch 설정

  • spring-batch는 가장 크게는 Job을 하나의 단위로 실행하고, Job 내에는 여러 Step이 존재하고, Step 내에는 여러 chunk가 존재한다.
@Configuration
@EnableBatchProcessing
@Import(DataSourceConfiguration.class)  // 위에서 설정한 dataSource와 transactionManager를 불러온다. 
public class HelloWorldJobConfiguration {

	@Bean
	public Step step(JobRepository jobRepository, JdbcTransactionManager transactionManager) {
		return new StepBuilder("step", jobRepository).tasklet((contribution, chunkContext) -> {
			System.out.println("Hello world!");
			return RepeatStatus.FINISHED;
		}, transactionManager).build();
	}

	@Bean
	public Job job(JobRepository jobRepository, Step step) {
		return new JobBuilder("job", jobRepository).start(step).build();
	}

	public static void main(String[] args) throws Exception {
		ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldJobConfiguration.class);
		JobLauncher jobLauncher = context.getBean(JobLauncher.class);
		Job job = context.getBean(Job.class);
		jobLauncher.run(job, new JobParameters());
	}

}

코드를 살펴보자.

  • @EnableBatchProcessing
    • Spring-batch의 기본 설정을 활성화한다. 이 설정에는 batch 작업에 필요한 JobRepository, JobLauncher, JobRegistry, PlatformTransactionManager, JobBuilderFactory 및 StepBuilderFactory 등의 빈(bean) 정의가 포함된다.
  • Step 메서드
    • batch 작업의 meta-data를 저장할 jobRepository와 트랜잭션 관리를 위한 transactionManager를 파라미터로 입력받는다.
    • StepBuilder는 파라미터로 해당 step의 이름과 jobRepository를 입력한다.
    • tasklet 메서드
      • 단일 작업 단위를 수행하는데 사용된다.
      • 파라미터로 Tasklet 인터페이스와 transactionManager를 입력받는다.
      • Tasklet 인터페이스는 아래와 같이 구성되어 실행할 경우 StepContribution(현재 step의 실행 상태 데이터)와 ChunkContext(chunk 실행에 필요한 데이터) 객체를 파라미터로 입력받아, RepeatStatus(작업의 반복 필요 여부 데이터)를 반환한다.
        @FunctionalInterface
        public interface Tasklet {
        	@Nullable
        	RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception;
        
        }
  • Job 메서드
    • JobRepository와 위에서 구성한 Step을 파리미터로 입력받는다.
    • JobBuilder를 통해서 해당 job의 이름과 jobRepository를 입력한다.
    • start 메서드로 구성한 step을 실행시킨다.
  • main 실행 메서드
    • 위에서 설정한 정보들을 ApplicationContext에 반영하여 호출하고, JobLauncher를 통해 해당 Job을 실행시킨다. (JobParameters는 위에 참고 사이트를 참고하면 이해가 쉽다.)
profile
다시 시작합니다.
post-custom-banner

0개의 댓글