
Spring Batch의 실행 구조는 JobExecution과 StepExecution의 계층으로 구성된다.
JobExecution은 Job 한 번의 실행을 의미한다. StepExecution은 JobExecution 내부에서 각 Step의 실행을 의미한다. 하나의 JobExecution은 여러 개의 StepExecution을 가질 수 있다. StepExecution은 자신이 속한 JobExecution을 참조한다.
이 구조로 인해 Step은 JobParameters를 직접 소유하지 않는다. 대신 StepExecution을 통해 부모 JobExecution에 접근하고, 그 안에 저장된 JobParameters를 조회한다.
이 설계는 Job 단위의 입력값을 모든 Step에서 동일하게 사용할 수 있도록 하기 위한 구조다.
Step 내부에서 JobParameters에 접근하는 경로는 명확하다. Step → StepExecution → JobExecution → JobParameters 순서로 접근한다.
다음은 Tasklet에서 JobParameters를 직접 조회하는 예제이다.
@Component
public class DailyAggregationTasklet implements Tasklet {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
JobParameters jobParameters = chunkContext.getStepContext()
.getStepExecution()
.getJobParameters();
String processDate = jobParameters.getString("processDate");
Integer batchSize = jobParameters.getInt("batchSize");
return RepeatStatus.FINISHED;
}
}
StepExecution#getJobParameters()는 내부적으로 부모 JobExecution이 보관 중인 JobParameters를 반환한다. Step 기준으로 접근하더라도 Job 단위의 파라미터를 동일하게 조회하게 된다.
JobParameters를 사용하는 가장 일반적인 방식은 @Value를 통한 주입이다. 이 방식은 내부적으로도 동일한 구조를 따른다. JobParameters는 JobExecution이 생성된 이후에만 유효하므로, 해당 값을 주입받는 빈은 실행 시점에 생성되어야 한다.
이 때문에 JobParameters를 주입받는 빈에는 @StepScope 또는 @JobScope가 필요하다.
@Bean
@StepScope
public Tasklet aggregationTasklet(
@Value("#{jobParameters['processDate']}") String processDate
) {
return (contribution, chunkContext) -> {
return RepeatStatus.FINISHED;
};
}
Scope가 지정되지 않은 싱글톤 빈은 애플리케이션 구동 시점에 생성된다. 이 시점에는 JobExecution이 존재하지 않으므로 JobParameters를 주입할 수 없다. 이 제약은 구현상의 한계가 아니라, JobParameters가 실행 객체에 속해 있다는 구조적 전제에서 비롯된다.