[Spring Boot] Spring Batch (File)

개요

여기에서는 Spring Boot + Spring Batch + H2 DB를 사용하여 파일 시스템을 input/output으로 사용하는 특정 Batch 업무를 처리하는 방법을 보여준다.

개발환경은 다음과 같다:

● Spring Tool Suite 3 (Version: 3.9.11)

● Spring Boot Version : 2.7.11

● Java : JDK 8


※ 관련글 목록: http://yellow.kr/lifeView.jsp?s=spring



예제 애플리케이션 설명

회사 고객의 CSS Score(신용 점수)가 있는 css-input.sam을 읽고, 그 Score에 해당하는 Grade(신용 등급)를 구한 다음 이를 css-output.sam에 저장한다.


예제로 사용된 css-input.sam과 Batch 실행 결과 만들어지는 css-output.sam은 다음과 같다.

● css-input.sam (작업년월,고객번호,신용점수)

202305,10001,987
202305,10002,452
202305,10003,880
202305,10004,766
202305,10005,658
202305,10006,901
202305,10007,745
202305,10008,888
202305,10009,542
202305,10010,697


● css-output.sam (작업년월,고객번호,신용등급)

202305,10001,1
202305,10002,8
202305,10003,3
202305,10004,5
202305,10005,6
202305,10006,3
202305,10007,5
202305,10008,3
202305,10009,7
202305,10010,6



Spring Boot project 생성

● eclips에서 Spring Boot project를 생성한다.

File > New > Project… > Spring Boot > Spring Starter Project

Name, Group, Package에 적당한 내용을 입력하고 [Next] 클릭


● 필요한 Dependency들을 선택한다.

Spring Batch, H2 Database를 선택한다.

[Finish] 클릭


yellow-springbatch 라는 이름으로 Project가 생성되었고, YellowSpringbatchApplication.java 가 생성되었다.

package com.yellow.springbatch;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class YellowSpringbatchApplication {

	public static void main(String[] args) {
		SpringApplication.run(YellowSpringbatchApplication.class, args);
	}

}

예제 애플리케이션이 완성되면 Project Structure은 다음과 같다.



Maven Dependencies

pom.xml을 보면 다음과 같은 dependency를 확인할 수 있다.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-batch</artifactId>
</dependency>

<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
	<scope>runtime</scope>
</dependency>



Spring Batch

Spring Batch는 대용량 데이터 처리를 지원하기 위한 오픈 소스 프레임워크이다. 스프링 프레임워크를 기반으로 하며, 대량의 데이터를 스케줄링하고 처리하기 위한 다양한 기능을 제공한다.

Spring Batch를 사용하면 다음과 같은 기능을 지원한다.

1. 대용량 데이터 처리

  • 대용량 데이터를 처리하기 위한 기능을 제공한다.
  • 대용량 데이터 처리를 위한 성능 최적화 기능을 제공한다.
  • 대용량 데이터 처리에서 발생할 수 있는 장애 상황에 대한 대처 방안을 제공한다.

2. Job 스케줄링

  • 스케줄링 기능을 제공하여 특정 시간에 Job을 실행할 수 있다.
  • Job의 실행 흐름 제어를 제공하여 여러 단계로 이루어진 Job의 실행 순서를 제어할 수 있다.
  • Job의 실행 상태를 모니터링할 수 있는 기능을 제공한다.

3. 재시도 및 재시작 기능

Job의 실행 중 실패하면 재시도 및 재시작을 할 수 있는 기능을 제공한다.

실패 시 다양한 원인에 대한 대응 방안을 제공한다.

4. 트랜잭션 관리

스프링 프레임워크의 트랜잭션 관리 기능을 활용하여 안정적인 데이터 처리를 보장한다.

5. 병렬 처리

대용량 데이터 처리를 위한 분산 처리 기능을 제공하여 빠른 처리 속도를 보장한다.

6. 에러 처리

발생 가능한 예외 상황에 대한 처리 방안을 제공한다.

실패한 작업을 복구하기 위한 기능을 제공한다.


Spring Batch는 이러한 다양한 기능을 제공하므로 대용량 데이터 처리를 위한 시스템 개발에 매우 유용하다. Spring Batch는 Spring Boot와 함께 사용하기 쉽게 설계되어 있어서, Spring Boot 기반의 대용량 데이터 처리 시스템을 쉽게 개발할 수 있다.



H2 DB

Spring Batch는 Job 실행 시의 상태 정보를 저장하기 위한 Batch 메타 데이터 테이블을 생성한다. 예를 들어, Job 실행 횟수, Step 실행 횟수, Job 파라미터 정보, 실행 시간 등의 정보를 저장한다. 이러한 정보는 다음과 같은 상황에서 사용될 수 있다.

  • Job 재시작 시 이전 실행 정보를 활용하여 이전 실행 상태로 복원
  • Job의 장애 발생 시 이전 실행 상태를 확인하고 문제를 진단
  • Job 실행 통계 정보 등의 운영 관리를 위한 목적으로 사용

따라서, Spring Batch에서는 이러한 Batch 메타 데이터를 저장하기 위해서 DB DataSource 설정이 필요하다.

여기에서는 H2 DB를 사용한다. Spring Boot에서 인메모리 H2 DB를 사용할 경우 application.properties 파일에 별도의 설정이 필요하지 않다. (HSQLDB, Derby도 마찬가지)

Spring Boot의 의존성 관리 기능을 이용하여 다음과 같이 HSQLDB 라이브러리를 프로젝트에 추가한다.

<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
	<scope>runtime</scope>
