본문 바로가기
Spring/Batch

[Spring] Spring Batch 시작하기 01

by 기몬식 2024. 1. 14.

Spring Batch 를 학습하기 위한 시리즈 글로 Spring Batch 5.1.0 버전을 기반으로 작성합니다.

프로젝트 환경

Spring Batch 를 실습하기 위해 먼저 프로젝트부터 생성하겠습니다. 다음과 같은 버전으로 프로젝트를 구성했습니다.
 

  • Gradle(8.2.1)
  • Spring Boot(3.2.1)
  • Java(17)
  • MySql(8.0.23)

또한 실습에 필요한 의존성은 다음과 같습니다.
 

  • Spring-Data-JPA(3.2.1)
  • Spring-Batch(5.1.0)
  • Lombok(1.18.30)
  • MySql-Connector(8.1.0)

 

프로젝트 생성 시 Spring Initializr 를 통해 필요한 의존성을 선택하여 생성하면 build.gralde 파일은 다음과 같습니다.

 

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.1'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'io.ones1kk'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-batch'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.mysql:mysql-connector-j'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.batch:spring-batch-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

데이터베이스 설정

데이터 베이스는 In-memory DB 로 유명한 H2 로 설정하는 방법도 있으나 저는 이미 로컬에 Docker 로 구성된 MySql 환경이 있어 이를 그대로 사용하겠습니다. 또한 해당 글은 Sprig Batch 에 대한 글이니 설정하는 방식에 대한 자세한 설명은 생략하고 구성된 파일과 명령어로 대체하겠습니다.

1. Docker 및 Docker Compose 설치

brew update

brew install cask docker

brew install cask docker-compose

 

docker -v
Docker version 20.10.23, build 7155243

 

docker-compose -v
Docker Compose version v2.15.1

2. docker-compose.yml 작성

 

version: '3'
services:
  local_db_root:
    platform: linux/x86_64
    image: library/mysql:8.0.23
    container_name: mysql-8.0.23
    restart: always
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      TZ: Asia/Seoul
    volumes:
      - ./db/mysql/data:/var/lib/mysql

 
MySql 버전과 ports, volumes, platform... 과 같은 속성들은 개인의 환경에 맞춰 알맞게 설정하기 바랍니다.

3. DB 접속 및 생성

CLI 또는 Database IDE 를 사용하여 정상적으로 데이터베이스가 생성되었는지 확인합니다.
저는 IDE를 사용하여 아래와 같이 정상적으로 생성되었음을 확인했습니다.
 

 
그 후 root 계정으로 접속하여 새로운 데이터베이스와 유저를 생성합니다.
 

# 데이터 베이스 'batch_db' 생성
CREATE DATABASE batch_db CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ;

# 유저 생성
CREATE USER 'admin'@'%' IDENTIFIED BY 'admin' PASSWORD EXPIRE NEVER;

# 권한 부여 
GRANT ALL PRIVILEGES ON batch_db.* TO 'admin'@'%';

# flush
FLUSH PRIVILEGES;

4. 애플리케이션 설정

위에서 생성된 데이터베이스 정보를 기반으로 application.yml을 다음과 작성할 수 있습니다.

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:13306/batch_db
    username: admin
    password: admin
    type: com.mysql.cj.jdbc.MysqlDataSource

  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate.format_sql: true
      dialect: org.hibernate.dialect.MySQL8Dialect

 

또한 기본적인 JPA 에 대한 설정도 작성했습니다. ddl-auto 는 변경된 부분만 반영되는 update 전략으로 설정했습니다. 실제 실행되는 query 를 식별하고 포맷된 로깅을 위해 show-sql, hibernate.format_sql를 true로 설정했습니다. 마지막으로 dialect 은 데이터베이스와 버전에 알맞은 MySQL8Dialect 을 설정했습니다.

메타 데이터 테이블

이제 프로젝트 환경 구성이 완료되었습니다.
 

// 5.0.0 버전부터는 @EnableBatchProcessing 어노테이션은 더 이상 필요하지 않습니다. 
@SpringBootApplication
public class SpringBatchApplication {

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

}

 
하지만 애플리케이션을 실행하기 이전에 한가지 더 선행되어야 할 것이 있습니다. 그것은 바로 메타 데이터 테이블들을 생성해야 합니다. Spring Batch는 배치 작업을 위해 메타 데이터들을 통해서 배치 작업의 상태를 추적하고 관리합니다.
 

다음은 주요 메타 테이블에 대한 설명입니다.
 

  • BATCH_JOB_INSTANCE: 배치 작업은 Job 이 실행될 때마다 새로운 인스턴스가 생성됩니다. 해당 Job 인스턴스를 저장하기 위한 테이블입니다.
  • BATCH_JOB_EXECUTION: Job 인스턴스에 대한 실행 정보를 저장합니다. 작업이 성공적으로 완료되었는지 또는 실패했는지와 같은 정보가 포함됩니다.
  • BATCH_STEP_EXECUTION: 각 배치 Step 의 실행 정보를 저장합니다. 하나 이상의 테스크를 수행한 Step 의 실행 정보가 저정됩니다.
  • BATCH_JOB_EXECUTION_PARAMS: 배치 작업 실행에 전달된 매개변수를 저장합니다. 배치 작업이 실행될 때 전달된 매개변수가 여기에 저장됩니다.
  • BATCH_JOB_SEQ: 배치 작업 인스턴스 및 실행 정보에 대한 고유 식별자를 생성하는 데 사용됩니다.

 

