[Spring Batch] 3. ์Šคํ”„๋ง ๋ฐฐ์น˜ ๋„๋ฉ”์ธ ์ดํ•ด

 

1. Job

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

- ๋ฐฐ์น˜ ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ ๊ฐ€์žฅ ์ƒ์œ„์— ์žˆ๋Š” ๊ฐœ๋…์œผ๋กœ์„œ ํ•˜๋‚˜์˜ ๋ฐฐ์น˜์ž‘์—… ์ž์ฒด๋ฅผ ์˜๋ฏธ 

  (ex. API ์„œ๋ฒ„์˜ ์ ‘์† ๋กœ๊ทธ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ต๊ณ„ ์„œ๋ฒ„๋กœ ์˜ฎ๊ธฐ๋Š” ๋ฐฐ์น˜ = Job ์ž์ฒด)

- Job Configuration์„ ํ†ตํ•ด ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ฒด ๋‹จ์œ„๋กœ์„œ ๋ฐฐ์น˜์ž‘์—…์„ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•  ๊ฒƒ์ธ์ง€ ์ „์ฒด์ ์œผ๋กœ ์„ค์ •ํ•˜๊ณ  ๋ช…์„ธํ•ด ๋†“์€ ๊ฐ์ฒด

- ๋ฐฐ์น˜ Job์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ์ตœ์ƒ์œ„ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฉฐ, ์Šคํ”„๋ง ๋ฐฐ์น˜๊ฐ€ ๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด๋ฅผ ์ œ๊ณต

- ์—ฌ๋Ÿฌ Step์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ์ปจํ…Œ์ด๋„ˆ๋กœ์„œ ๋ฐ˜๋“œ์‹œ ํ•œ ๊ฐœ ์ด์ƒ์˜ Step์œผ๋กœ ๊ตฌ์„ฑํ•ด์•ผํ•จ

 

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

[ 1. SimpleJob ]

- ์ˆœ์ฐจ์ ์œผ๋กœ Step์„ ์‹คํ–‰์‹œํ‚ค๋Š” Job

- ๋ชจ๋“  Job์—์„œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ‘œ์ค€ ๊ธฐ๋Šฅ์„ ๊ฐ–๊ณ ์žˆ์Œ

 

[ 2. FlowJob ]

- ํŠน์ •ํ•œ ์กฐ๊ฑด๊ณผ ํ๋ฆ„์— ๋”ฐ๋ผ Step์„ ๊ตฌ์„ฑํ•˜์—ฌ ์‹คํ–‰์‹œํ‚ค๋Š” Job

- Flow ๊ฐ์ฒด๋ฅผ ์‹คํ–‰์‹œ์ผœ์„œ ์ž‘์—…์„ ์ง„ํ–‰

 

- JobLauncher (Job ์‹คํ–‰) ์ด job ๊ฐ์ฒด์™€ parameters ๊ฐ์ฒด๋กœ Job ์‹คํ–‰

- Job์€ ํ•˜๋‚˜์˜ ๋„๋ฉ”์ธ ๊ฐ์ฒด (์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ œ๊ณต) 

- Steps๋ผ๋Š” List ๋ณ€์ˆ˜ ๊ฐ€์ง€๊ณ ์žˆ์Œ

- ํ•˜๋‚˜์˜ ๋ช…์„ธ์„œ/์„ค๊ณ„์„œ๊ณ  Step์„ ํฌํ•จํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ ์—ญํ• ์„ ํ•จ

 

- Job ์ตœ์ƒ์œ„ Interface

- void execute ๋ฉ”์„œ๋“œ (JobeExecution) ๋„๋ฉ”์ธ ๊ฐ์ฒด ์ธ์ž๋กœ ๋ฐ›์•„์„œ ์‹คํ–‰

- ์ด Interface๋ฅผ ์ƒ์†ํ•œ ์ถ”์ƒํด๋ž˜์Šค AbstractJob (ํ•„๋“œ ๊ฐ€์ง)

- ์ด ์ถ”์ƒํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ๋‘ ๊ฐœ์˜ Job

 

