[Spring Batch] JobParameters와 Scope

유기훈·2025년 6월 15일

JobParameters

Spring Batch를 처음 접하면 가장 헷갈릴 수 있는 개념 중 하나가 JobParameters입니다. JobParameters는 단순히 파라미터를 전달하는 기능을 넘어서, 배치 잡(Job)의 식별성과 재실행 제어에 깊이 관여하는 중요한 요소입니다.

이 포스트에서는 JobParameters에 대한 개념, 다른 구성 요소와의 차이점, 사용 방법, 그리고 유효성 검증까지 자세히 설명하겠습니다.

JobParameter에 대하여

JobParameters란?

JobParameters는 Spring Batch에서 배치 Job을 실행할 때 외부로부터 전달받는 입력값들을 말합니다. 이 값들은 JobInstance의 구분 기준이 되며, 동일한 JobParameters로 같은 Job을 실행하면 이미 실행된 것으로 간주되어 재실행되지 않습니다.

즉, JobParameters는 Job의 고유성을 식별하는 키(Key) 역할을 합니다.

public interface JobLauncher {
    JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, ...
}

JobLauncher를 통해 Job을 실행할 때 두 번째 인자로 JobParameters를 전달합니다.

특징 정리

  • Immutable: Job 실행 도중에는 변경할 수 없습니다.
  • JobInstance 식별 기준: Job 이름 + JobParameters 조합이 유일한 JobInstance를 만듭니다.
  • 재실행 제어: 같은 JobParameters로는 동일 JobInstance가 실행되지 않음 (이미 성공했다면 실행 불가).
JobParameters params = new JobParametersBuilder()
    .addString("requestDate", "2025-06-15")
    .addLong("version", 1L)
    .addDouble("rate", 0.85)
    .addDate("timestamp", new Date())
    .toJobParameters();

이 예제는 문자열, 숫자, 실수, 날짜 타입을 가진 JobParameters를 생성합니다. 내부적으로는 Map<String, JobParameter> 형태로 관리됩니다.

프로퍼티와 JobParameters의 차이

Spring Batch에서는 외부에서 데이터를 주입할 수 있는 여러 방법이 있지만, 그중 application.properties (혹은 YAML) 을 사용하는 방식과 JobParameters를 사용하는 방식은 목적이 다릅니다.

📌 즉, application.properties는 환경 구성용, JobParameters는 데이터 처리와 Job 실행 제어용입니다.

JobParameters 입력 방법

JobParameters는 다양한 방식으로 전달할 수 있습니다.

  1. CommandLineJobRunner 사용
java -jar my-batch.jar jobName requestDate=2025-06-15 version=1

위와 같이 실행하면 Spring Batch는 전달된 파라미터를 JobParameters로 자동 변환합니다.
커맨드 라인 파라미터를 넘길 때 Json 형식으로도 입력 가능합니다.

1-a. CommandLineJobRunner 사용 (JSON)

먼저, Spring Batch 설정 클래스에 아래와 같이 JsonJobParametersConverter를 Bean으로 등록합니다.

@Bean
public JobParametersConverter jobParametersConverter() {
    return new JsonJobParametersConverter();
}

커맨드라인에서 JSON 파라미터 전달 예시

java -jar batch-app.jar '{"dateParam":"2024-06-15","userId":123,"flag":true}'

컨버터를 반드시 JsonJobParametersConverter로 변경해야 합니다.

  1. JobLauncher를 사용한 프로그램 실행
@Autowired
private JobLauncher jobLauncher;

@Autowired
private Job sampleJob;

