Spring Batch 완전 학습 인덱스


1. 개요 & 배경

배치 처리란?

  • 배치(Batch) vs 실시간(Real-time) 처리 비교
  • 배치가 필요한 대표적인 상황
    • 대용량 데이터 정산 / 집계
    • 주기적인 리포트 생성
    • 외부 시스템 데이터 동기화
    • 야간 마감 처리 / 월말 정산
  • 배치 처리의 핵심 요구사항 — 안정성, 재시작 가능성, 추적 가능성

Spring Batch란?

  • Spring Batch가 해결하는 문제 (직접 구현 대비)
  • JSR-352 (Batch Applications for Java EE) 표준과의 관계
  • Spring Batch 5.x 주요 변화 (Spring Boot 3.x 기반)
  • Spring Batch vs Quartz vs Spring Scheduler 역할 구분

핵심 아키텍처 미리보기

  • JobStepItemReaderItemProcessorItemWriter 흐름
  • JobRepository — 모든 메타데이터의 저장소
  • JobLauncher — Job 실행 진입점

2. 아키텍처 & 도메인 모델

Job

  • Job — 배치 작업의 최상위 단위
  • JobInstance — Job + JobParameters의 실행 단위
  • JobExecution — JobInstance의 실제 실행 기록 (시도마다 생성)
  • JobParameters — Job 실행 시 전달되는 파라미터 (식별자 역할)
    • String, Long, Double, Date 타입
    • identifying vs non-identifying 파라미터

Step

  • Step — Job을 구성하는 독립적인 처리 단위
  • StepExecution — Step의 실제 실행 기록
  • ExecutionContext — Step/Job 간 데이터 공유 저장소 (직렬화 주의)
  • Chunk-oriented Step vs Tasklet Step

JobRepository & 메타데이터 테이블

  • JobRepository의 역할 — 실행 이력 영속화
  • 메타데이터 테이블 구조
    • BATCH_JOB_INSTANCE
    • BATCH_JOB_EXECUTION
    • BATCH_JOB_EXECUTION_PARAMS
    • BATCH_JOB_EXECUTION_CONTEXT
    • BATCH_STEP_EXECUTION
    • BATCH_STEP_EXECUTION_CONTEXT
  • 스키마 초기화 설정 (spring.batch.jdbc.initialize-schema)
  • 메타데이터 DB를 운영 DB와 분리하는 패턴

JobLauncher

  • JobLauncher.run(Job, JobParameters)
  • 동기(Synchronous) vs 비동기(Asynchronous) 실행
  • TaskExecutorJobLauncher

3. Job 구성

Job 정의 방식 (Spring Batch 5.x)

  • JobBuilder / JobBuilderFactory (deprecated in 5.x)
  • new JobBuilder("jobName", jobRepository) — 5.x 방식
  • @Configuration 클래스에서 @Bean으로 등록

Job 실행 조건

  • JobParameters로 동일 Job의 재실행 구분
    • 같은 JobParameters → 이미 완료된 JobInstance 재실행 불가 (JobInstanceAlreadyCompleteException)
    • 타임스탬프 파라미터 추가로 매번 새 인스턴스 생성 패턴
  • JobParametersIncrementer — 파라미터 자동 증가
    • RunIdIncrementer (기본 제공)
    • 커스텀 Incrementer 구현

Job 흐름 제어

  • 순차 실행: start(step1).next(step2).next(step3)
  • 조건부 흐름: on("FAILED").to(failStep).on("*").to(nextStep)
  • BatchStatus vs ExitStatus 차이
    • BatchStatus — 프레임워크 내부 상태 (COMPLETED, FAILED, STOPPED 등)
    • ExitStatus — 흐름 제어용 문자열 상태 (커스텀 가능)
  • end() vs fail() vs stopAndRestart()

Job 리스너

  • JobExecutionListener — beforeJob / afterJob
  • @BeforeJob / @AfterJob 어노테이션 방식
  • 슬랙 알림, 로그 기록 등 횡단 관심사 처리 패턴

