관리 메뉴

나만의공간

Spring Batch 강의 #6(배치란?) 본문

IT/Spring Batch

Spring Batch 강의 #6(배치란?)

밥알이 2023. 9. 25. 09:41

Spring Batch를 만들기전 Batch란 무엇이며, Spring Batch에서 사용하는 용어에 대한 정리를 하겠습니다.

Batch란?

배치는 어떤 업무에 대한 일괄 처리를 뜻합니다.
전날 신규 가입한 고객수를 알고자 하는 업무가 있다고 할때
필요할 때 마다 OLTP(RDS DB)를 매번 조회 한다고 하면 DB는 해당 트래픽을 감당하지 못할 수 도 있고, 의미 없는 네트워 비용, DB비용이 많이 들게 됩니다.
이럴때 전날 신규 가입한 고객에 대해서 따로 집계를 하는 어플리케이션(배치)가 있다고 하면 별도 집계는 필요없이 한번 집계된 데이타를 조회만 하면 되니 시스템 안정성/비용 등이 대폭 감소하게 됩니다.
이런한 업무를 처리하는 어플리케이션을 배치 어플리케이션 이라고 합니다.
배치 어플리케이션이 처리 하는 업무는 아래와 같은 업무를 처리 합니다.

  • 대용량 처리: 대량의 데이터를 조회하거나, 집계하는 역활을 해야 한다.
  • 자동화: 정해진 시간에 문제 없이 수행이 되어야 한다.
  • 신뢰성: 로깅,알림등으로 어플리케이션에 이슈가 있으면, 추적이 가능해야 한다.
  • 성능: 지정된 시간안에 원하는 업무를 처리 해야하고, 어플리케이션 배치간에 간섭이 없어야 한다.

Spring Batch 계층 구조도

스프링 배치 구조도는 크게 3가지로 되어 있습니다.

  • 배치 인프라 레이어
    • 어플리케이션과 배치코어는 배치 인프라 위에서 빌드 됩니다.
    • Job 실행과 흐름에 대한 틀을 제공합니다.
    • 일반적인 Reader / Writer / RetryTemplate과 같은 서비스를 포함 합니다.
  • 코어 레이어
    • 배치 작업을 시작/종료/제어 하는데 필요한 런타임 라이브러리를 제공합니다.
    • JobLauncher, Job, Step, Flow 등
  • 어플리케이션 레이어
    • 배치업무를 작성하는 레이어로 개발자가 만든 코드를 나타냅니다.

@EnableBatchProcessing

@EnableBatchProcessing 어노테이션을 선언하게 하면 해당 프로젝트는 Spring Batch를 수행하기 위한 기본 정보들을 자동으로 수행 하게 됩니다.

  • 총 4개의 설정정보를 실행시키며, 스프링 배치에 필요한 초기화 및 실행 구성이 실행 됩니다.
    • SimpleBatchConfiguration
      1. JobBuilderFactory 와  StepBuilderFactory생성
      2. 스프링 배치의 주요 구성 요소 생성(프록시 객체로 생성)
    • BatchConfigurerConfiguration
      1. BasicBatchConfigurer
        • SimpleBatchCOnfiguration에서 생성한 프록시 객체의 실제 대상 객체를 생성하는 설정 클래스
        • Bean 의존성 생성으로 주요 객체들을 참조해서 사용할 수 있다.
      2. JpaBatchConfigurer
        • BasicBatchConfigurer를 상속받아 JPA관련 객체를 생성/설정 클래스
      3. 위 두 클래스는 BatchConfigurer 인터페이스로 구현 되어 있음.
    • BatchAutoConfiguration
      1. 스프링 배치가 초기화 될때 자동으로 실행되는 설정 클래스
      2. Job을 수행하는 JobLuncherApplicationRunner 빈을 생성
      3. 스프링 부트가 자동으로 Job을 실행시키는 것과 관련된 작업을 진행

동작순서

 

Batch 기본용어

  • Job
    • 하나의 일을 의미
  • Step
    • 하나의 일(Job)안에서 단계를 의미
  • Tasklet
    • 하나의 단계(Step)안에서 실질적으로 수행하는 작업 의미

간단한 배치 어플리케이션

package com.study.springbatch.domain.job;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.StepContribution;
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.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
@RequiredArgsConstructor
public class SampleBatchJobConfig {

	// Job을 생성하는 빌더 팩토리로, Job을 생성할 때 new Job이 아니라 jobBuilderFactory을 사용해 쉽게 Job을 생성합니다.
	private final JobBuilderFactory jobBuilderFactory;
	// JobBuilderFactory와 같은 맥락입니다.
	private final StepBuilderFactory stepBuilderFactory;

	@Bean
	public Job helloJob(){
		return jobBuilderFactory.get("helloJob") // helloJob을 생성합니다.
			.start(helloStep1()) // Job의 첫번째 Step으로 helloStep1을 등록합니다.
			// .next(helloStep2()) // helloStep1을 수행한 이후 다음 Step을 등록합니다.
			.build();
	}

	@Bean
	public Step helloStep1() {
		return stepBuilderFactory.get("helloStep1") // helloStep1을 생성합니다.
			.tasklet(new Tasklet() { // Step의 작업 내용 Tasklet을 정의합니다.
				@Override
				public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
					System.out.println("hellStep1");
					// Step은 기본적으로 Tasklet을 무한 반복시킵니다.
					// 따라서 null이나 RepeatStatus.FINISHED를 반환해줘야 1번만 Tasklet을 실행합니다.
					return RepeatStatus.FINISHED;
				}
			})
			.build();
	}

	/**
	 * helloStep2를 Bean으로 등록하게 되면
	 * 오류가 발생하고 있음.
	 * // TODO: 2023/10/07 원인 찾아야 함. 
	 */
	// helloStep1과 같은 맥락입니다.
	// @Bean
	// public Step helloStep2() {
	// 	return stepBuilderFactory.get("helloStep2")
	// 		.tasklet(new Tasklet() {
	// 			@Override
	// 			public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
	// 				System.out.println("hellStep2");
	// 				return RepeatStatus.FINISHED;
	// 			}
	// 		})
	// 		.build();
	// }

}

 

Comments