๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Spring/Spring Batch

Spring Batch (5) Step, StepExecution

by ์ฃผ๋ฐœ2 2022. 11. 3.
๋ฐ˜์‘ํ˜•

๐Ÿ“Ž Step, StepExecution

์ง€๋‚œ ์‹œ๊ฐ„์—๋Š” Job, JobInstance, JobParameter, JobExecution์˜ ๊ฐœ๋…์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” Job์„ ๊ตฌ์„ฑํ•˜๋Š” ์ž‘์—…์˜ ๋‹จ์œ„์ธ Step, StepExecution ๊ฐ์ฒด์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

(์˜ˆ์ œ ์ฝ”๋“œ๋Š” GitHub์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜ƒ)

 

 

๐Ÿ“Œ ํ•ด๋‹น ํฌ์ŠคํŒ…์˜ ๋ชฉํ‘œ

  • Spring Batch Step
  • Spring Batch StepExecution

 

 

 

๐Ÿ“Œ Step

https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html#step

๊ธฐ๋ณธ ๊ฐœ๋…

  • Step์€ ๋…๋ฆฝ์ ์ด๊ณ  ์ˆœ์ฐจ์ ์ธ Batch Job์„ ์บก์Šํ™”ํ•˜๋Š” ๋„๋ฉ”์ธ ๊ฐ์ฒด
  • Step์—๋Š” ์‹ค์ œ Batch ์ฒ˜๋ฆฌ๋ฅผ ์ง„ํ–‰ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋“ค์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Œ
  • Step์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์›ํ•˜๋Š” ๋งŒํผ ๊ฐ„๋‹จํ•˜๊ฑฐ๋‚˜ ๋ณต์žกํ•  ์ˆ˜ ์žˆ์Œ
  • ๋ชจ๋“  Job์€ ํ•˜๋‚˜ ์ด์ƒ์˜ Step์œผ๋กœ ๊ตฌ์„ฑ๋จ

 

๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด

  • TaskletStep : ๊ฐ€์žฅ ๊ธฐ๋ณธ์ด ๋˜๋Š” ํด๋ž˜์Šค๋กœ Tasklet ํƒ€์ž…์˜ ๊ตฌํ˜„์ฒด๋“ค์„ ์ œ์–ด
  • PartitionStep : ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ๋ฐฉ์‹์œผ๋กœ Step์„ ์—ฌ๋Ÿฌ ๊ฐœ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์‹คํ–‰
  • JobStep : Step ๋‚ด์—์„œ Job์„ ์‹คํ–‰ํ•˜๋„๋ก ํ•จ
  • FlowStep : Step ๋‚ด์—์„œ Flow๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•จ

 

๊ตฌํ˜„์ฒด์— ๋”ฐ๋ฅธ ๊ฐ Step ์ƒ์„ฑ