4. Step — Chunk 지향 처리

Chunk 처리란?

  • 데이터를 N개씩 묶어서 읽기 → 처리 → 쓰기 반복
  • commit-interval (chunk size) — 한 트랜잭션에서 처리할 아이템 수
  • 청크 처리 트랜잭션 경계
    • 읽기 실패: 현재 청크 롤백
    • 쓰기 실패: 현재 청크 롤백
    • ItemReader는 롤백 안 되는 경우 (상태 주의)

StepBuilder (Spring Batch 5.x)

  • new StepBuilder("stepName", jobRepository)
  • .<InputType, OutputType>chunk(chunkSize, transactionManager)
  • .reader(), .processor(), .writer()
  • .faultTolerant() — 내결함성 설정 진입

Step 리스너

  • StepExecutionListener — beforeStep / afterStep
  • ItemReadListener — beforeRead / afterRead / onReadError
  • ItemProcessListener — beforeProcess / afterProcess / onProcessError
  • ItemWriteListener — beforeWrite / afterWrite / onWriteError
  • ChunkListener — beforeChunk / afterChunk / afterChunkError

5. Step — Tasklet 처리

Tasklet이란?

  • 단순 작업 단위 — execute() 한 번 호출
  • RepeatStatus.FINISHED vs RepeatStatus.CONTINUABLE
  • 트랜잭션 적용 범위 (Tasklet 전체가 하나의 트랜잭션)

활용 사례

  • 파일 이동 / 삭제 / 압축
  • DB 테이블 초기화 / 임시 데이터 정리
  • 외부 API 단순 호출
  • 집계 결과 알림 발송

커스텀 Tasklet 구현

  • Tasklet 인터페이스 구현
  • StepContribution, ChunkContext 활용
  • ExecutionContext를 통한 상태 저장

6. ItemReader

기본 개념

  • ItemReader<T>read() 반환 null이면 입력 끝
  • Thread-safety 주의 (대부분의 기본 구현체는 Non Thread-safe)
  • ItemStreamReaderopen(), update(), close() 생명주기

파일 기반 Reader

  • FlatFileItemReader — CSV, 구분자 기반 파일
    • DelimitedLineTokenizer — 구분자 기반
    • FixedLengthTokenizer — 고정 길이
    • DefaultLineMapper + BeanWrapperFieldSetMapper
    • 인코딩 설정, 건너뛸 라인 수(linesToSkip)
  • JsonItemReader — JSON 배열 파일
    • JacksonJsonObjectReader
  • MultiResourceItemReader — 여러 파일을 순서대로 처리

DB 기반 Reader

  • JdbcCursorItemReader — DB 커서 방식 (단일 커넥션, 빠름)
    • RowMapper 설정
    • fetchSize — 네트워크 왕복 최소화
  • JdbcPagingItemReader — 페이징 방식 (커넥션 반환 후 재조회)
    • PagingQueryProvider — DB별 페이징 쿼리 생성
    • SqlPagingQueryProviderFactoryBean
    • 정렬 키(sortKeys) 필수 — 중복 방지
  • JpaCursorItemReader (Spring Batch 4.3+) — JPA 커서
  • JpaPagingItemReader — JPA 페이징
  • 커서 vs 페이징 선택 기준
    • 커서: 빠르지만 커넥션 오래 점유, Thread-safe 아님
    • 페이징: 약간 느리지만 병렬 처리 가능

커스텀 Reader

  • ItemReader<T> 직접 구현
  • ItemStreamReader 구현 — 재시작 지원을 위한 상태 저장
  • API 기반 Reader, 메시지 큐 기반 Reader 패턴

7. ItemProcessor

기본 개념

  • ItemProcessor<I, O>process() null 반환 시 해당 아이템 필터링
  • Reader 타입과 Writer 타입이 다를 때 변환 역할
  • 비즈니스 검증 / 변환 / 필터링 로직 위치