* Job ์„ค์ • -> Step ์„ค์ • -> Joblauncher๊ฐ€ Job ์‹คํ–‰ -> Job ๊ตฌ๋™ -> Job์ด Step ์‹คํ–‰ -> Tasklet ์‹คํ–‰


2. JobInstance

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

- Job์ด ์‹คํ–‰๋  ๋•Œ ์ƒ์„ฑ๋˜๋Š” Job์˜ ๋…ผ๋ฆฌ์  ์‹คํ–‰ ๋‹จ์œ„ ๊ฐ์ฒด๋กœ์„œ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ ๊ฐ€๋Šฅํ•œ ์ž‘์—… ์‹คํ–‰์„ ๋‚˜ํƒ€๋ƒ„

- Job์˜ ์„ค์ •๊ณผ ๊ตฌ์„ฑ์€ ๋™์ผํ•˜์ง€๋งŒ Job์ด ์‹คํ–‰๋˜๋Š” ์‹œ์ ์— ์ฒ˜๋ฆฌํ•˜๋Š” ๋‚ด์šฉ์€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— Job์˜ ์‹คํ–‰์„ ๊ตฌ๋ถ„ํ•ด์•ผํ•จ

   ex) ํ•˜๋ฃจ์— ํ•œ ๋ฒˆ์”ฉ ๋ฐฐ์น˜ Job์ด ์‹คํ–‰๋œ๋‹ค๋ฉด ๋งค์ผ ์‹คํ–‰๋˜๋Š” ๊ฐ๊ฐ์˜ Job์„ JobInstance๋กœ ํ‘œํ˜„

- JobInstance ์ƒ์„ฑ ๋ฐ ์‹คํ–‰

   > ์ฒ˜์Œ ์‹œ์ž‘ํ•˜๋Š” Job + JobParameter์ผ ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด JobInstance ์ƒ์„ฑ

   > ์ด์ „๊ณผ ๋™์ผํ•œ Job + JobParameter์œผ๋กœ ์‹คํ–‰ํ•  ๊ฒฝ์šฐ ์ด๋ฏธ ์กด์žฌํ•˜๋Š” JobInstance ๋ฆฌํ„ด

   > ๋‚ด๋ถ€์ ์œผ๋กœ JobName + JobKey (JobParameter์˜ ํ•ด์‹œ๊ฐ’)๋ฅผ ๊ฐ€์ง€๊ณ  JobInstance ๊ฐ์ฒด๋ฅผ ์–ป์Œ

- Job๊ณผ 1:M ๊ด€๊ณ„

 

2) BATCH_JOB_INSTANC ํ…Œ์ด๋ธ”๊ณผ ๋งตํ•‘

- JOB_NAME(Job) ๊ณผ JOB_KEY(JobParameter ํ•ด์‹œ๊ฐ’)๊ฐ€ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋Š” ์ค‘๋ณตํ•ด์„œ ์ €์žฅํ•  ์ˆ˜ ์—†์Œ

 

- Job / JobParameters ํ‚ค ๊ฐ’์œผ๋กœ ๊ธฐ์กด ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์ƒˆ๋กœ์šด JobInstance ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด JobInstance ๋ฆฌํ„ด

 

JobRunner

package io.springbatch.springbatch;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class JobRunner implements ApplicationRunner {

    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private Job job;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("name", "user1")
                        .toJobParameters();

        jobLauncher.run(job, jobParameters);
    }
}

-> ์‹คํ–‰ ์‹œํ‚ค๋ฉด JobInstance ํ…Œ์ด๋ธ”์— ์ €์žฅ๋จ

-> ๋™์ผํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์‹คํ–‰์‹œํ‚ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ ์ถœ๋ ฅ๋˜๋ฉด์„œ ๋ฐฐ์น˜ ์‹คํŒจ

Caused by: org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for identifying parameters={'name':'{value=user1, type=class java.lang.String, identifying=true}'}.  
If you want to run this job again, change the parameters.

 


3. JobParameter

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

- Job์„ ์‹คํ–‰ํ•  ๋•Œ ํ•จ๊ป˜ ํฌํ•จ๋˜์–ด ์‚ฌ์šฉ๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ง„ ๋„๋ฉ”์ธ ๊ฐ์ฒด

