Spring Batch 입문 5편 — Batch Infrastructure (@EnableBatchProcessing · Beans)

2026-05-17Spring Batch 입문에서 운영까지

Spring Batch 입문 5편. Batch Infrastructure 설정 — @EnableBatchProcessing 의 모든 것, JobRepository·JobOperator·TransactionManager 자동 생성, ResourcelessJobRepository (v6 신규), DefaultBatchConfiguration·JdbcDefaultBatchConfiguration·MongoDefaultBatchConfiguration 비교까지 풀어쓴 학습 노트.

📚 Spring Batch 입문에서 운영까지 · 5편 — Batch Infrastructure (@EnableBatchProcessing · Beans)

이 글은 Spring Batch 입문에서 운영까지 시리즈 48편 중 5편이에요. 4편 까지 Part 1 입문 을 끝냈다면, 이번 5편부터 Part 2 — Job 설정·실행 (6편) 으로 들어가요. 첫 글은 모든 Job 의 기반Batch Infrastructure (배치 실행을 떠받치는 하부 구조).

Batch Infrastructure가 어렵게 느껴지는 이유

Spring Batch 가 자동으로 만들어주는 bean 들이 어떤 게 만들어지는지·어떻게 customize 하는지 가 모호하다는 것.

첫째, @EnableBatchProcessing(배치 자동 구성 활성 어노테이션)의 의미. 어노테이션 한 줄이 수많은 bean 을 자동으로 만들어내는데, 정확히 어떤 bean 이고 default 값은 무엇인지가 잘 안 보여요.

둘째, v6 의 ResourcelessJobRepository(DB 없이 메모리만 쓰는 JobRepository). 학습·테스트엔 편한데, 언제 쓰고 언제 안 쓰는지가 헷갈려요.

셋째, DefaultBatchConfiguration vs annotation. 두 방식이 같은 결과를 내는데, 그럼 언제 어느 쪽을 골라야 하는지.

이 글에서 infrastructure bean 6가지 + 3가지 설정 방식 + 운영 권장까지.

Infrastructure Beans 6가지

Spring Batch 가 만드는 핵심 bean:

1. JobRepository

public interface JobRepository {
    void add(JobExecution jobExecution);
    void update(JobExecution jobExecution);
    JobExecution createJobExecution(Job job, JobParameters parameters);
    // ...
}

JobRepository(Job/Step 실행 상태를 저장하는 저장소)는 모든 Job/Step 실행 상태를 영속 저장해요. 7편에서 깊이 다뤄요.

2. JobOperator

public interface JobOperator {
    Long start(Job job, JobParameters parameters);
    boolean stop(long executionId);
    Long restart(long executionId);
    // ...
}

JobOperator(Job 실행·중지·재시작 진입점)가 Job 의 시작·중지·재시작을 책임져요. 8편 깊이.

3. TransactionManager

PlatformTransactionManager(스프링 트랜잭션 추상화). chunk 단위 transaction commit/rollback 의 기반이에요.

4. JobLauncher (자주 JobOperator 가 wrap)

JobLauncher(실제 Job 을 시작시키는 컴포넌트)가 Job 을 실제로 띄워요.

5. JobRegistry (옵션)

JobRegistry(이름으로 Job 을 찾기 위한 레지스트리)는 이름 → Job 매핑을 들고 있어요. CLI·REST 에서 이름으로 호출할 때 필요해요.

6. JobScope·StepScope

@Bean
@StepScope
public ItemReader<String> reader(@Value("#{jobParameters['filePath']}") String filePath) {
    // ...
}

JobScope·StepScope(Job·Step 생명주기에 묶인 bean scope). late binding (실행 시점에 값 주입) 으로 동작해요 — 21편에서 다뤄요.

v6 — 3가지 설정 방식

Way 1: @EnableBatchProcessing (기본 — Resourceless)

@Configuration
@EnableBatchProcessing
public class MyJobConfig {
    @Bean
    public Job job(JobRepository repo) {
        return new JobBuilder("myJob", repo).build();
    }
}

v6 의 기본 동작은 ResourcelessJobRepository 예요. 메모리 only, DB 안 필요.

장점:

  • 학습·테스트 매우 간단
  • DB·schema 설정 없이 시작

단점:

  • Job 재시작 불가 (메모리만 → 종료 시 사라짐)
  • 운영 환경 절대 사용 X

Way 2: @EnableJdbcJobRepository (운영 표준)

@Configuration
@EnableBatchProcessing
@EnableJdbcJobRepository
public class MyJobConfig {
    // DataSource 필요 (Spring Boot 자동)
}

@EnableJdbcJobRepository(JDBC 기반 JobRepository 활성). DB 에 영속 저장, 재시작 가능. 운영 환경 권장.