활용 패턴

  • 도메인 객체 → DTO 변환
  • 조건에 맞지 않는 아이템 null 반환으로 필터링
  • 외부 API / DB 조회로 데이터 보강 (Enrichment)
  • 유효성 검사 + SkipPolicy와 조합

CompositeItemProcessor

  • 여러 Processor를 체인으로 연결
  • setDelegates(List<ItemProcessor>) 설정
  • 단계별 변환이 필요한 복잡한 처리

ValidatingItemProcessor

  • Validator<T> 연동
  • JSR-303 (@Valid) 통합
  • 검증 실패 시 skip 또는 예외

8. ItemWriter

기본 개념

  • ItemWriter<T>write(Chunk<? extends T> chunk) (Spring Batch 5.x)
  • 청크 단위로 묶어서 한 번에 쓰기

파일 기반 Writer

  • FlatFileItemWriter — CSV, 구분자 파일 쓰기
    • BeanWrapperFieldExtractor
    • DelimitedLineAggregator
    • shouldDeleteIfExists / appendAllowed
  • JsonFileItemWriter — JSON 파일 쓰기
  • MultiResourceItemWriter — 일정 아이템 수마다 새 파일 생성

DB 기반 Writer

  • JdbcBatchItemWriter — JDBC Batch INSERT/UPDATE (성능 최고)
    • sql + beanMapped() / columnMapped()
    • assertUpdates — 업데이트 건수 검증
  • JpaItemWriter — JPA merge() 기반
    • 배치 INSERT 성능 주의 (IDENTITY 전략 문제)
  • HibernateItemWriter

커스텀 Writer

  • ItemWriter<T> 직접 구현
  • 외부 API 호출, 메시지 발행, 이메일 발송 등

CompositeItemWriter

  • 여러 Writer에 동시에 쓰기
  • 트랜잭션 공유 주의사항

ClassifierCompositeItemWriter

  • 아이템 타입/조건에 따라 다른 Writer로 분기
  • Classifier<T, ItemWriter<? super T>> 구현

9. 내결함성 (Fault Tolerance)

Skip

  • 처리 중 특정 예외 발생 시 해당 아이템 건너뜀
  • .faultTolerant().skip(SomeException.class).skipLimit(10)
  • SkipPolicy — 커스텀 스킵 정책 구현
  • Read / Process / Write 단계별 스킵 동작 차이
    • Write 스킵: 청크를 아이템 단위로 재처리 (binary search 방식)
  • SkipListener — 스킵된 아이템 기록

Retry

  • 처리 실패 시 지정 횟수만큼 재시도
  • .faultTolerant().retry(SomeException.class).retryLimit(3)
  • RetryPolicy / BackOffPolicy — 커스텀 재시도 정책
  • RetryListener — 재시도 이벤트 처리
  • Skip + Retry 조합 시 동작 순서

noSkip / noRetry

  • 특정 예외는 절대 스킵/재시도 하지 않도록 설정
  • 치명적 예외 보호 (FatalStepExecutionException)

10. 재시작 (Restart)

재시작 기본 원리

  • 실패한 JobInstance를 동일 JobParameters로 재실행
  • StepExecution의 마지막 성공 상태부터 재개
  • ExecutionContext에 저장된 커서/오프셋으로 재개 위치 복원

ItemStream과 재시작

  • ItemStreamReaderupdate(ExecutionContext)로 진행 상태 저장
  • ItemStreamWriter — 파일 append 모드 재시작
  • 기본 제공 Reader들은 대부분 재시작 지원

재시작 불가 설정

  • preventRestart() — Job 재시작 금지 (매번 새로 실행)
  • startLimit(n) — Step 최대 실행 횟수 제한

재시작 시나리오별 처리

  • 부분 성공 후 실패: 성공한 청크는 건너뜀
  • Step 중간 실패: 해당 Step부터 재시작
  • 이미 완료된 Step 재실행: allowStartIfComplete(true)

11. 병렬 처리

