이번 글에서는 Spring Batch의 핵심 구성요소인 Reader / Processor / Writer를
“실무 기준”으로 이해할 수 있도록 정리합니다.
Chunk 기반 Step에서 가장 중요한 부분이 바로 이 3요소이며,
구조를 어떻게 잡느냐에 따라 성능, 유지보수성, 장애 대응까지 큰 차이가 납니다.
✔ Reader / Processor / Writer는 왜 중요한가?
Spring Batch에서 Chunk 기반 Step은 아래 순서로 반복 실행됩니다.
Reader → Processor → Writer → (반복)
즉, Reader가 데이터를 어떻게 읽고, Processor가 무엇을 가공하며, Writer가 어디로 저장하느냐가 전체 배치 품질을 결정합니다.
- Reader: 어디에서 데이터를 읽을 것인가?
- Processor: 읽어온 데이터를 어떻게 변환할 것인가?
- Writer: 변환된 데이터를 어디로 보낼 것인가?
이제 실무 사례 기반으로 하나씩 살펴보겠습니다.
1. ItemReader — 데이터를 읽는 방식 선택하기
Reader는 “무엇을 읽을지”에 따라 전략이 달라집니다.
✔ 1) JpaPagingItemReader (페이징 기반)
가장 많이 사용하는 Reader. 대량 데이터 읽기에 적합하며, 페이징 방식으로 안정적으로 처리합니다.
@Bean
public JpaPagingItemReader<MailEntity> waitingMailReader() {
return new JpaPagingItemReaderBuilder<MailEntity>()
.name("waitingMailReader")
.entityManagerFactory(entityManagerFactory)
.queryString("SELECT m FROM MailEntity m WHERE m.status = 'WAIT'")
.pageSize(100)
.build();
}
실무 장점
- 대량 데이터 읽을 때 안전함
- DB 부하가 적음
- Chunk 크기와 페이징 크기가 잘 맞음
✔ 2) JdbcCursorItemReader (커서 기반)
데이터량이 중간 수준일 때 더 빠르게 읽고 싶을 때 좋습니다.
@Bean
public JdbcCursorItemReader<User> userCursorReader() {
return new JdbcCursorItemReaderBuilder<User>()
.name("userCursorReader")
.dataSource(dataSource)
.sql("SELECT id, name, email FROM users")
.rowMapper(new UserRowMapper())
.build();
}
단점: 대량 데이터에는 커서 방식이 불안정할 수 있음 (DB 부하↑)
✔ 3) FlatFileItemReader (CSV/파일)
외부에서 전달된 파일을 읽어들일 때 사용.
@Bean
public FlatFileItemReader<CsvUser> csvReader() {
return new FlatFileItemReaderBuilder<CsvUser>()
.name("csvReader")
.resource(new ClassPathResource("users.csv"))
.delimited()
.names("id", "name", "email")
.targetType(CsvUser.class)
.build();
}
2. ItemProcessor — 데이터를 변환하는 단계
Processor는 말 그대로 데이터 가공 로직을 넣는 위치입니다. DB → 모델 매핑, 단순 계산, 문자열 변환, 유효성 체크 등 로직을 넣을 수 있습니다.
✔ 기본 Processor 예시
@Bean
public ItemProcessor<MailEntity, MailMessage> mailProcessor() {
return mailEntity -> {
MailMessage msg = new MailMessage();
msg.setTo(mailEntity.getEmail());
msg.setSubject(mailEntity.getSubject());
msg.setBody(mailEntity.getContent());
return msg;
};
}
✔ Processor 실무 활용 패턴
- null 반환 → Writer에서 제외됨 (필터링 기능)
- 외부 API 결과를 조합해 변환
- 암호화/복호화 처리
- 유효성 체크 후 불량 데이터 로그 저장
실무 팁: Processor에 비즈니스 로직을 몰아넣지 말고, 서비스/헬퍼 클래스로 분리하는 것이 유지보수에 좋음
3. ItemWriter — 데이터를 저장하거나 외부로 보내는 단계
Writer는 “최종 목적지” 역할을 합니다. DB 저장뿐 아니라 Kafka, S3, 외부 API 호출 등을 Writer에서 처리할 수 있습니다.
✔ 1) JpaItemWriter — DB 저장
@Bean
public JpaItemWriter<UserHistory> userHistoryWriter() {
return new JpaItemWriterBuilder<UserHistory>()
.entityManagerFactory(entityManagerFactory)
.build();
}
✔ 2) Kafka Writer — 메시지 큐로 데이터 전송
Kakao/메일 알림 발송 자동화할 때 사용했던 방식.
@Bean
public ItemWriter<MailMessage> kafkaMailWriter() {
return items -> items.forEach(kafkaProducer::send);
}
Writer는 대량으로 메시지를 쏘는 경우도 많기 때문에 “Chunk 단위로 묶어서 처리”하는 게 매우 중요합니다.
✔ 3) Custom Writer — 외부 API 전송
@Bean
public ItemWriter<OrderResult> apiWriter() {
return items -> {
for (OrderResult item : items) {
externalApi.sendOrder(item);
}
};
}
Writer는 Chunk(예: 100건) 단위로 실행되므로 실패 시 해당 Chunk만 재시도 가능 → 안정적
4. 실무 배치 구조 예시
@Bean
public Step sendMailStep() {
return stepBuilderFactory.get("sendMailStep")
.<MailEntity, MailMessage>chunk(100)
.reader(waitingMailReader())
.processor(mailProcessor())
.writer(kafkaMailWriter())
.build();
}
- Reader: 발송 대기 메일 조회
- Processor: 템플릿 변환 + 데이터 매핑
- Writer: Kafka 발송
이 구조는 실무에서 가장 많이 사용되는 형태입니다.
5. 최종 정리 — 실무 기준 선택 가이드
- Reader: 데이터 소스(DB / 파일 / API)에 따라 선택
- Processor: 가공, 필터링, 유효성 체크
- Writer: 저장 또는 외부 발송
특히 “대량 처리”를 다루는 기업에서는 Reader 성능 + Writer 안정성이 가장 중요한 포인트임.
'Backend > Batch' 카테고리의 다른 글
| [Batch] 6. 스케줄링 & 운영 전략 — Spring Scheduler · Crontab · Quartz · EventBridge 비교 (0) | 2025.11.13 |
|---|---|
| [Batch] 5. Spring Batch — Skip / Retry / Listener로 장애 내성 높은 배치 만들기 (0) | 2025.11.13 |
| [Batch] 3. Spring Batch — Chunk vs Tasklet (0) | 2025.11.13 |
| [Batch] 2. Batch 환경 구성 — Job / Step / Repository (0) | 2025.11.13 |
| [Batch] 1. Spring Batch 의 구조 및 개념 (0) | 2025.11.13 |