๊ฐ์ข ๊ณต์ฐ์ ์๋งคํ๊ณ ์๋ฆผ์ ๋ฐ์ ์ ์๋ ์๋น์ค๋ฅผ ๋ง๋ค๊ณ ์์๋ค. ์ฌ๊ธฐ์ ์๋งคํ ๊ณต์ฐ์ ์์ ํ๋ฃจ ์ ํ์๋ค์๊ฒ ์ผ๊ด์ ์ผ๋ก ์๋ฆผ์ ๋ณด๋ด์ฃผ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ค.
์นด์นด์คํก ์๋ฆผ์ ๋ณด๋ด๋ ค ํ์ง๋ง ์ฌ์ ์ ๋ฒํธ๊ฐ ์์ด์ผ ํ๋ค๊ณ ํด์ ์์ฌ์ด๋ฐ๋ก sms ์ ์ก์ผ๋ก ๋์ฒดํ๋ค.
sms push ์๋ฆผ์ naver cloud์์ ์ ๊ณตํ๋ sens๋ฅผ ์ฌ์ฉํ๋ค. coolsms๊ฐ ์ ์ผ ๋ณดํธ์ ์ผ๋ก ๋ง์ด ์ฐ์ด๋ ๊ฒ ๊ฐ๋๋ฐ ํจ์ฌ ์ ๋ ดํ๊ฒ ์ฌ์ฉํ ์ ์์๋ค. (์ง๊ธ์ ์ฌ์ ์๋ง ๊ฐ๋ฅํ๋๋ก ๋ค์ด๋ฒ์์ ๋ง์.. ์คํจ๋ฌธ์ )
์๋ฌดํผ ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ค๊ณ ์ด๊ฒ์ ๊ฒ ์ฐพ์๋ณด๋ค ์ค์ผ์ค๋ฌ์ ๋ฐฐ์น์ ๋ํด ์๊ฒ ๋์๊ณ ํ์ฌ ์งํ์ค์ธ ํ๋ก์ ํธ์ ์คํ๋ง ๋ฐฐ์น๋ฅผ ์ ์ฉ์ํค๊ธฐ๋ก ํ๋ค.
์คํ๋ง ๋ฐฐ์น๋ ์ด๋ค ์์ ์ ์ฐ์ผ๊น?
์์ฝ ์๊ฐ์ ๊ด๊ณณ์ด ๋ฉ์์ง ๋ฐ์ก, ๊ฒฐ์ ์ ์ฐ ์์ , ์ด์์ ์ํด ํ์ํ ํต๊ณ ๋ฐ์ดํฐ ๊ตฌ์ถ, ๋๋ ๋ฐ์ดํฐ๋ฅผ ํ์๋ก ํ๋ ๋ชจ๋ธ ํ์ต ์์ ๋ฑ ํน์ ์๊ฐ์ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํด์ผ ํ๋ ๊ฒฝ์ฐ์ ๋ง์ด ์ฐ์๋ค.
์คํ๋ง ๋ฐฐ์น๋ ์ค์ผ์ค๋ฌ์ ํผ๋ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์๋ฐ ์ ํ ๋ค๋ฅธ ๊ฐ๋ ์ด๋ค. ๋์ ์ฐจ์ด๋ ๋ค๋ฅธ ๊ธ์์ ๋ค๋ฃจ๊ฒ ๋ค.
https://dgjinsu.tistory.com/20
Spring batch ์ฉ์ด ์ ๋ฆฌ
- Job
- ๋ฐฐ์น์ฒ๋ฆฌ ๊ณผ์ ์ ํ๋์ ๋จ์๋ก ๋ง๋ค์ด ๋์ ๊ฐ์ฒด.
- ์ ์ฒด ๋ฐฐ์น ํ๋ก์ธ์ค๋ฅผ ์บก์ํํ๋ ์ํฐํฐ, ์คํ์ํฌ ์์ .
- JobInstance
- ๋ ผ๋ฆฌ์ ์ธ Job ์ ์คํ์ ๋จ์.
- Job ์ ์คํ์ํค๋ฉด ํ๋์ JobInstance ๊ฐ ์์ฑ.
- ์๋ฅผ๋ค์ด, 1์ 1์ผ ์คํ, 1์ 2์ผ ์คํ์ ํ๊ฒ ๋๋ฉด ๊ฐ๊ฐ์ JobInstance ๊ฐ ์์ฑ๋๊ณ , ๋ง์ฝ 1์ 1์ผ์ ์คํํ JobInstance ๊ฐ ์คํจํ์ฌ ์ดํ ์ฌ์คํ ํ๋๋ผ๋ ์ด JobInstance ๋ 1์ 1์ผ์ ๋ํ ๋ฐ์ดํฐ๋ง ์ฒ๋ฆฌ.
- JobParameters
- Job ์ ์คํํ๋๋ฐ ์ฌ์ฉํ๋ ํ๋ผ๋ฏธํฐ์ ์งํฉ์ผ๋ก, Job ์ด ์คํ๋๋ ๋์์ JobInstance ์ ์๋ณ ์ธ์๋ ๋งค๊ฐ๋ณ์ ์ญํ ๋ก ์ฌ์ฉ.
- JobExecution
- JobInstance ์์ ์คํ ์๋์ ๋ํ ๊ฐ์ฒด.
- ์คํ์ ๋ํ JobExecution ์ ๊ฐ๋ณ๋ก ์์ฑ.
- JobInstance ์คํ์ ๋ํ ์ํ, ์์์๊ฐ, ์ข
๋ฃ์๊ฐ, ์์ฑ์๊ฐ ๋ฑ์ ์ ๋ณด๋ฅผ ๊ฐ์ง.
- ์๋ฅผ๋ค์ด, 1์ 1์ผ์ ์คํํ JobInstance ๊ฐ ์คํจํ์ฌ ์ฌ์คํ์ ํ์ฌ๋ ๋์ผํ JobInstance ๋ฅผ ์คํ์ํค์ง๋ง ์ด 2๋ฒ์ ์คํ์ ๋ํ Job Execution ์ ๊ฐ๋ณ๋ก ์์ฑ.
- Step
- Job ์ ๋ฐฐ์น์ฒ๋ฆฌ๋ฅผ ์ ์ํ๊ณ ์์ฐจ์ ์ธ ๋จ๊ณ๋ฅผ ์บก์ํ.
- Job ์ ์ต์ 1๊ฐ ์ด์์ Step ์ ๊ฐ์ ธ์ผ ํ๊ณ , Job ์ ์ค์ ์ผ๊ด ์ฒ๋ฆฌ๋ฅผ ์ ์ดํ๋ ๋ชจ๋ ์ ๋ณด๋ฅผ ํฌํจ.
- Step ์ ๋ด์ฉ์ ๊ฐ๋ฐ์์ ์ ํ์ ๋ฐ๋ผ ๊ตฌ์ฑ.
- Tasklet ์ฒ๋ฆฌ ๋ฐฉ์๊ณผ Chunk ์งํฅ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ง์
- Tasklet
- ๋จ์ํ ๋ฐ์ดํฐ ํ๋ก์ธ์ค ์ฒ๋ฆฌ์ ์ ํฉํ ๋ชจ๋ธ.
- SQL 1ํ ๋ช ๋ น ๋ฑ ๋จ์ํ๊ฑฐ๋, ์์ ํ๋ก์ธ์ค์ ํ์คํ๊ฐ ์ด๋ ค์ด ๋ณต์กํ ๊ฒฝ์ฐ์ Custom ์์ ์์ฑ์ ์ํด ์ฌ์ฉ.
- Chunk
- ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌด ๋ง๊ณ , ํฐ ๋ฐ์ดํฐ ๋ค์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๋๋ฐ ์ ํฉ.
- ์ผ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ผ๊ด์ ์ผ๋ก read / process / write ํ๋ก์ธ์ค ํ๋ฆ์ ๋ฐ๋ผ ํ์คํํ์ฌ ์์ ์ ๊ตฌํ.
- ํ๋์ Transaction ์์์ ์ฒ๋ฆฌํ Item ์ ๋ฉ์ด๋ฆฌ.
- chunk size ๊ฐ 10์ด๋ผ๋ฉด ํ๋์ transaction ์์์ 10๊ฐ์ item ์ ๋ํด ์ฒ๋ฆฌ ํ๊ณ commit.
- Tasklet
- StepExecution
- JobExceution ๊ณผ ๋์ผํ๊ฒ Step ์คํ ์๋์ ๋ํ ๊ฐ์ฒด.
- ์ค์ ์์์ด ๋ ๋ ์์ฑ.
- ์์ ์๊ฐ, ์ข
๋ฃ ์๊ฐ, ์ํ, ์ข
๋ฃ ์ํ, Commit Count, ItemCount, Skip Count ๋ฑ ์คํ์ ๋ํ ๋ค์ํ ์ ๋ณด๋ฅผ ๊ฐ์ง.
- ์๋ฅผ๋ค์ด, Job ์ด ์ฌ๋ฌ ๋จ๊ณ์ Step ์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ ๊ฒฝ์ฐ ์ด์ ๋จ๊ณ์ Step ์ด ์คํจํ๊ฒ ๋๋ฉด ๋ค์ ๋จ๊ณ๊ฐ ์คํ๋์ง ์์์ผ๋ก ์คํจ ์ดํ StepExecution ์ ์์ฑ๋์ง ์์.
- ExecutionContext
- Job ์์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ ์ ์๋ ๋ฐ์ดํฐ ์ ์ฅ์.
- Spring Batch ์์๋ JobExecutionContext, StepExecutionContext ๋ฅผ ์ง์ํ๋ค.
- JobExecutionContext
- Commit ์์ ์ ์ ์ฅ
- StepExecutionContext
- ์คํ ์ฌ์ด์ ์ ์ฅ ExecutionContext ๋ฅผ ํตํด Step ๊ฐ Data ๊ณต์ ๊ฐ ๊ฐ๋ฅํ๊ณ , Job ์คํจ์ ExecutionContext ๋ฅผ ํตํด ๋ง์ง๋ง ์คํ ๊ฐ์ ์ฌ๊ตฌ์ฑ ํ ์ ์์.
- JobExecutionContext
- JobRepository
- ์ํ๋๋ Job ์ ๋ชจ๋ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ ์ ์ฅ์.
- ์ด๋ ํ Job ์ด ์ธ์ ์ํ๋์๊ณ , ์ธ์ ์ข ๋ฃํ๊ณ , ๋ช ๋ฒ ์คํ๋์๊ณ , ์คํ์ ๋ํ ๊ฒฐ๊ณผ๊ฐ ์ด๋ค์ง ๋ฑ์ Batch ์ํ๊ณผ ๊ณผ๋ จ๋ ๋ชจ๋ Meta Data ๊ฐ ์ ์ฅ.
- Job ์ด ์คํ๋๊ฒ ๋๋ฉด JobRepository ์ JobExecution ๊ณผ StepExecution ์ ์์ฑํ๊ณ , JobRepository ์์ Execution ์ ๋ณด๋ค์ ์ ์ฅํ๊ณ ์กฐํํ๋ฉฐ ์ฌ์ฉ.
Meta-Table Schema
- Spring Batch ์์๋ 6๊ฐ์ Meta Table ๊ณผ 3๊ฐ์ Sequence Table ์ด ์กด์ฌํ๋ค.
- ์์ ์ด ์ํ๋ ๋ ๋ง๋ค ์คํ๋ Job ์ ๋ํ ๋ค์ํ ์ ๋ณด๋ค์ ์ ์ฅํ์ฌ ๊ด๋ฆฌํ๋ค.
- ์ผ๋ฐ์ ์ผ๋ก๋ Meta Table ์ด ์์ผ๋ฉด Spring Batch ๋ฅผ ์คํํ ์ ์๋ค.
Spring Batch 5 ๋ณ๊ฒฝ์
Spring Boot 3(=Spring Framework 6)๋ถํฐ Spring Batch 5 ๋ฒ์ ์ ์ฌ์ฉํ๊ฒ ์ ๋ฐ์ดํธ ๋์๋ค. Batch 5์ ๋ณ๊ฒฝ์ ์ด ๋ง์ด ์๊ฒจ ๊ธฐ์กด์ 4๋ฒ์ ๊ณผ ๋ค๋ฅธ ๋ถ๋ถ์ด ๋ง์ด ์๊ฒผ๋ค. ์ฒ์ ๋ฐฐ์น๋ฅผ ๊ตฌํํด๋ณด๋๋ฐ Spring Batch5 ๋ฒ์ ์ ์ฐธ๊ณ ํ ์๋ฃ๊ฐ ๋ง์ด ์์ด ๊ณ ์ํ๋ค.
๋ด๊ฐ ๊ตฌํํ๋ฉด์ ๋ฐ๊ฒฌํ ๋ณ๊ฒฝ์ ์ ์๋์ ๊ฐ๋ค.
1. JobBuilderFactory, StepBuilderFactory deprecated
// Sample with v4
@Configuration
@EnableBatchProcessing
public class MyJobConfig {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Bean
public Job myJob(Step step) {
return this.jobBuilderFactory.get("myJob")
.start(step)
.build();
}
}
// Sample with v5
@Configuration
@EnableBatchProcessing
public class MyJobConfig {
@Bean
public Job myJob(JobRepository jobRepository, Step step) {
return new JobBuilder("myJob", jobRepository)
.start(step)
.build();
}
}
2. JobRepository, TransactionManager ๋ช ์์ ์ผ๋ก ๋ณ๊ฒฝ
๋ด๋ถ์ ์ผ๋ก ํ์ํ ๊ฐ์ฒด๋ฅผ ๋ช ์์ ์ผ๋ก ํ์ํด ์ฃผ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝ๋์๋ค
// Sample with v4
@Configuration
@EnableBatchProcessing
public class MyStepConfig {
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean
public Step myStep() {
return this.stepBuilderFactory.get("myStep")
.tasklet(..) // or .chunk()
.build();
}
}
// Sample with v5
@Configuration
@EnableBatchProcessing
public class MyStepConfig {
@Bean
public Tasklet myTasklet() {
return new MyTasklet();
}
@Bean
public Step myStep(JobRepository jobRepository, Tasklet myTasklet, PlatformTransactionManager transactionManager) {
return new StepBuilder("myStep", jobRepository)
.tasklet(myTasklet, transactionManager) // or .chunk(chunkSize, transactionManager)
.build();
}
}
3. JobParameter ์ง์ ๋ฒ์ ํ๋
v4 ์์์ ์คํ๋ง ๋ฐฐ์น๋ Job parameter ๋ก Long, String, Date, Double ๋ง ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
v5 ์์๋ ์ฌ๊ธฐ์ ๋ํด converter ๋ฅผ ์ง์ ๊ตฌํํ๋ ๊ฒ์ผ๋ก ๋ชจ๋ ์ข ๋ฅ์ ํ์ ์ JobParameter ๋ก ์ฌ์ฉํ ์ ์๋๋ก ๊ฐ์ ๋๋ค.
๋ณธ๊ฒฉ์ ์ผ๋ก ์๋ฆผ ์ผ๊ด์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฐํด๋ณด์
SmsJobConfiguration
@Slf4j
@Configuration
@RequiredArgsConstructor
public class SmsJobConfiguration {
private final SmsService smsService;
private final EntityManagerFactory entityManagerFactory;
@Bean @Qualifier(value = "smsSendJob")
public Job smsSendJob(JobRepository jobRepository, Step smsSendStep) {
return new JobBuilder("smsSendJob", jobRepository)
.start(smsSendStep)
.build();
}
@Bean
public Step smsSendStep(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager){
return new StepBuilder("smsSendStep", jobRepository)
.<Ticketing, Ticketing>chunk(100, platformTransactionManager)
.reader(itemReader())
.processor(itemProcessor())
.writer(itemWriter())
.build();
}
@Bean
public ItemReader<Ticketing> itemReader() {
LocalDateTime tomorrow = LocalDateTime.now().plusDays(1);
// DateTimeFormatter๋ฅผ ์ฌ์ฉํ์ฌ ํฌ๋งท ์ง์
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 00:00๋ก ์ค์
LocalDateTime tomorrowStart = tomorrow.withHour(0).withMinute(0).withSecond(0).withNano(0);
// 23:59๋ก ์ค์
LocalDateTime tomorrowEnd = tomorrow.withHour(23).withMinute(59);
return new JpaCursorItemReaderBuilder<Ticketing>()
.name("itemReader")
.entityManagerFactory(entityManagerFactory)
.queryString("select t from Ticketing t join fetch t.member m where t.event.startEvent between :tomorrowStart and :tomorrowEnd")
.parameterValues(Map.of("tomorrowStart", tomorrowStart, "tomorrowEnd", tomorrowEnd))
.build();
}
@Bean
public ItemProcessor<Ticketing, Ticketing> itemProcessor() {
return ticketing -> {
Member member = ticketing.getMember();
String eventName = ticketing.getEvent().getName();
LocalDateTime startEvent = ticketing.getEvent().getStartEvent();
int month = startEvent.getMonthValue(); // ์(month) ์ถ์ถ
int day = startEvent.getDayOfMonth(); // ์ผ(day) ์ถ์ถ
int hour = startEvent.getHour(); // ์(hour) ์ถ์ถ
int minute = startEvent.getMinute(); // ๋ถ(minute) ์ถ์ถ
String content = month + "์" + day + "์ผ " + hour + "์" + minute + "๋ถ์ " + eventName + "์ด ์๋งค๋์ด ์์ต๋๋ค. ์๊ฐ์ ๋ง์ถฐ ๋ฐฉ๋ฌธํด์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.";
log.info(member.getPhone() + " ํด๋น ์ ํ๋ฒํธ๋ก [" + content + "] ๋ฌธ์ ๋ฐ์ก๋์์ต๋๋ค.");
smsService.sendSms(member.getPhone(), content);
return ticketing;
};
}
@Bean
public JpaItemWriter<Ticketing> itemWriter() {
return new JpaItemWriterBuilder<Ticketing>()
.entityManagerFactory(entityManagerFactory)
.build();
}
}
์ ์ฒด ์ฝ๋๋ ์์ ๊ฐ๋ค.
ํ๋์ฉ ๋ฏ์ด์ ๋ณด๋ฉด
- Job์ ๋น์ผ๋ก ๋ฑ๋กํ๋ฉฐ Step์ Job์ ๋ฑ๋ก
@Bean @Qualifier(value = "smsSendJob")
public Job smsSendJob(JobRepository jobRepository, Step smsSendStep) {
return new JobBuilder("smsSendJob", jobRepository)
.start(smsSendStep)
.build();
}
- Step ์ ์ (reader, processor, writer ์ธํ )
@Bean
public Step smsSendStep(JobRepository jobRepository, PlatformTransactionManager platformTransactionManager){
return new StepBuilder("smsSendStep", jobRepository)
.<Ticketing, Ticketing>chunk(5, platformTransactionManager)
.reader(itemReader())
.processor(itemProcessor())
.writer(itemWriter())
.build();
}
- reader
- JpaCursorItemReaderBuilder๋ฅผ ์ฌ์ฉํ์ฌ ์กฐ๊ฑด์ ๋ง๋ item ์กฐํ
@Bean
public ItemReader<Ticketing> itemReader() {
LocalDateTime tomorrow = LocalDateTime.now().plusDays(1);
// DateTimeFormatter๋ฅผ ์ฌ์ฉํ์ฌ ํฌ๋งท ์ง์
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 00:00๋ก ์ค์
LocalDateTime tomorrowStart = tomorrow.withHour(0).withMinute(0).withSecond(0).withNano(0);
// 23:59๋ก ์ค์
LocalDateTime tomorrowEnd = tomorrow.withHour(23).withMinute(59);
return new JpaCursorItemReaderBuilder<Ticketing>()
.name("itemReader")
.entityManagerFactory(entityManagerFactory)
.queryString("select t from Ticketing t join fetch t.member m where t.event.startEvent between :tomorrowStart and :tomorrowEnd")
.parameterValues(Map.of("tomorrowStart", tomorrowStart, "tomorrowEnd", tomorrowEnd))
.build();
}
- processor
- reader์์ ์ฝ์ด๋๋ฆฐ item์ ํ์ฉํด ํ์ํ ๋ก์ง ์ํ.
- ๋ฌธ์๋ฅผ ๋ณด๋ด๋ ๋ก์ง์ด ์ฌ๊ธฐ์ ๋ค์ด๊ฐ๋ค
@Bean
public ItemProcessor<Ticketing, Ticketing> itemProcessor() {
return ticketing -> {
Member member = ticketing.getMember();
String eventName = ticketing.getEvent().getName();
LocalDateTime startEvent = ticketing.getEvent().getStartEvent();
int month = startEvent.getMonthValue(); // ์(month) ์ถ์ถ
int day = startEvent.getDayOfMonth(); // ์ผ(day) ์ถ์ถ
int hour = startEvent.getHour(); // ์(hour) ์ถ์ถ
int minute = startEvent.getMinute(); // ๋ถ(minute) ์ถ์ถ
String content = month + "์" + day + "์ผ " + hour + "์" + minute + "๋ถ์ " + eventName + "์ด ์๋งค๋์ด ์์ต๋๋ค. ์๊ฐ์ ๋ง์ถฐ ๋ฐฉ๋ฌธํด์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.";
log.info(member.getPhone() + " ํด๋น ์ ํ๋ฒํธ๋ก [" + content + "] ๋ฌธ์ ๋ฐ์ก๋์์ต๋๋ค.");
smsService.sendSms(member.getPhone(), content);
return ticketing;
};
}
- writer
- ๋ณ๊ฒฝ๋ item๋ค์ ๋ค์ ์ ์ฅํ๋ ๋ถ๋ถ์ด๋ค.
- ๋๋ item๋ค์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ๋ก ์์ ํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ ์ฅํ ๊ฑด ์๋ค.
@Bean
public JpaItemWriter<Ticketing> itemWriter() {
return new JpaItemWriterBuilder<Ticketing>()
.entityManagerFactory(entityManagerFactory)
.build();
}
์ด๋ ๊ฒ ์์ฑํ Batch ๋ก์ง์ Sheduler์ ๋ฑ๋กํ์ฌ ์ํ๋ ์๊ฐ๋์ ์คํํด์ฃผ๋ฉด ๋๋ค.
ScheduledJob
@Scheduled(cron = "0 0 20 * * *", zone = "Asia/Seoul") // ์ด ๋ถ ์ ์ผ ์ ์์ผ
public void sendReminderMessages() {
Map<String, JobParameter<?>> confMap = new HashMap<>();
confMap.put("time", new JobParameter(System.currentTimeMillis(), Long.class));
JobParameters jobParameters = new JobParameters(confMap);
try {
jobLauncher.run(SmsSendJob, jobParameters);
jobLauncher.run(alarmJob, jobParameters);
} catch (JobExecutionAlreadyRunningException e) {
throw new RuntimeException(e);
} catch (JobRestartException e) {
throw new RuntimeException(e);
} catch (JobInstanceAlreadyCompleteException e) {
throw new RuntimeException(e);
} catch (JobParametersInvalidException e) {
throw new RuntimeException(e);
}
log.info("์ค์ผ์ค๋ฌ ์คํ");
}
JobParameter๋ฅผ ์ฌ์ฉํ๋ ์ด์ ์ค ํ๋๋ Spring Batch๊ฐ ๊ฐ ์์ ์ ๊ณ ์ ํ๊ฒ ์๋ณํ ์ ์๋๋ก ํ๊ธฐ ์ํด์์ด๋ค.
Spring Batch๋ ๊ฐ ์์ ์คํ์ ๋ํ ์ ์ผํ ํค๋ฅผ ๊ฐ์ ธ์ผ ํ๋ฉฐ, ์ด๋ฌํ ํค๋ JobParameters์ ์ํด ์ ๊ณต๋๋ค.