Multi-threaded Step

  • TaskExecutor를 Step에 적용 → 청크 단위 병렬 처리
  • Thread-safe ItemReader 필수 (SynchronizedItemStreamReader로 래핑)
  • throttleLimit — 동시 실행 스레드 수 제한 (deprecated in 5.x, TaskExecutor 직접 제어)
  • 재시작 지원 제한 (커서 위치 공유 불가)

Parallel Steps (Split Flow)

  • 여러 Step을 동시에 실행 (split(taskExecutor).add(flow1, flow2))
  • 독립적인 Step들을 병렬로 처리
  • 모든 병렬 Step 완료 후 다음 Step 진행

Partitioning (파티셔닝)

  • 데이터를 파티션으로 분할 → 각 파티션을 Worker Step에서 병렬 처리
  • Partitioner — 파티션 정의 (ExecutionContext 맵 반환)
  • PartitionHandler — Worker 실행 방식 결정
    • TaskExecutorPartitionHandler — 로컬 멀티스레드
    • MessageChannelPartitionHandler — 원격 Worker (Spring Integration)
  • 범위 기반 파티셔닝 (ColumnRangePartitioner 패턴)
  • 대용량 처리에 가장 효과적인 방법

Remote Chunking

  • Manager가 데이터를 읽어 Worker에 전달 → Worker가 처리/쓰기
  • Spring Integration / Kafka / RabbitMQ 기반 통신
  • 네트워크 부하 주의 (I/O 병목 시 비효율)

12. JobParameters & 실행 관리

JobParameters 활용

  • 실행 날짜, 파일 경로, 처리 대상 범위 등 외부 주입
  • @Value("#{jobParameters['targetDate']}") — SpEL로 주입
  • @StepScope / @JobScope — 런타임 바인딩을 위한 필수 설정
    • Step/Job 빌드 시점이 아닌 실행 시점에 Bean 생성
    • Lazy Proxy 원리

@JobScope vs @StepScope

  • @JobScope — Job 실행 시 생성, Job 종료 시 소멸
  • @StepScope — Step 실행 시 생성, Step 종료 시 소멸
  • Late Binding (지연 바인딩) 패턴

Job 실행 방식

  • CommandLineJobRunner — CLI 실행
  • JobLauncherApplicationRunner — Spring Boot 자동 실행
    • spring.batch.job.enabled=false — 자동 실행 비활성화
    • spring.batch.job.name — 실행할 Job 지정
  • 프로그래밍 방식 JobLauncher.run() — API 트리거

13. 스케줄링 연동

Spring Scheduler

  • @Scheduled(cron = "0 0 2 * * *") — 새벽 2시 실행
  • @EnableScheduling
  • Scheduler + JobLauncher 조합 패턴
  • 클러스터 환경에서의 중복 실행 문제

Quartz 연동

  • QuartzJobBean + JobLauncher
  • JobDetailFactoryBean / CronTriggerFactoryBean
  • Quartz 클러스터링 — JDBC JobStore로 중복 실행 방지
  • DB 기반 잠금으로 단일 실행 보장

ShedLock

  • 분산 환경에서 스케줄 중복 실행 방지
  • @SchedulerLock(name = "jobName")
  • DB / Redis 기반 락

14. 모니터링 & 운영

Spring Batch Admin / Spring Cloud Data Flow

  • Spring Batch Admin (deprecated) 대안
  • Spring Cloud Data Flow — 배치/스트림 통합 관리
  • Kubernetes 기반 배포 시 고려사항

Actuator 연동

  • /actuator/health — 배치 헬스 체크
  • 메타데이터 테이블 기반 모니터링

메트릭 (Micrometer)

  • spring.batch.metrics.enabled=true (Spring Batch 5.x)
  • Job/Step 실행 시간, 읽기/처리/쓰기 카운트
  • Prometheus + Grafana 대시보드 구성

로깅 & 추적

  • JobExecution / StepExecution 상태 조회 SQL
  • 배치 실행 이력 조회 API 패턴
  • 실패 원인 파악 — exitDescription 필드
  • MDC 기반 Job/Step 컨텍스트 로그