- ํ•˜๋‚˜์˜ Job์— ์กด์žฌํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ JobInstance๋ฅผ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„

- JobParameter์˜ JobInstance๋Š” 1:1 ๊ด€๊ณ„

 

2) ์ƒ์„ฑ ๋ฐ ๋ฐ”์ธ๋”ฉ

- ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ ์ฃผ์ž… (Java -jar LogBatch.jar / requestDate = 20210101) ๋‚ด๋ถ€์ ์œผ๋กœ ์ธ์ˆ˜๋กœ

- ์ฝ”๋“œ๋กœ ์ƒ์„ฑ (JobParameterBuilder >= DefaultJobParametersConverter)

- SpEL์ด์šฉ (@Value("#{JobParamter[requestDate]}"), @JobScope, @StepScope) ์„ ์–ธ ํ•„์ˆ˜

 

3) BATCH_JOB_EXECUTION_PARAM ํ…Œ์ด๋ธ”๊ณผ ๋งตํ•‘

- JOB_EXECUTION๊ณผ 1:M ๊ด€๊ณ„

 

- JobParameter  Wrapper (๋‚ด๋ถ€์ ์œผ๋กœ LinkedHashMap)

- ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’ ์ €์žฅ (Object ํƒ€์ž… / ParameterType)

- ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž… ๊ตฌ๋ถ„ (STRING / DATE  / LONG / DOUBLE)

 

package io.springbatch.springbatch;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JobParameterTest implements ApplicationRunner {
    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private Job job;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("name", "user4")
                .addLong("seq", 2L)
                .addDate("date", new Date())
                .addDouble("age", 15.5)
                .toJobParameters();

        jobLauncher.run(job, jobParameters);
    }
}

4. JobExecution

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

- JobInstance์— ๋Œ€ํ•œ ํ•œ๋ฒˆ์˜ ์‹œ๋„๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฐ์ฒด๋กœ์„œ Job ์‹คํ–‰ ์ค‘์— ๋ฐœ์ƒํ•œ ์ •๋ณด ์ €์žฅ ๊ฐ์ฒด

(์‹œ์ž‘์‹œ๊ฐ„ / ์ข…๋ฃŒ์‹œ๊ฐ„ / ์ƒํƒœ ์†์„ฑ ๊ฐ€์ง)

- JobInstance์™€์˜ ๊ด€๊ณ„

> JobExecution์€ FAILED ๋˜๋Š” COMPLICATED ๋“ฑ์˜ Job์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ์Œ

> JobExecution์˜ ์‹คํ–‰ ์ƒํƒœ ๊ฒฐ๊ณผ๊ฐ€ COMPLICATED๋ฉด JobInstance ์‹คํ–‰์ด ์™„๋ฃŒ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•ด ์žฌ์‹คํ–‰ ๋ถˆ๊ฐ€

> JobExecution์˜ ์‹คํ–‰ ์ƒํƒœ ๊ฒฐ๊ณผ๊ฐ€ FAILED๋ฉด JobInstance ์‹คํ–‰์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ๊ฐใ„ด์ฃผํ•ด ์žฌ์‹คํ–‰ ๊ฐ€๋Šฅ

   JobParameter๊ฐ€ ๋™์ผํ•œ ๊ฐ’์œผ๋กœ Job์„ ์‹คํ–‰ํ• ์ง€๋ผ๋„ JobInstance๋ฅผ ๊ณ„์† ์‹คํ–‰ ๊ฐ€๋Šฅ

> JobExecution์˜ ์‹คํ–‰ ์ƒํƒœ ๊ฒฐ๊ณผ๊ฐ€ COMPLICATED ๋  ๋•Œ๊นŒ์ง€ ํ•˜๋‚˜์˜ JobInstance ๋‚ด์—์„œ ์—ฌ๋Ÿฌ ๋ฒˆ์˜ ์‹œ๋„ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Œ

 

 

์ •๋ฆฌ) Job + JobParameter -> JobInstance 1๊ฐœ -> JobExecution ์—ฌ๋Ÿฌ๊ฐœ

 

2) BATCH_JOB_EXECUTION ํ…Œ์ด๋ธ”๊ณผ ๋งตํ•‘

