배치가 뭐길래 : Spring Batch 5
배치
Spring Batch는 스케쥴러를 지원하지 않음 (공식 웹사이트 첨부 필요)
Spring Batch의 목적은 대용량 처리
스케쥴러 : 일정 주기로 실행하는 것
Quatz는 뭔지?
Job(배치 할 것)은 여러개의 Step으로 구성됨
Step은 ItemReader, ItemProcesor, ItemWriter로 구성됨
Job을 실현하기 위해 JobLauncher가 필요
모두 JobRepository 통해서 데이터랑 통신하는듯?
Job : Job 이름 정의 가능, Step 정의와 순서, Job 재사용 가능성 정의
JobInstance :논리적으로 Job을 실행, (어제 실행한 Job인지, 오늘 실행한 Job인지.. JobParameters를 이용해서 구분)
JobExecution : Job을 실행하는 단일 시도. 실패했던 JobInstance에 대한 새로운 실행을 하면 새로운 JobExecution이 생성
- BatchStatus : 실행 상태 (실행중이면 started, 실패하면 failed, 성공하면 completed)
- ExitStatus : 실행 결과. ExitCode 등을 포함
Step : Job은 하나 이상의 Step으로 구성됨
배치 작업의 독립적이고 순차적인 단계를 캡슐화하는 도메인 객체
모든 Job은 이상의 Step으로 이뤄짐
Step의 내용은 개발자의 재량
StepExecution
- Status 실행 상태
- ExitStatus 실행의 결과
Read Count, WriteCounte, CommitCount, RollbackCount, FilterCount등의 정보를 담고 있음
JobRepository : Job, Step 구현을 위한 CRUD 작업을 제공
JobLancher : Jobt을 시작하기 위한 간단한 인터페이스
메타데이터를 그대로 사용할 수 있음. 비즈니스 로직에 집중하게 해줌
아이템 : 작업에 사용하는 데이터 (예를 들면 DB의 한 row)
ItemReader : Step에서 한 항목씩 검색한다. 모든 항목이 소진된 경우 null을 반환한다. (db 조회)
ItemWriter : 여러 출력 항목을 나타냄 (db에 저장 등) (마지막에)
ItemProcessor : 비즈니스 처리르 담당. 항목이 유효하지 않으면 null을 반환
프레임워크 사용하므로 JobLauncer나 JobRepo는 구현 안해도 됨
Tasklet
- 익명 Tasklet
- chunk
chunk : 각 커밋 사이에 처리되 row의 수
성공 시 cunk 만큼 커밋, 실패 시 chunk 만큼 롤백
write에서는 chunk를 한버에 write
ItemReader
- cursor, paging
cursor : 1 connection에 1 item 가져옴
paging : 1 connection에 N개의 Item 가져옴
page size는 chunk size와 동일하게 설정하는 것이 좋음
page size > chunk size면 하나의 트랜잭션 처리를 위해 paging을 여러번 해야됨
ItemProcessor (Optional)
비즈니스 코드를 담는 곳
데이터 실패 시 null을 반환 (?)
실패 여부에 따라 조건문으로 step을 실행할 수 있음
테스트 코드 작성이 필요. QA 하기 어려움. 통합테스트도 필요, 각각의 단위 테스트도 필요
관리 도구
: Cron (리눅스 작업 스케쥴러)
: Quartz + Admin (스케쥴러 프레임워크 + 관리자 페이지 구현)
: CI Tool (ex. Jenkins)
젠킨스 장점 : 실행 이력 / 로그 관리에도 좋음
✅ Spring Batch ItemReader에서 로그가 안 찍히는 이유 정리
🔹 문제 상황
ItemReader 설정 코드에 아래처럼 로그를 찍었지만, 로그가 한 번만 출력되고 이후에는 보이지 않음:
🔹 원인
- 이 로그는 ItemReader 빈 생성 시점에만 실행됨.
- 실제로 read() 메서드가 실행될 때 찍히는 로그가 아님.
- 따라서 Step 실행 중에 Reader가 동작하는지 확인할 수 없음.
✅ 왜 그런가?
@Bean 메서드 | Spring이 어플리케이션 시작 시 한 번만 실행해서 빈을 생성함 |
log.debug(...) | 위 메서드 안에 있으면 빈 생성 시점에만 실행됨 |
read() 메서드 | Step 실행 중에 호출되지만, JpaCursorItemReader 내부이므로 우리가 로그를 못 넣음 |
✅ 해결 방법
1. read() 호출 시점에 로그를 보고 싶다면
JpaCursorItemReader를 감싸는 커스텀 ItemReader를 만들어서 read()를 직접 override해야 함:
✅ 핵심 요약
로그가 왜 안 찍혀? | @Bean 메서드 안에서만 찍으면, 빈 생성 시점에만 로그가 출력됨 |
실제 Step에서 Reader가 호출될 때 로그 찍으려면? | read() 메서드를 오버라이드해서 직접 로그 넣어야 함 |
JpaCursorItemReader는 왜 로그 못 넣어? | 내부 구현에 접근할 수 없고, 우리가 read()를 override하지 않았기 때문 |
레퍼런스
https://www.youtube.com/watch?v=1xJU8HfBREY