자동 활성 조건 (Spring Boot):

  • spring-boot-starter-data-jpa 또는 spring-jdbc 의존성
  • DataSource bean 존재

Way 3: @EnableMongoJobRepository

@EnableMongoJobRepository

MongoDB 기반. RDBMS 안 쓰는 환경 의 옵션이에요. v6 신규.

DefaultBatchConfiguration — Class 기반

annotation 대신 class 상속:

@Configuration
public class MyBatchConfig extends DefaultBatchConfiguration {

    @Bean
    public Job job(JobRepository repo) {
        // ...
    }
}

DefaultBatchConfiguration(상속으로 배치 설정을 커스터마이즈하는 베이스 클래스)에 세 갈래가 있어요:

  • DefaultBatchConfiguration — Resourceless
  • JdbcDefaultBatchConfiguration — JDBC
  • MongoDefaultBatchConfiguration — MongoDB

annotation vs class 차이:

  • annotation = 더 짧고 간결
  • class = override 자유 (특정 bean customize 시)

대부분 환경은 annotation 으로 충분해요.

Spring Boot 자동 구성

Spring Boot 의 BatchAutoConfiguration(Spring Boot 가 배치 컴포넌트를 자동 등록하는 자동 구성)이 대부분 자동 처리:

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

이거면 끝. Spring Boot 가 알아서:

  • JobRepository 자동 생성 (DataSource 있으면 JDBC, 없으면 Resourceless)
  • JobOperator·JobLauncher·TransactionManager 자동
  • DB schema 자동 초기화 (spring.batch.jdbc.initialize-schema=always)
  • Job 자동 실행 (spring.batch.job.enabled=true)

여기서 시험 함정이 하나 있어요 — Spring Boot 가 @EnableBatchProcessing 자동 추가 X. 명시 해야 해요. (v5 부터)

@Configuration
@EnableBatchProcessing          // 명시!
public class BatchConfig { }

운영 환경 권장 설정

application.yml

spring:
  datasource:
    url: jdbc:postgresql://db:5432/batch
    username: ${DB_USER}
    password: ${DB_PASSWORD}
    hikari:
      maximum-pool-size: 10
      minimum-idle: 2

  batch:
    jdbc:
      initialize-schema: never              # 운영 환경 = never
      schema: classpath:org/springframework/batch/core/schema-postgresql.sql
      table-prefix: BATCH_
    job:
      enabled: false                        # CLI 또는 REST 로 명시 실행

핵심:

  • initialize-schema: never = 운영에서 자동 schema 는 위험해요. DBA 가 수동 적용.
  • spring.batch.job.enabled: false = application 시작 시 자동 실행 X. JobLauncher 로 명시 실행.

명시 schema 생성 (운영 첫 deploy)

$ psql -d batch < schema-postgresql.sql

schema 파일은 spring-batch-core jar 안에 들어 있어요. 47편 Schema 에서 더 깊이 다뤄요.

명시 Job 실행

CLI:

$ java -jar my-batch.jar --job.name=myJob --param1=value1

또는 REST:

@RestController
public class JobController {
    @Autowired
    private JobOperator jobOperator;

    @PostMapping("/jobs/{name}/start")
    public Long start(@PathVariable String name, @RequestBody Map<String, String> params) {
        Job job = jobRegistry.getJob(name);
        return jobOperator.start(job, buildParameters(params));
    }
}

Customizing — DefaultBatchConfiguration override

특정 bean override:

@Configuration
public class CustomBatchConfig extends JdbcDefaultBatchConfiguration {

    @Override
    protected String getTablePrefix() {
        return "MY_BATCH_";          // 기본 "BATCH_" → "MY_BATCH_"
    }

    @Override
    protected Charset getCharset() {
        return StandardCharsets.UTF_8;
    }

    @Override
    protected DatabaseType getDatabaseType() {
        return DatabaseType.POSTGRES;
    }

    // 기타 customize ...
}

자주 customize 하는 자리:

  • getTablePrefix() — 여러 batch 가 같은 DB schema 를 공유할 때 분리용
  • getCharset() — 비-UTF-8 환경
  • getMaxVarCharLength() — long parameter·context 저장
  • getDatabaseType() — auto-detect 안 될 때

Table Prefix — 다중 Batch

같은 DB 에 여러 batch application 이 공유될 때:

# Batch A
spring.batch.jdbc.table-prefix: BATCH_A_

# Batch B
spring.batch.jdbc.table-prefix: BATCH_B_

각자 별도로 BATCH_A_*·BATCH_B_* 테이블을 써요. 충돌 없음.

Multi DataSource — Business 와 Batch 분리

큰 운영 환경에서 자주 보이는 패턴 — business 데이터 DBJobRepository DB 분리.

@Configuration
public class BatchConfig extends JdbcDefaultBatchConfiguration {

