본문 바로가기

Batch

Spring Batch에 대해 알아보자 - (1) Job, JobInstance, JobParameter, JobExecution

Job 이란?

Job은 Spring Batch에서 배치 작업의 최상위 단위입니다.

  • 하나의 Job은 여러 개의 Step으로 구성됩니다.
  • Job을 실행하면 내부 Step들이 정의된 순서와 조건에 따라 실행됩니다.
  • 실행 결과는 JobExecution으로 관리되며, 성공/실패/중단 등의 상태가 기록됩니다.

즉, Job은 배치 처리 과정 전체를 대표하는 컨테이너라고 할 수 있습니다.


Job의 구성 방법 (SimpleJob, FlowJob)

Job을 구성하는 방식은 크게 2가지가 있습니다.

  • SimpleJob - 정해진 순서에 따라 Step을 실행
  • FlowJob - 정해진 조건에 따라 Step을 실행

Job의 종류와 실행 순서 특징

 

 

SimpleJob

SimpleJob은 가장 기본적인 Job 구현체입니다.

  • 단순히 Step들을 순차적으로 실행합니다.
  • 조건 분기나 복잡한 흐름 없이 정해진 순서대로 차례대로 실행되는 경우에 적합합니다.
    @Bean
    public Job simpleJob(JobRepository jobRepository,
                         Step step1, Step step2, Step step3, Step step4) {
        return new JobBuilder("simpleJob", jobRepository)
                .start(step1)   // step1 실행
                .next(step2)   // step2 실행
                .next(step3)   // step3 실행
                .next(step4)   // step4 실행
                .build();
    }


위 코드처럼 step1 → step2 → step3 → step4 순서로 실행됩니다.

만약 step1이 실패하면 step2는 실행되지 않고 Job이 실패 상태로 종료됩니다.

 

 

FlowJob

FlowJob은 SimpleJob보다 더 복잡한 제어 흐름을 지원합니다.

  • Flow 객체를 기반으로 Step 실행 순서를 제어합니다.
  • 분기(조건문), 병렬 실행, 조건부 흐름 제어 등을 정의할 수 있습니다.
    // 기본 예시
    @Bean
    public Job flowJob(JobRepository jobRepository, Step step1, Step step2, Step step3) {
        Flow flow = new FlowBuilder<Flow>("sampleFlow")
                .start(step1)
                .next(step2)
                .build();

        return new JobBuilder("flowJob", jobRepository)
                .start(flow)   // flow 실행 (step1 -> step2)
                .next(step3)   // flow 끝나고 step3 실행
                .end()
                .build();
    }


    // 조건 분기 예시
    @Bean
    public Job conditionalFlowJob(JobRepository jobRepository, Step step1, Step step2, Step step3) {
        return new JobBuilder("conditionalFlowJob", jobRepository)
                .start(step1)
                    .on("FAILED").to(step3)   // step1 실패 시 step3 실행
                    .from(step1).on("*").to(step2) // 그 외 경우 step2 실행
                .end()
                .build();
    }


    // 복잡한 분기 예시
    @Bean
    public Job flowJobMultipleBranch(JobRepository jobRepository,
                                     Step step1, Step step2, Step step3, Step step4) {
        return new JobBuilder("flowJobMultipleBranch", jobRepository)
                .start(step1)
                    .on("COMPLETED WITH SKIPS").to(step2)   // 특정 ExitStatus 시 step2 실행
                    .from(step1).on("FAILED").to(step3)     // 실패 시 step3 실행
                    .from(step1).on("*").to(step4)          // 그 외 경우 step4 실행
                .end()
                .build();
    }



    // 병렬 예시
    @Bean
    public Job flowJobParallel(JobRepository jobRepository,
                               Step step1, Step step2, Step step3, Step step4, TaskExecutor taskExecutor) {
        Flow flow1 = new FlowBuilder<Flow>("flow1")
                .start(step1)
                .next(step2)
                .build();

        Flow flow2 = new FlowBuilder<Flow>("flow2")
                .start(step3)
                .next(step4)
                .build();

        return new JobBuilder("flowJobParallel", jobRepository)
                .start(flow1)
                .split(taskExecutor)  // 병렬 실행
                .add(flow2)
                .end()
                .build();
    }

 


JobInstance 란?

JobInstance 생성 과정

  • JobInstance는 특정 Job 이름과 JobParameters 조합에 의해 유일하게 식별되는 배치 실행 단위입니다.
  • 쉽게 말해, 어떤 Job을 어떤 파라미터로 실행했는가를 나타내는 개체입니다.
  • 같은 Job + 같은 파라미터 조합으로는 새로운 JobInstance가 생성되지 않습니다. (=JobInstance는 유니크 하다)
  • 데이터베이스 테이블 기준으로는 BATCH_JOB_INSTANCE에 저장됩니다.

 

JobInstance와 Job의 차이

하나의 Job은 여러개의 JobInstance를 만들수 있다. (1:N)

  • Job은 정의(Definition)입니다.
    • 예: "회원 데이터 처리 Job"
  • JobInstance는 특정 실행 단위입니다.
    • 예: "회원 데이터 처리 Job + date=2025-08-29"