운영 이슈 대응

  • 장시간 실행 배치 모니터링
  • 배치 강제 종료 후 재시작 절차
  • 메타데이터 테이블 정기 정리 (JobExplorer + JobOperator)
  • JobOperator.stop() — 실행 중인 Job 중지

15. 테스트

단위 테스트

  • ItemReader / ItemProcessor / ItemWriter 단독 테스트
  • Mockito 활용 의존성 Mock 처리
  • StepScopeTestUtils@StepScope Bean 테스트

통합 테스트

  • @SpringBatchTest (Spring Batch 4.1+)
    • JobLauncherTestUtils — Job/Step 실행
    • JobRepositoryTestUtils — 실행 이력 정리
    • StepScopeTestExecutionListener
  • @SpringBootTest + @SpringBatchTest 조합
  • jobLauncherTestUtils.launchJob(jobParameters) — Job 전체 테스트
  • jobLauncherTestUtils.launchStep("stepName") — Step 단독 테스트

테스트 DB 설정

  • H2 인메모리 DB — 빠른 단위 테스트
  • Testcontainers — 실제 DB 환경 통합 테스트
  • 메타데이터 테이블 자동 초기화 설정

청크 테스트 패턴

  • JobRepositoryTestUtils.removeJobExecutions() — 테스트 간 격리
  • AssertFile — 출력 파일 내용 검증
  • 아이템 카운트, 스킵 카운트 검증

16. 실무 패턴 & 베스트 프랙티스

대용량 처리 설계

  • JdbcCursorItemReader vs JdbcPagingItemReader 선택
  • 적절한 chunk size 설정 (일반적으로 100~1000, 측정 기반)
  • 파티셔닝으로 병렬화 — CPU / IO 바운드 구분
  • DB 인덱스 최적화 (Reader 쿼리 기준)

멱등성 (Idempotency) 확보

  • 배치는 언제든 재실행 가능해야 함
  • UPSERT 패턴 (INSERT ON DUPLICATE KEY UPDATE)
  • 처리 완료 플래그 컬럼 활용
  • 중복 처리 방지 로직

배치 실패 알림

  • JobExecutionListener.afterJob()에서 FAILED 상태 감지
  • 슬랙, 이메일, PagerDuty 알림 패턴
  • 실패 원인 exitDescription 파싱

Job 분리 전략

  • 하나의 Job은 하나의 책임
  • 공통 Step 재사용 패턴
  • Job Flow 복잡도 제한 (Step 수 기준)
  • 배치 서버 분리 vs 애플리케이션 내장

안티패턴

  • Step 안에서 또 다른 Service 트랜잭션 남발 — 트랜잭션 경계 혼란
  • JpaItemWriter + IDENTITY 전략 — 배치 INSERT 불가 (SEQUENCE 또는 JdbcBatchItemWriter 사용)
  • chunk size = 1 — 트랜잭션 오버헤드
  • 메타데이터 테이블 무한 누적 — 정기 정리 필수
  • @StepScope 없이 JobParameters SpEL 바인딩 — NPE 또는 잘못된 값

17. Spring Batch 5.x 변경사항

Spring Boot 3.x / Spring Batch 5.x 주요 변화

  • Java 17 최소 요구사항
  • Jakarta EE 10 (javaxjakarta)
  • JobBuilderFactory / StepBuilderFactory 제거 → JobBuilder / StepBuilder 직접 사용
  • ItemWriter.write(List)ItemWriter.write(Chunk) 시그니처 변경
  • JobParameters 타입 변경 (날짜 타입 제거, LocalDate/LocalDateTime 지원 추가)
  • @EnableBatchProcessing 자동 구성 변경 — DefaultBatchConfiguration 상속 방식

마이그레이션 포인트

  • JobBuilderFactoryJobBuilder(name, jobRepository)
  • StepBuilderFactoryStepBuilder(name, jobRepository)
  • write(List<? extends T>)write(Chunk<? extends T>)
  • spring.batch.job.namesspring.batch.job.name (단수 변경)
  • 메타데이터 스키마 변경 여부 확인

17 items under this folder.