[Spring] Spring Batch 5 With Kotlin

김효권·2023년 6월 4일
post-thumbnail

Spring Batch에 대한 내용은 아래 블로그를 참고하였습니다.

https://jojoldu.tistory.com/324

이번 포스트에는 Spring Batch 5와 Kotlin 기준으로 예제 코드를 중심으로 작성하였습니다.

프로젝트 생성

먼저 프로젝트는 다음과 같은 버전을 사용하고, Spring initializer를 사용해서 프로젝트를 생성하였다.

  • Spring boot 3.1
  • Spring batch 5

프로젝트를 생성하고 나서 build.gradle.kts 파일이 생성된다.

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.1.0"
    id("io.spring.dependency-management") version "1.1.0"
    kotlin("jvm") version "1.8.21"
    kotlin("plugin.spring") version "1.8.21"
    kotlin("plugin.jpa") version "1.8.21"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-batch")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("io.github.microutils:kotlin-logging:2.0.11") // 코틀린 로깅 라이브러리
    runtimeOnly("com.h2database:h2")
    runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.springframework.batch:spring-batch-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "17"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

간단한 Job 생성해보기

Spring Batch 5 이전 버전에는 다음과 같은 방법으로 JobBuilderFactory, StepBuilderFactory 를 의존주입 받아서 사용하는 방식으로 했으나, Spring Batch 5로 릴리즈 되면서 해당 방법은 Deprecated 되었다.

@Configuration
class JobConfiguration (
    val jobBuilderFactory: JobBuilderFactory,
    val stepBuilderFactory: StepBuilderFactory,
)

Spring Batch 5 부터는 JobRepository 를 명시적으로 선언해서 Job을 생성해야한다.

@SpringBootApplication
class SpringBatchWithKotlinApplication

fun main(args: Array<String>) {
    runApplication<SpringBatchWithKotlinApplication>(*args)
}

보통 Application.class에 배치 기능 활성화 하는 어노테이션인 @EnableBatchProcessing 를 선언하지만 Spring boot 3.x에서는 해당 어노테이션을 사용하지 않는다.
Spring boot 3.0의 릴리즈 노트를 보면 위와 같이 @EnableBatchProcessing 는 더 이상 사용되지 않는다. 라고 작성되어 있다. 기존에는 @EnableBatchProcessing 를 사용하면 배치관련 설정을 자동으로 해주지만, Spring Batch 5에서는 Datasoruce, TransactionManager와 같은 설정들을 명시적으로 하는 방법을 지향하는 것 같다.

private val log = KotlinLogging.logger {}

@Configuration
class JobConfiguration {

    @Bean
    fun job(jobRepository: JobRepository, 
		    transactionManager: PlatformTransactionManager
    ): Job {
        return JobBuilder("testJob", jobRepository)
            .start(step(jobRepository, transactionManager))
            .build()
    }

    @Bean
    fun step(
        jobRepository: JobRepository,
        platformTransactionManager: PlatformTransactionManager,
    ): Step {
        return StepBuilder("collectStep", jobRepository)
            .tasklet({_, _ ->
                log.info{ "hello, world" }
                RepeatStatus.FINISHED
            }, platformTransactionManager)
            .build()
    }

}

위와 같이 hello, world 로그를 출력하는 간단한 Job 만들어봤다. application run을 하면 다음과 같이 로그가 출력되는 것을 확인할 수 있다.
DataSource 관련해서 아무런 설정을 하지 않는 경우 자동으로 인메모리 DB인 H2를 사용하는 것을 확인할 수 있고, Job의 이름과 Job을 실행 시킬 때 사용한 파라미터를 확인할 수 있다.

mariaDB 환경에서 실습해보기

인메모리 DB인 H2 환경이 아닌 다른 DB에서 진행하기 위해서는 DataSource 셋팅이 필요하다. 설정하기 위한 방법은 아래와 같다.

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

위와 같이 DB 설정을 진행한다.

  1. @Bean 설정
@Configuration
class DataSourceConfig {

    @Bean
    fun dataSource(): DataSource {
        return DataSourceBuilder.create()
            .driverClassName("org.mariadb.jdbc.Driver")
            .url("jdbc:mariadb://localhost:3306/spring_batch_demo")
            .username("root")
            .password("1234")
            .build()
    }
}
  1. DefaultBatchConfiguration.class 메서드 재정의 하기
  @Configuration
  public class MyJobConfiguration extends DefaultBatchConfiguration {
 
      @Bean
      public Job job(JobRepository jobRepository) {
          return new JobBuilder("myJob", jobRepository)
                  // define job flow as needed
                  .build();
      }
 
  }

DefaultBatchConfiguration을 상속 받은 뒤 get 메서드를 재정의하여 배치 설정을 커스텀할 수 있는데, 위와 같은 방법은 아직 사용해보진 않았다.

MariaDB 설정을 하고 나서 다시 application run 을 하면 다음과 같은 에러가 발생할 것이다.

어떤 테이블이 존재하지 않는다는 에러가 발생하는데, Spring Batch 를 사용하기 위해서는 메타 데이터 테이블들이 필요하다. H2를 사용하는 경우에는 해당 테이블을 자동으로 생성해주지만, MariaDB나 다른 DB를 사용하는 경우에는 개발자가 직접 테이블을 생성해주어야 한다.

이미 Spring Batch에는 메타 데이터 테이블에 대한 스키마가 이미 존재하므로 아래와 같은 설정을 추가해주면 자동으로 테이블이 생성된다.

spring:
  batch:
    jdbc:
      initialize-schema: ALWAYS # 스키마 자동 생성

설정을 하고 난 뒤, 다시 실행 시키면 다음과 같은 테이블이 생성된다.
BATCH_JOB_INSTANCE테이블에서 Job 인스턴스가 하나 추가된 것을 확인할 수 있다.

BATCH_JOB_INSTANCE 는 잡이 실행될 때마다 추가되는 것이 아닌 Argument에 할당받은 고유한 JobParameter값에 따라 새로 생성된다.

따라서 JobParameter를 변경하지 않고 다시 Application run을 하게 되면 실행할 작업이 없다는 메세지가 출력된다. 다시 실행 시키기 위해 application을 실행 시킬 때 Argument를 넘겨서 Job을 실행시키면 새로운 JobInstance가 추가된다.

program argument 옵션으로 지정해주었다.
새로운 JobInstance가 추가되고, 해당 Job이 실행되었다.

0개의 댓글