// Tasklet - ์ง์ ‘ ์ƒ์„ฑํ•œ Tasklet ์‹คํ–‰
@Bean
public Step step1() {
    return this.stepBuilderFactory.get("step")
            .tasklet(myTasklet())
            .build();


// Tasklet - ChunkOrientedTasklet ์‹คํ–‰
@Bean
public Step step1() {
    return this.stepBuilderFactory.get("step")
            .<Member,Member>chunk(100)
            .reader(reader())
            .writer(writer())
            .build();
            

// JobStep - Step์—์„œ Job์„ ์‹คํ–‰
@Bean
public Step step1() {
    public Step jobStep () {
        return this.stepBuilderFactory.get("step")
                .job(job())
                .launcher(jobLauncher)
                .parametersExtractor(jobParametersExtractor())
                .build();
                

// FlowStep - Step์—์„œ Flow๋ฅผ ์‹คํ–‰
@Bean
public Step step1() {
    public Step flowStep () {
        return this.stepBuilderFactory.get("step")
                .flow(myFlow())
                .build();

๊ฐ Step์€ ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌ์„ฑ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Spring Batch๋ฅผ ๋งŽ์ด ์ ‘ํ•ด๋ณด์ง„ ์•Š์•˜์ง€๋งŒ ๋ณดํ†ต ๊ฐ„๋‹จํ•œ ์ž‘์—…์€ ์ฒซ ๋ฒˆ์งธ์˜ Tasklet์„ ์ง์ ‘ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹์„, ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ Chunk ๊ธฐ๋ฐ˜์˜ ๋‘ ๋ฒˆ์งธ ๋ฐฉ์‹์„ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์„ธ ๋ฒˆ์งธ์™€ ๋„ค ๋ฒˆ์งธ๋Š” ์–ธ์ œ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์€ ๋ฐฉ๋ฒ•์ธ์ง€๋Š” ์ถ”ํ›„ ํ•™์Šต์„ ํ•˜๋ฉด์„œ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ^^;

 

 

 

๐Ÿ“Œ StepExecution

์•„๋ž˜ StepExecution์˜ ํ•„๋“œ๋“ค์— ๋Œ€ํ•œ ์„ค๋ช…์€ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š” :)

๊ธฐ๋ณธ ๊ฐœ๋…

  • StepExecution์€ Step์— ๋Œ€ํ•ด ํ•œ ๋ฒˆ์˜ ์‹œ๋„๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฐ์ฒด๋กœ Step ์‹คํ–‰์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•จ
  • JobExecution์™€ ์œ ์‚ฌํ•˜๊ฒŒ Step์ด ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด StepExecution์ด ์ƒ์„ฑ๋จ 
  • ์ด์ „ ๋‹จ๊ณ„์˜ Step์ด ์‹คํŒจํ•ด ํ˜„์žฌ Step์„ ์‹คํ–‰ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด, StepExecution์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์Œ
  • JobExecution์™€์˜ ๊ด€๊ณ„
    • Step์˜ StepExecution์ด ๋ชจ๋‘ ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ๋˜์–ด์•ผ JobExecution์ด ์ •์ƒ์ ์œผ๋กœ ์™„๋ฃŒ๋จ
    • ์—ฌ๋Ÿฌ Step ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์‹คํŒจํ•˜๋ฉด JobExecution์€ ์‹คํŒจํ•จ
    • JobExecution์™€ StepExecution์€ 1 : M์˜ ๊ด€๊ณ„
  • BATCH_STEP_EXECUTION ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘

https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html

 

์˜ˆ์ œ ์ฝ”๋“œ

@RequiredArgsConstructor
@Configuration
public class StepExecutionConfiguration {

    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Primary
    @Bean
    public Job stepExecutionJob() {
        return this.jobBuilderFactory.get("StepExecutionJob")
                .start(step1())
                .next(step2())
                .next(step3())
                .build();
    }

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                .tasklet(new Tasklet() {
                    @Override
                    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
                        System.out.println("step1 has executed");
                        return RepeatStatus.FINISHED;
                    }
                })
                .build();
    }

    @Bean
    public Step step2() {
        return stepBuilderFactory.get("step2")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("step2 has executed");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

    @Bean
    public Step step3() {
        return stepBuilderFactory.get("step3")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("step3 has executed");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }
}

์ด์ „ ์ฝ”๋“œ๋“ค๊ณผ ๋Œ€๋ถ€๋ถ„ ๋น„์Šทํ•œ ํ˜•์‹์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ์— ๋Œ€ํ•œ ์„ค๋ช…์€ ์ƒ๋žตํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์œ„ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•œ ํ›„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ™•์ธํ•ด ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ชจ๋“  Step์ด ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜์–ด COMPLETED ์ƒํƒœ๊ฐ€ ๋˜์—ˆ๊ณ , JOB_EXECUTION ๋˜ํ•œ COMPLETED ์ƒํƒœ์ธ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

BATCH_STEP_EXECUTION
BATCH_JOB_EXECUTION

 

์ด๋ฒˆ์—๋Š” ์œ„์™€๋Š” ๋‹ค๋ฅด๊ฒŒ step2์—์„œ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ ํ›„ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

(๋ฐ์ดํ„ฐ ํ™•์ธ์„ ์‰ฝ๊ฒŒ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ์กด ํ…Œ์ด๋ธ” ๋ฐ ๋ฐ์ดํ„ฐ๋Š” Drop ํ•œ ํ›„ ์ƒˆ๋กœ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.)

...

    @Bean
    public Step step2() {
        return stepBuilderFactory.get("step2")
                .tasklet((contribution, chunkContext) -> {
                    throw new RuntimeException("step2 Exception"); // ๊ฐ•์ œ ์˜ˆ์™ธ ๋ฐœ์ƒ
                })
                .build();
    }

...

BATCH_STEP_EXECUTION
BATCH_JOB_EXECUTION

step2๋Š” ์‹คํ–‰์€ ๋˜์—ˆ์œผ๋‚˜ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์‹คํŒจํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— StepExecution์€ ์ƒ์„ฑ์ด ๋˜์–ด BATCH_STEP_EXECUTION ํ…Œ์ด๋ธ”์— ์ €์žฅ์€ ๋˜์ง€๋งŒ, ์ƒํƒœ๋Š” FAILED์ธ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฒฐ๋ก ์ ์œผ๋กœ JOB_EXECUTION์˜ ์ƒํƒœ ๋˜ํ•œ FAILED์ธ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

(step2๊ฐ€ ์‹คํŒจํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— step3์€ ์‹คํ–‰์กฐ์ฐจ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

 

 

์ด์ œ step2์—์„œ ๊ฐ•์ œ๋กœ ๋ฐœ์ƒ์‹œ์ผฐ๋˜ ์˜ˆ์™ธ๋ฅผ ์ œ๊ฑฐํ•œ ํ›„ ๋‹ค์‹œ Job์„ ์‹คํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    @Bean
    public Step step2() {
        return stepBuilderFactory.get("step2")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("step2 has executed");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }

BATCH_STEP_EXECUTION
BATCH_JOB_EXECUTION
BATCH_JOB_INSTANCE

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ํ™•์ธํ•ด ๋ณด๋ฉด ์ด์ „์— ์ •์ƒ์ ์œผ๋กœ ์ˆ˜ํ–‰๋œ step1์€ ์žฌ์‹คํ–‰์ด ์•ˆ๋˜๊ณ , ์‹คํŒจํ–ˆ๋˜ step2์™€ ์‹คํ–‰๋˜์ง€ ์•Š์€ step3๋งŒ ์žฌ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์–ด ์ˆ˜ํ–‰๋˜๊ณ  ์ƒํƒœ๊ฐ€ COMPLETED์ธ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

BATCH_JOB_EXECUTION ํ…Œ์ด๋ธ”์—๋„ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋˜์—ˆ๊ณ , ์ƒํƒœ๊ฐ€ COMPLETED์ธ ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋งŒ์•ฝ ์œ„ ์ƒํƒœ์—์„œ ์—๋Ÿฌ๊ฐ€ ์—†๋Š” Job & Step์„ ํ•œ ๋ฒˆ ๋” ์‹คํ–‰ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

BATCH_JOB_EXECUTION

์œ„ ์‚ฌ์ง„์˜ ๋ฌธ๊ตฌ์ฒ˜๋Ÿผ ๋ชจ๋“  Step์ด ์‹คํ–‰๋˜์—ˆ๊ฑฐ๋‚˜, Job์— ์•„๋ฌด๋Ÿฐ Step์ด ๊ตฌ์„ฑ๋˜์ง€ ์•Š์•˜๋‹ค๊ณ  ๋‚˜์˜ค๋ฉฐ COMPLETED๋กœ ์ €์žฅ์ด ๋ฉ๋‹ˆ๋‹ค.

(BATCH_STEP_EXECUTION ํ…Œ์ด๋ธ”์—๋Š” ์•„๋ฌด๋Ÿฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ์•„์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

 

BATCH_JOB_INSTANCE

JobInstance์˜ ๊ฒฝ์šฐ ์ƒˆ๋กœ ์ƒ์„ฑ๋˜์ง€ ์•Š๊ณ  ๋‹จ ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ๋งŒ ์กด์žฌํ•˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ์š”, JobInstance์™€ JobExecution, StepExecution์˜ ๊ด€๊ณ„๋ฅผ ๋‹ค์‹œ ์ •๋ฆฌํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

JobInstance

  • Job์ด ์‹คํ–‰๋˜๋Š” ์‹œ์ ์— ์ƒ์„ฑ๋˜๋Š” Job์˜ ๋…ผ๋ฆฌ์  ์ž‘์—… ์‹คํ–‰ ๊ฐœ๋…
  • Job์˜ ์‹คํ–‰ ๊ตฌ๋ถ„
  • JobExecution์™€์˜ ๊ด€๊ณ„๋Š” 1 : N

JobExecution

  • Job์— ๋Œ€ํ•œ ํ•œ ๋ฒˆ์˜ ์‹œ๋„๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ Job ์‹คํ–‰ ์ค‘ ๋ฐœ์ƒํ•œ ์ •๋ณด๋“ค์„ ์ €์žฅ
  • StepExecution์™€์˜ ๊ด€๊ณ„๋Š” 1 : N

StepExecution

  • Step์— ๋Œ€ํ•œ ํ•œ ๋ฒˆ์˜ ์‹œ๋„๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ Step ์‹คํ–‰ ์ค‘ ๋ฐœ์ƒํ•œ ์ •๋ณด๋“ค์„ ์ €์žฅ
  • Step์ด ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด StepExecution์ด ์ƒ์„ฑ

 

 

์ฐธ๊ณ  ๋ฌธ์„œ

 

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€