- JobInstance์™€ JobExecution์€ 1:M์˜ ๊ด€๊ณ„๋กœ์„œ JobInstance์— ๋Œ€ํ•œ ์„ฑ๊ณต/์‹คํŒจ ๋‚ด์—ญ ๊ฐ€์ง

 


5. Step

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

- Batch Job์„ ๊ตฌ์„ฑํ•˜๋Š” ๋…๋ฆฝ์ ์ธ ํ•˜๋‚˜์˜ ๋‹จ๊ณ„๋กœ์„œ ์‹ค์ œ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ๋ฅผ ์ •์˜ํ•˜๊ณ  ์ปจํŠธ๋กคํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋„๋ฉ”์ธ ๊ฐ์ฒด

- ๋‹จ์ˆœํ•œ ๋‹จ์ผ ํ…Œ์Šคํฌ ๋ฟ ์•„๋‹ˆ๋ผ ์ž…๋ ฅ๊ณผ ์ฒ˜๋ฆฌ ๊ทธ๋ฆฌ๊ณ  ์ถœ๋ ฅ๊ณผ ๊ด€๋ จ๋œ ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํฌํ•จํ•˜๋Š” ๋ชจ๋“  ์„ค์ •๋“ค์„ ๋‹ด๊ณ ์žˆ์Œ

- ๋ฐฐ์น˜์ž‘์—…์„ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•  ๊ฒƒ์ธ์ง€ Job์˜ ์„ธ๋ถ€ ์ž‘์—…์„ Task ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค์ •ํ•˜๊ณ  ๋ช…์„ธํ•ด ๋†“์€ ๊ฐ์ฒด

- ๋ชจ๋“  Job์€ ํ•˜๋‚˜ ์ด์ƒ์˜ step์œผ๋กœ ๊ตฌ์„ฑ๋จ

 

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

- TaskletStep : ๊ฐ€์žฅ ๊ธฐ๋ณธ์ด ๋˜๋Š” ํด๋ž˜์Šค๋กœ์„œ Tasklet ํƒ€์ž…์˜ ๊ตฌํ˜„์ฒด๋“ค์„ ์ œ์–ด

- PartitionStep : ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ๋ฐฉ์‹์œผ๋กœ Step์„ ์—ฌ๋Ÿฌ ๊ฐœ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์‹คํ–‰

- JobStep : Step ๋‚ด์—์„œ Job์„ ์‹คํ–‰ํ•˜๋„๋ก ํ•จ (Job -> Step -> Job -> Step)

- FlowStep : Step ๋‚ด์—์„œ Flow๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•จ (Flow = ์Šคํ…๊ณผ ๊ฐ™์€ ๋‹จ์œ„)

 

Job = ๋ช…์„ธ์„œ 
Step = ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง (tasklet ๊ธฐ๋ฐ˜ ์ž‘์—…)

 

 

Job ๋„๋ฉ”์ธ ๋นˆ ์ƒ์„ฑ -> ์—ฌ๋Ÿฌ๊ฐœ ์Šคํ… ํฌํ•จ (๋ฆฌ์ŠคํŠธ์— ๋‹ด์•„๋‘ ) ๊ฐ๊ฐ ์Šคํ…์„ executeํ•ด์„œ ์‹คํ–‰

-> Step์€ ๋‚ด๋ถ€์ ์œผ๋กœ tasklet ์ธํ„ฐํŽ˜์ด์Šค ๊ฐ์ฒด ํฌํ•จ -> Step์ด Tasklet execute

-> Tasklet ์•ˆ์— Chunk ๊ธฐ๋ฐ˜ (reader writer) or customized  ๋œ ๋‹จ์œ„ task

 

3) API ์„ค์ •์— ๋”ฐ๋ฅธ ๊ฐ Step ์„ค์ •

 

tasklet -> step -> Job ์ˆœ์œผ๋กœ ๋งŒ๋“ค์–ด์ง

  • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
  • ๋„ค์ด๋ฒ„ ๋ฐด๋“œ์— ๊ณต์œ ํ•˜๊ธฐ
  • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
  • ์นด์นด์˜ค์Šคํ† ๋ฆฌ ๊ณต์œ ํ•˜๊ธฐ