</dependency>



Spring Batch and Job Config

● BatchAppConfig.java

package com.yellow.springbatch;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;

@Configuration
@EnableBatchProcessing
public class BatchAppConfig {
	
	@Autowired public JobBuilderFactory jobBuilderFactory;
	@Autowired public StepBuilderFactory stepBuilderFactory;
	
	@Bean
	public Job monthlyCssJob() {
		Job cssJob = jobBuilderFactory
				.get("CssJob")
				.start(step())
				.build();
		return cssJob;
	}
	
	@Bean
	public Step step() {
		return stepBuilderFactory
				.get("step")
				.<CssInput, CssOutput> chunk(4)
				.reader(reader())
				.processor(processor())
				.writer(writer())
				.build();
	}
	
	@Bean
	public FlatFileItemReader<CssInput> reader() {
		return new FlatFileItemReaderBuilder<CssInput>()
				.name("cssItemReader")
				.resource(new FileSystemResource("C:/app/datafile/css-input.sam"))
				.delimited()
				.delimiter(",")
				.names(new String[] {"workYm","custNo","cssScore"})
				.targetType(CssInput.class)
				.build();
	}
	
	@Bean
	public CssItemProcessor processor() {
		return new CssItemProcessor();
	}
	
	@Bean
	public FlatFileItemWriter<CssOutput> writer() {
		return new FlatFileItemWriterBuilder<CssOutput>()
				.name("cssItemWriter")
				.encoding("UTF-8")
				.resource(new FileSystemResource("C:/app/datafile/css-output.sam"))
				.delimited()
				.delimiter(",")
	            .names(new String[]{"workYm", "custNo", "cssGrade"})
				.build();
	}

}

– Spring Batch에서 Chunk는 하나의 트랜잭션 단위로 처리되는 데이터 덩어리를 의미한다. Chunk 크기는 한 번에 처리할 데이터의 레코드 수를 결정하는 요소이다. 즉, Chunk 크기를 설정함으로써 한 번에 처리되는 데이터 양을 조절할 수 있다.

Chunk 크기는 상황에 따라 조정할 수 있다. 작업의 성격, 데이터의 양과 특성, 성능 등을 고려하여 적절한 Chunk 크기를 설정해야한다. Chunk 크기가 너무 작으면 트랜잭션 오버헤드가 증가할 수 있고, 너무 크면 메모리 부담이 커질 수 있으므로 적절한 크기를 찾는 것이 중요하다.


● CssInput.java

package com.yellow.springbatch;

public class CssInput {
	
	private String workYm;
	private String custNo;
	private long cssScore;
	
	public String getWorkYm() {
		return workYm;
	}
	public void setWorkYm(String workYm) {
		this.workYm = workYm;
	}
	public String getCustNo() {
		return custNo;
	}
	public void setCustNo(String custNo) {
		this.custNo = custNo;
	}
	public long getCssScore() {
		return cssScore;
	}
	public void setCssScore(long cssScore) {
		this.cssScore = cssScore;
	}
	
	@Override
	public String toString() {
		return "workYm:" + workYm + ",custNo:" + custNo + ",cssScore:" + cssScore;
	}
}


● CssOutput.java

package com.yellow.springbatch;

public class CssOutput {
	
	private String workYm;
	private String custNo;
	private long cssGrade;
	
	public CssOutput(String workYm, String custNo, long cssGrade) {
		this.setWorkYm(workYm);
		this.setCustNo(custNo);
		this.setCssGrade(cssGrade);
	}
	
	public String getWorkYm() {
		return workYm;
	}
	public void setWorkYm(String workYm) {
		this.workYm = workYm;
	}
	public String getCustNo() {
		return custNo;
	}
	public void setCustNo(String custNo) {
		this.custNo = custNo;
	}
	public long getCssGrade() {
		return cssGrade;
	}
	public void setCssGrade(long cssGrade) {
		this.cssGrade = cssGrade;
	}
	
	@Override
	public String toString() {
		return "workYm:" + workYm + ",custNo:" + custNo + ",cssGrade:" + cssGrade;
	}

}


● CssItemProcessor.java

package com.yellow.springbatch;

import org.springframework.batch.item.ItemProcessor;

public class CssItemProcessor implements ItemProcessor<CssInput,CssOutput> {
	
	@Override
	public CssOutput process(final CssInput cssInput) {
		
		final String workYm = cssInput.getWorkYm();
		final String custNo = cssInput.getCustNo();
		final long cssScore = cssInput.getCssScore();
		long cssGrade;
		
		if (cssScore >= 950) {
			cssGrade = 1;
		} else if (cssScore >= 950) {
			cssGrade = 2;
		} else if (cssScore >= 880) {
			cssGrade = 3;
		} else if (cssScore >= 800) {
			cssGrade = 4;
		} else if (cssScore >= 700) {
			cssGrade = 5;
		} else if (cssScore >= 600) {
			cssGrade = 6;
		} else if (cssScore >= 500) {
			cssGrade = 7;
		} else if (cssScore >= 400) {
			cssGrade = 8;
		} else {
			cssGrade = 9;
		}
		
		final CssOutput cssOutput = new CssOutput(workYm,custNo,cssGrade);
		
		return cssOutput;
	}

}



Application 실행

Project를 선택한 후, Run AS > Spring Boot App 를 하면 Batch 프로그램이 정상적으로 수행된다.​​ C:\app\datafile\css-output.sam 이 정상적으로 만들어졌는지 확인한다.


[Spring Boot] Spring Batch (File)
Tagged on:             

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.