즉, Job은 설계도, JobInstance는 그 설계도를 특정 파라미터로 찍어낸 결과물이라고 할 수 있습니다.

 

예를 들어, 매일 특정 날짜 기준으로 회원 데이터를 처리하는 Job이 있다고 해봅시다.

JobParameters parameters = new JobParametersBuilder()
    .addString("date", "2025-08-29")
    .toJobParameters();

jobLauncher.run(userDataJob, parameters);
  • date=2025-08-29 파라미터로 실행 → 하나의 JobInstance 생성
  • 그러나 같은 Job + 같은 파라미터 조합으로는 새로운 JobInstance가 생성되지 않습니다.

JobLauncher 란?

Spring Batch에서 Job은 단순히 정의(Definition)일 뿐이고, 실행은 자동으로 일어나지 않습니다.
이때 JobLauncher를 사용하면 Job을 외부 요청이나 특정 시점에 맞춰 실행할 수 있습니다.

즉, Job을 프로그래밍적으로 트리거할 때 JobLauncher를 사용합니다.


JobLauncher 실행 방법

(1) 애플리케이션 시작 시 Job 실행

Spring Boot 환경에서는 기본적으로 JobLauncherCommandLineRunner가 Job을 자동 실행해줍니다.
하지만 경우에 따라 원하는 Job만 실행하거나 조건을 달아서 실행하고 싶을 때 JobLauncher를 직접 호출합니다.

@SpringBootApplication
public class BatchApplication implements CommandLineRunner {
    @Autowired
    private JobLauncher jobLauncher;

    @Autowired
    private Job simpleJob;

    @Override
    public void run(String... args) throws Exception {
        JobParameters params = new JobParametersBuilder()
                .addString("date", LocalDate.now().toString())
                .toJobParameters();

        jobLauncher.run(simpleJob, params);
    }
}

 

(2) REST API로 배치 실행

실무에서 자주 쓰이는 방식입니다.
관리자가 특정 시점에 API를 호출해서 배치를 실행할 수 있게 합니다.

@RestController
@RequiredArgsConstructor
public class JobController {
    private final JobLauncher jobLauncher;
    private final Job orderJob;

    @GetMapping("/run-job")
    public String runJob() throws Exception {
        JobParameters params = new JobParametersBuilder()
                .addLong("time", System.currentTimeMillis()) // 중복 실행 방지용
                .toJobParameters();

        JobExecution execution = jobLauncher.run(orderJob, params);
        return "Job Status : " + execution.getStatus();
    }
}

 

 

(3) 스케줄러와 함께 사용

Quartz, Spring Scheduler 같은 스케줄러에서 주기적으로 JobLauncher를 호출해 배치를 실행할 수 있습니다.

@Component
@RequiredArgsConstructor
public class BatchScheduler {
    private final JobLauncher jobLauncher;
    private final Job reportJob;

    @Scheduled(cron = "0 0 2 * * ?") // 매일 새벽 2시
    public void runReportJob() throws Exception {
        JobParameters params = new JobParametersBuilder()
                .addLong("time", System.currentTimeMillis()) 
                .toJobParameters();

        jobLauncher.run(reportJob, params);
    }
}

JobExecution 이란?

  • JobExecution은 JobInstance의 실행 시도를 나타내는 객체입니다.
  • JobInstance는 "Job + JobParameters 조합"으로 고유하게 생성되지만, 실행할 때마다 새로운 JobExecution이 생깁니다.
  • 따라서 한 JobInstance에는 여러 개의 JobExecution이 매핑될 수 있습니다.
  • Job 실행이 시작될 때 생성되고, 실행이 끝나면 상태가 기록됩니다.
  • 실행 상태, 시작 시간, 종료 시간, 실패 원인 등을 관리합니다.
  • 데이터베이스에서는 BATCH_JOB_EXECUTION 테이블에 저장됩니다.

 

JobInstance와 JobExecution의 관계

Job (정의)
 └─ JobInstance (Job + JobParameters 조합, 유일)
       ├─ JobExecution #1 (실패)
       ├─ JobExecution #2 (재시도, 실패)
       └─ JobExecution #3 (재시도, 성공)

하나의 JobInstance는 여러개의 JobExecution이 있을수 있다

 

JobInstance를 실행할 때마다 새로운 JobExecution이 생기고, 각 실행의 성공/실패 여부가 기록됩니다.

 

  • JobExecution은 COMPLETED, FAILED 등의 실행결과 상태를 가지고 있음
  • JobExecution이 COMPLETED면 JobInstance 실행이 완료된 것으로 간주해서 재실행이 불가능함
  • JobExecution이 FAILED면 JobInstance 실행이 완료되지 않은 것으로 간주해서 재실행이 가능함

 

JobInstance는 여러개의 JobExecution이 있을수 있습니다.

  • JobExecution의 실행 상태 결과가 COMPLETED 될 때까지 하나의 JobInstance 내에서 여러 번의 시도가 생길수 있음
  • BATCH_JOB_EXECUTION 테이블에 JobInstance와 JobExecution은 1:M의 관계로서 성공/실패의 내역을 가지고 있음.