프로젝트를 진행 하면서 특정한 조건에 따라서 인스턴스 생성, 쿠폰 지급을 할 수 있도록 대용량 데이터를 일괄적 으로 처리 하는 Spring Batch을
사용하게 되었는데 Spring Batch 가 어떤 유형으로 되어있는지,상황별로 어느걸 사용해야하는지의 대한 비교를 해보겠습니다.
(혹시 읽으시면서 비정확한 부분이나 첨언 해주실 부분 있으면 말씀 해주세요.)
(1) Spring Batch 사용 이점:
1-1 자동화 및 일관성 유지
1-2 확장성 및 안정성
1-3 모니터링 및 관리
(2) 배치 형식:
이해를 돕기 위해서 현재는 비즈니스로직 이 변경 되긴 하였지만
프로젝트의 내부 플로우를 정리한 그림을 가져왔습니다.
Job->Step(Step 내부 컴포넌트 실행) 순으로 진행이 되는데,
한개의 Job에 여러개의 Step을 정의해서 사용 할 수 있습니다.
조합 방법 | 적합한 사용 상황 | 장점 | 단점 |
---|---|---|---|
CommandLineRunner + JobLauncher | 애플리케이션 시작 시 특정 조건을 만족하는 배치 작업을 실행해야 할 때 | 애플리케이션 시작과 동시에 배치 작업 실행 | |
Job 파라미터 전달 가능 Job 실행 종료 후 콜백 처리 가능 | 직접 실행 시점 제어 불가스케쥴링 옵션 부재 | ||
@Scheduled + JobLauncher | 정해진 시간이나 주기에 따라 파라미터를 동적으로 전달하며 배치 작업을 실행해야 할 때 | 주기적 실행 가능 정확한 시간에 작업 실행 가능 | |
Job 파라미터 전달 가능 Job 실행 종료 후 콜백 처리 가능 | 복잡한 스케쥴링 요구사항에 한계 | ||
스프링 컨텍스트 필요 |
기능 | JobLauncher | JobOperator |
---|---|---|
기능 | 기본 Job 실행 | 고급 Job 실행 제어 |
실행 스타일 | 동기 | 비동기 |
Job 제어 | 제한적(Job 및 JobParameters 사용 시작) | 직접 제어(시작, 중지, 재시작, 취소) |
사용 사례 | 간단한 예약된 Job, 외부 트리거 | 복잡한 워크플로, 실시간 모니터링, 고급 관리 |
일반적으로 배치작업을 실행하고자 하는 요구 조건에 따라
CommandLineRunner + Joblauncher 혹은 @Scehduled +JobLauncher 와
JobConfig 파일을 같이 작성할 것인지, Batch4.0부터 지원하는 JobLauncher와
Config 를 동시에 정의하고 조금 더 Job 의 제어를 세밀하게 관리할필요가 있다면
공식 문서를 이용하여 필요시에 사용 하면 좋을 것 같습니다.
JobConfig에서 어떤 방식으로 Job 과 Step 을 정의 하고 어떠한 컴포넌트를 쓰는지 비교 해보겠습니다.
@Bean
fun eventJob(jobRepository: JobRepository,deleteStep:Step, eventStep: Step): Job {
return JobBuilder("premiumDealJob", jobRepository)
.start(deleteStep)//특가삭제
.next(eventStep)//apply-> 특가
.build()
}
이런식으로 Jobbuilder 안에 정의한 Step 을 의도한 순서대로 작성하면 됩니다.
(3) 컴포넌트 유형 :
3-1 Tasklet: 간단하고 단일한 작업 수행
3-2 ItemOriented:
(4) ItemOriented vs Tasklet 비교
구분 | ItemOriented | Tasklet |
---|---|---|
특징 | 아이템 단위 데이터 처리 | 간단하고 단일한 작업 |
장점 | 다양한 데이터 형식 및 처리 로직 지원 | 코드 작성 간편 |
단점 | 성능 저하 가능성 | 복잡한 작업 수행 어려움 |
적용 분야 | 데이터 마이그레이션, ETL, 데이터 분석 | 파일 복사, 데이터베이스 테이블 초기화 |
Batch 트러블 슈팅
java.lang.NoSuchMethodException: jdk.proxy2.$Proxy190.findByApplicationDateBetween(java.time.LocalDateTime,java.time.LocalDateTime,org.springframework.data.domain.PageRequest)