🔍 Spring Batch란?
배치 처리(batch processing)를 효율적으로 수행할 수 있도록 도와주는 Spring 기반의 오픈 소스 프레임워크입니다.
일반적으로 배치 작업은 대량의 데이터를 처리하거나, 주기적이고 반복적인 작업을 자동화하는 데 사용됩니다.
활용 예:
- 로깅 및 추적
- 트랜잭션 관리
- 정기적인 대량 데이터 처리
Spring Batch와 Scheduler
| 항목 | Spring Batch | Scheduler |
| 역할 | - 대량의 데이터 처리 - 로그 처리 등의 무거운 작업을 처리하는 배치 프레임워크 → 무엇을 처리할 지 |
특정 시점/주기로 작업을 스케줄링해서 실행하는 기능 → 언제 실행할 지 |
| 주요 기능 | Reader, Processor, Writer 구조로 복잡한 데이터 처리 흐름 구성 |
주기적으로 특정 메서드를 실행하게 함 (`@Scheduled`) |
| 상태 저장 | Job 실행 이력, 실패/재시작 상태 저장 가능 (DB 기반) |
상태 저장 기능 없음 기본적으로 단순 실행 |
| 트랜잭션 관리 | 트랜잭션, 커밋/롤백, 체크포인트 등 내장 지원 | 트랜잭션 직접 구현해야 함 |
| 실행 방식 | 스케줄러로 실행됨 (예: @Scheduled, Quartz 등) | 주기적으로 지정한 메서드 실행 |
| 확장성 | 분산 처리, 병렬 처리, 예외 리커버리 등 확장성 높음 | 단순 반복 작업에 적합 |
Spring Batch는 '무엇'을 처리하고, Scheduler는 '언제' 처리할지 결정합니다.
🧱 Spring Batch의 구성요소
Spring Batch는 대규모 데이터 처리 흐름을 잘게 나눠 체계적으로 구성할 수 있도록 여러 핵심 구성요소를 제공합니다.
가장 기본이 되는 구성은 Job → Step → (Reader → Processor → Writer) 구조입니다.
| 구성요소 | 설명 |
| Job | - 배치 작업 전체 단위 - 하나의 Job은 여러 개의 Step으로 구성됨 - 실행될 때마다 `JobInstance`, `JobExecution`이 생성되어 실행 이력 관리가 가능 |
| Step | - Job 안에 포함되는 단위 작업 - 각각의 Step은 독립적인 처리 흐름을 가짐 (Reader → Processor → Writer) - 트랜잭션 단위로 실행되며, 실패/재시도, 스킵 등의 설정 가능 |
| ItemReader | - 데이터를 읽어오는 역할 - DB, CSV, XML, API 등 다양한 소스로부터 데이터를 가져옴 |
| ItemProcessor | - 읽어온 데이터를 가공/필터링/검증하는 역할 - Null을 리턴하면 Writer로 전달되지 않음 |
| ItemWriter | - 처리된 데이터를 목적지에 저장하는 역할 - DB, 파일, 외부 API 등 다양한 출력 가능 |
| JobRepository | - Job, Step 실행 정보(상태, 시작/종료 시간 등)를 DB에 기록 - Spring Batch가 실행 이력과 상태를 관리하는 핵심 구성요소 |
| JobLauncher | - Job을 실행시키는 역할 - 코드에서 수동 실행하거나, 스케줄러(`@Scheduled`)에서 호출 |
Spring Batch에서 데이터 처리 방식
| 처리 방식 | 설명 |
| Tasklet 기반 | 한 번에 전체 로직을 수행 (단순하거나 고정된 작업에 적합) `StepBuilder.tasklet(...)` 단일 Tesk 기반으로 동작 |
| Chunk 기반 | 데이터를 일정 단위(chunk)로 나누어 `read -> process -> write` 반복 수행 `StepBuilder.chunk(...)` Step이 Chunk 기반으로 동작 |
📝 table-now 프로젝트에서의 Spring Batch
결제 완료된 데이터를 기반으로 정산 데이터를 생성하고,
일정 시간 이후 정산 상태를 완료로 변경하는 2단계 정산 처리 시스템이 구현되었습니다.
Spring Batch의 Chunk 기반 처리 방식으로, Reader → Processor → Writer로 구성되었습니다.
`SettlementRegisterJobConfig`
결제된 결제(Payment) 중 아직 정산(Settlement)이 생성되지 않은 건을 찾아 정산 테이블에 등록

- Reader
- 결제 완료(payment.status가 `DONE`)이고, settlement 테이블에 아직 해당 payment에 대한 정산 레코드가 없는 경우
- 등록되지 않은 payment에 대해 settlement를 새로 생성
- Processor
- `Payment` -> `Settlement`
- Writer
- 등록된 Settlement를 DB에 저장
`SettlementCompleteJobConfig`
상태가 READY인 정산 건을 DONE 상태로 변경

- Reader
- 상태가 `READY`인 settlement만 조회
- Processor
- Settlement 객체의 상태를 `DONE`으로 변경
- Writer
- DB에 저장된 settlement의 상태 변경 (status = `DONE`, updated_at = NOW())
`SettlementScheduler`
위 두 Job을 스케줄링하여 주기적으로 실행 (`@Scheduled`)
- 정산 등록: 1시간 마다
- 정산 완료: 매일 자정
동시 Job 실행 방지를 위해 Redisson으로 분산 락 처리 포함
- 정산 등록과 완료 Job이 동시에 실행되면 데이터 충돌이 발생할 수 있어 Redisson 기반 분산 락을 적용하여 순차 실행을 보장
🧠 마무리
- Spring Batch는 대량 데이터를 안정적으로 처리하는 데 적합한 프레임워크
- Scheduler는 작업 실행 시점을 제어하고, Spring Batch는 실제 작업의 흐름을 담당
- Reader → Processor → Writer 구조는 Chunk 방식의 구조
- 트랜잭션 단위로 처리되므로 대규모 처리 시에도 안정성을 유지
- 프로젝트에서는 Job 간 충돌 방지를 위한 분산 락(Redis 기반 Redisson) 적용하는 방식으로 구현됨
'Dev Projects' 카테고리의 다른 글
| [table-now] 1:1(예약자:가게) 채팅 기능 고도화를 위해 RabbitMQ Relay를 적용한 이유 (0) | 2025.06.05 |
|---|---|
| [table-now] 예약자-사장님 1:1 실시간 채팅 기능 설계 및 구현 (2) | 2025.06.04 |
| [table-now] Spring Security의 oauth2Login() 대신 WebClient를 선택한 이유 (3) | 2025.05.28 |
| [table-now] 의사결정 기록 - 외부 연동 시스템 예외 처리 강화 리팩토링 (0) | 2025.05.23 |
| [table-now] S3 이미지 업로드 - Presigned Url 방식으로 구현하기 (1) | 2025.05.23 |