이런 메타 테이블을 H2 DB를 제외한 다른 벤더사의 DB는 개발자가 직접 생성해야합니다. 아래와 같이 사용하는 IDE 에서 파일 검색을 진행하면 각 데이터베이스와 용도에 알맞은 .sql 파일을 찾을 수 있습니다.

알맞은 .sql 파일을 찾아서 파일 내부에 있는 Query 문을 실행시키면 총 9개의 메타 테이블 생성됩니다.

Job 생성

Spring Batch 가 v5.1.0 으로 버전이 올라가면서 새롭게 추가된 내용들이 있습니다. 변경된 내용을 간략하게 소개하겠습니다.

다양한 JobParameter Type

4 버전까지는 4개의 Type(Long, Double, String, Date)만을 지원했지만 5 버전부터는 다양한 타입을 지원합니다.

public class JobParameter<T> implements Serializable {

    private final T value;

    private final Class<T> type;
    ...
}

JobParameter 클래스에 타입 파라미터를 통해 다양한 타입을 JobParameter 로 사용 가능해졌습니다. 따라서 기본적이 표기법이 아래와 같이 변경되었습니다.

  • 기본 표기법: parameterName=parameterValue,parameterType,identificationFlag
  • 확장 표기법: parameterName='{"value": "parameterValue", "type":"parameterType", "identifying": "booleanValue"}'

명시적 자동 설정

JobBuilderFactory, StepBuilderFactory 가 deprecated 됐습니다. 그 이유는 숨겨진 자동 설정과 관련된 내용입니다.
 

@Deprecated(since = "5.0.0", forRemoval = true)
public class JobBuilderFactory {
  ...

  public JobBuilder get(String name) {
    return new JobBuilder(name, this.jobRepository);
  }
}

 

@Deprecated(since = "5.0.0", forRemoval = true)
public class StepBuilderFactory {
  ...

  public StepBuilder get(String name) {
    return new StepBuilder(name, this.jobRepository);
  }
}

 
위 두 메소드는 각각의 Factory 클래스에서 Job 과 Step 을 생성하는 메소드입니다. 두 개의 Builder 를 생성하기 위해서는 JobRepository 를 필요로 하는데 이는 해당 메소드를 사용하는 개발자가 문서를 읽지 않는한 인지하기 어렵다는 이유에서 입니다. 즉 JobRepository 에 대한 의존성을 숨기고 있기 때문에 이를 명시적으로 선언하여 사용하는 것을 권고한 것입니다.
 

변경된 내용과 v4.x.x -> v5.1.0 마이그레이션에 대한 자세한 내용은 해당 링크해당 링크를 참고하시면 됩니다.

 
이제 그디어 배치 애플리케이션 실행을 위한 코드를 작성할 수 있습니다.
 

@Slf4j
@Configuration
public class TestJobConfiguration {

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

  @Bean
  public Step step(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
      return new StepBuilder("step1", jobRepository)
              .tasklet(tasklet(), transactionManager)
              .build();
  }

  public Tasklet tasklet() {
      return (contribution, chunkContext) -> {
          log.info(">>> execute tasklet");
          return RepeatStatus.FINISHED;
      };
  }

}

 

위의 코드는 Job 을 실행시키기 위한 기본적인 코드입니다. 모든 Job 과 Step은 Bean 으로서 관리되기 때문에 @Configuration 을 선언한 설정 파일에서 Bean 으로 선언합니다. Job 이란 하나의 배치 작업 단위를 나타내는 용어로 단순한 Step 인스턴스의 컨테이너 개념으로 여러 개의 Step 으로 구성될 수 있습니다.

 

다음으로 myJob 을 구성하는 step 을 살펴 보도록 하겠습니다.

출처
Step 은 Job 의 각 실행 단위를 나타냅니다. 일반적으로 하나의 Step 은 특정한 처리를 담당하며 특정한 비즈니스 로직을 담당하여 구성되며 이런 Step 들을 조합하여 사용합니다. 이 중에서 Step 은 두가지 방식으로 구성이 될 수 있는데 하나의 Tasklet과 ItemReader & ItemProcessor & ItemWriter 한 묶음으로 구성될 수 있습니다.
 
여기서 Tasklet 이란 간단한 작업을 수행하는 데 사용되는 사용자 정의의 비즈니스 로직을 작성하는 한 덩어리의 Step 의 구성 요소로 이해하면 됩니다. 예제를 단순화하기 위해 Tasklet 을 사용하여 작성했습니다.

실행

이제 작성된 코드들을 기반으로 애플리케이션을 실행합니다.

COMPLETED 상태로 Job이 종료되었다고 로그가 찍힙니다.
 

select * from batch_job_instance;

 

Job Instance 도 잘 생성되었습니다.
 

select job_execution_id, job_instance_id, status, exit_code, start_time, end_time from batch_job_execution;

 

마지막으로 Job Execution 도 COMPLETED 상태로 종료된 것을 확인할 수 있습니다.
 
이것으로 간단하게 Spring Batch 애플리케이션 프로젝트 생성부터 환경 설정 그리고 예제 Job 까지 생성하여 실행까지 시켜보았습니다. 위와 같이 구성한 프로젝트를 기반으로 Spring Batch 의 다양한 기능을 실습하고 공부해보도록 하겠습니다.
 
작성한 코드는 Github 에서 확인할 수 있습니다.
 
오탈자 및 오류 내용을 댓글 또는 메일로 알려주시면, 검토 후 조치하겠습니다.

'Spring > Batch' 카테고리의 다른 글

[Spring] Spring Batch Job 등록부터 실행까지(1)  (1) 2024.01.22
[Spring] Spring Batch란?  (2) 2023.12.18