    @Bean
    @ConfigurationProperties("spring.datasource.batch")
    public DataSource batchDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.business")
    public DataSource businessDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Override
    @Bean
    public DataSource getDataSource() {
        return batchDataSource();
    }

    @Override
    @Bean
    public PlatformTransactionManager getTransactionManager() {
        return new JdbcTransactionManager(batchDataSource());
    }
}
spring:
  datasource:
    batch:
      url: jdbc:postgresql://batch-db:5432/batch_meta
    business:
      url: jdbc:postgresql://biz-db:5432/business

장점은 batch 메타데이터 DBbusiness DB 영향 X. 백업·복구도 따로 분리돼요.

Bean 의존성 한눈에

DataSource (Spring Boot 자동)
    ↓
TransactionManager (JdbcTransactionManager)
    ↓
JobRepository (JdbcJobRepository) ──┐
    ↓                                │
JobLauncher                          ↓
    ↓                          JobOperator
[Job] ↔ [Step] ↔ [Reader/Writer]

대부분 자동이라 직접 만들 일은 거의 없어요.

모니터링·디버깅

로그

logging:
  level:
    org.springframework.batch.core: INFO
    org.springframework.batch.repeat: DEBUG          # chunk 단위 디버깅
    org.springframework.transaction: DEBUG           # transaction 추적

Actuator

management:
  endpoints:
    web:
      exposure:
        include: health,info,batch
  endpoint:
    batch:
      enabled: true

/actuator/batch현재 Job 상태 를 노출해요 (Spring Boot 3.5+).

한계·실무 함정

1. ResourcelessJobRepository 운영 사용

절대 X. 재시작 불가에 이력이 사라져서 운영 사고로 직결돼요.

2. initialize-schema: always 운영

운영 DB 가 부팅마다 schema 재생성 을 시도해요. 위험.

3. job.enabled: true 운영

운영 환경에서 부팅마다 Job 이 자동 실행 돼서 의도 안 한 실행이 일어나요. 명시 실행 권장.

4. @EnableBatchProcessing 누락

Spring Batch 6 부터는 명시 필수. 누락하면 Bean 이 만들어지지 않아요.

5. Table prefix 통일

여러 application 이 같은 prefix 를 쓰면 transaction 안에서 메타데이터가 충돌 해요. 명시 분리.

6. Multi-DataSource transaction 분리

batch metadata 와 business data 가 다른 DB 인데 같은 transaction 으로 처리하려고 하면 2-phase commit 필요 (XA, 두 DB 를 한 트랜잭션으로 묶는 분산 커밋 프로토콜). 분리 권장.

시험 직전 한 번 더 — Batch Infrastructure 함정 압축 노트

  • Infrastructure Beans 6가지 = JobRepository · JobOperator · TransactionManager · JobLauncher · JobRegistry · JobScope/StepScope
  • 3가지 설정 방식 = @EnableBatchProcessing (기본, Resourceless) · @EnableJdbcJobRepository (운영) · @EnableMongoJobRepository
  • 또는 class — DefaultBatchConfiguration·JdbcDefaultBatchConfiguration·MongoDefaultBatchConfiguration
  • ResourcelessJobRepository (v6 신규) = 메모리 only, 학습·테스트만
  • 운영 표준 = @EnableJdbcJobRepository (또는 Mongo)
  • Spring Boot = 대부분 자동 (DataSource 있으면 JDBC), 단 @EnableBatchProcessing 명시 필요
  • 운영 yml — initialize-schema: never + job.enabled: false
  • 명시 schema = jar 안 schema-<db>.sqlDBA 가 적용
  • 명시 Job 실행 = CLI·REST·JobOperator.start()
  • DefaultBatchConfiguration overridegetTablePrefix·getCharset·getMaxVarCharLength·getDatabaseType
  • Table Prefix = 다중 batch application 분리 (BATCH_A_·BATCH_B_)
  • Multi-DataSource = batch metadata DB ↔ business DB 분리 (운영 권장)
  • Bean 의존성 — DataSource → TransactionManager → JobRepository → JobLauncher/Operator
  • 로그 — org.springframework.batch.core: INFO·repeat: DEBUG
  • /actuator/batch (Spring Boot 3.5+)
  • 함정 — Resourceless 운영 사용 = 재시작 불가
  • 함정 — initialize-schema: always 운영 = DB schema 위험
  • 함정 — job.enabled: true 운영 = 부팅마다 자동 실행
  • 함정 — @EnableBatchProcessing 누락 (v6 명시 필수)
  • 함정 — Table prefix 통일 = 메타데이터 충돌
  • 함정 — Multi-DataSource 의 transaction = 2PC 필요

공식 문서: Batch infrastructure Configuration 에서 원문을 확인할 수 있어요.

시리즈 다른 편 (앞뒤 글 모음)

이전 글:

다음 글:

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!