public void launchJob() {
    JobParameters params = new JobParametersBuilder()
        .addString("requestDate", "2025-06-15")
        .toJobParameters();

    try {
        JobExecution execution = jobLauncher.run(sampleJob, params);
        System.out.println("Job Status : " + execution.getStatus());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  1. 스케줄러 연동
    Spring Scheduler 또는 외부 스케줄러에서 날짜나 파일명 등을 파라미터로 동적으로 넘기는 방식으로 많이 사용됩니다.
String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
JobParameters jobParameters = new JobParametersBuilder()
        .addString("date", today)
        .toJobParameters();

JobParametersValidator

Spring Batch는 JobParameters가 필수값을 누락하거나 잘못된 값을 받을 경우를 대비해 JobParametersValidator를 제공합니다. 이 Validator를 구현하면 Job 실행 전 파라미터의 유효성을 검증할 수 있습니다.

기본 인터페이스

public interface JobParametersValidator {
    void validate(JobParameters parameters) throws JobParametersInvalidException;
}

예제: 커스텀 Validator 만들기

@Component
public class CustomJobParametersValidator implements JobParametersValidator {
    @Override
    public void validate(JobParameters parameters) throws JobParametersInvalidException {
        String requestDate = parameters.getString("requestDate");

        if (requestDate == null) {
            throw new JobParametersInvalidException("requestDate parameter is required");
        }

        try {
            LocalDate.parse(requestDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (DateTimeParseException e) {
            throw new JobParametersInvalidException("Invalid requestDate format. Expected yyyy-MM-dd");
        }
    }
}

Job에 Validator 등록

@Bean
public Job sampleJob(JobRepository jobRepository, Step sampleStep) {
    return new JobBuilder("sampleJob", jobRepository)
        .validator(new CustomJobParametersValidator())
        .start(sampleStep)
        .build();
}

위와 같이 등록하면, requestDate가 없거나 잘못된 형식이면 Job이 실행되지 않고 예외가 발생합니다.

Scope

Spring Batch에서 동적으로 생성되는 객체에 파라미터를 주입하거나, Job/Step 실행 시점에 객체를 초기화하고자 할 때 매우 유용하게 사용된다.

Spring Batch의 Step Scope & Job Scope

Scope란?

Spring에서 @Scope는 Bean의 생성 시점과 생존 범위를 정의합니다. 기본은 singleton이지만, Batch에서는 Job과 Step 단위로 실행되기 때문에 이를 반영한 @JobScope와 @StepScope라는 특수한 스코프가 존재합니다.

Spring Batch에서 Bean을 미리 만들지 않고, Job 실행 시점 또는 Step 실행 시점에 동적으로 객체를 생성하고 싶을 때 이 두 가지 Scope를 사용합니다.

왜 사용하는가?

Job과 Step은 외부에서 전달된 JobParameters를 기반으로 실행됩니다.
그런데 Spring에서는 기본적으로 Bean이 애플리케이션 시작 시점에 생성되기 때문에, Job 실행 전에는 JobParameters가 아직 없습니다.

따라서 실행 시점에 JobParameters를 사용할 수 있도록 하려면,
객체를 “나중에” 즉, Job 실행 시점 (JobScope), Step 실행 시점 (StepScope) 에 초기화해야 합니다.

JobScope

@JobScope는 Bean을 Job 실행 시점에 초기화합니다.
언제 사용하나?

  • Step 객체를 JobParameters에 따라 유동적으로 구성해야 할 때
  • Job 내에 여러 Step이 있고 각 Step마다 JobParameter 값을 공유해야 할 때

사용 예시

@Bean
@JobScope
public Step exampleStep(@Value("#{jobParameters['requestDate']}") String requestDate) {
    return stepBuilderFactory.get("exampleStep")
        .tasklet((contribution, chunkContext) -> {
            System.out.println("Job Parameter - requestDate: " + requestDate);
            return RepeatStatus.FINISHED;
        }).build();
}
  • @Value("#{jobParameters['requestDate']}")로 JobParameter 주입
  • Step이 Job 실행 시점에 생성되므로 주입 가능

StepScope

@StepScope는 Bean을 Step 실행 시점에 초기화합니다.
언제 사용하나?

  • Tasklet 또는 ItemReader/Processor/Writer에서 JobParameters를 사용해야 할 때
  • Step이 여러 번 실행되는 경우, 실행 시마다 새로운 상태로 객체를 생성해야 할 때

사용 예시

@Bean
@StepScope
public Tasklet printDateTasklet(@Value("#{jobParameters['requestDate']}") String requestDate) {
    return (contribution, chunkContext) -> {
        System.out.println("Step에서 requestDate 사용: " + requestDate);
        return RepeatStatus.FINISHED;
    };
}

이 Tasklet은 Step 실행 시점에 만들어지므로, JobParameter를 정상적으로 주입받을 수 있습니다.

Scope 없이 사용하면 생기는 문제

@Bean
public Tasklet myTasklet(@Value("#{jobParameters['requestDate']}") String requestDate) {
    // 잘못된 예시
}
  • 이 경우 Spring은 애플리케이션 시작 시점에 jobParameters['requestDate']를 평가하려고 시도
  • 하지만 아직 Job이 실행되지 않았기 때문에 requestDate는 존재하지 않아 에러 발생
  • 해결 방법: @StepScope 또는 @JobScope 추가
profile
개발 블로그

0개의 댓글