개요
Java로 개발하는 프로젝트에는 JSpecify를(참고: https://blog.igooo.org/167) 사용해서 null safety를 지원하고 있다.
Batch 애플리케이션을 개발하는 경우 Spring Batch를 사용하여 개발을 하는데, 이때 JobParameter를 사용하여 실행을 위한 데이터를 입력하는 경우가 많다. JobParamter를 사용하는 경우 간단하게 Job이나 Step 선언부에 @Value("#{jobParamters['name']}")를 사용하여 JobParamter를 처리하는 방법을 많이 사용하는데 이때 null을 사용하지 않고 Spring Batch Job을 구성하는 방법에 대하여 알아본다.
AS-IS
Spring Batch를 사용하여 JobParameter로 date를 입력받는 경우 보통은 아래와 같이 Job을 구성한다.
Step을 구성하는 step 메서드에 @Value 어노테이션을 사용해서 JobParameter를 처리하는 경우에는 파리미터로 String date를 선언했기 때문에 job 메서드에서 step(null)으로 호출을 해야 한다.
@Bean
Job job() {
return new JobBuilder("testJob", this.jobRepository)
.start(step(null))
.build();
}
@Bean
@JobScope
Step step(@Value("#{jobParameters['date']}") String date) {
return new StepBuilder("testStep", this.jobRepository)
.tasklet((s, c) -> {
System.out.println("Date: " + date);
return RepeatStatus.FINISHED;
}, this.transactionManager)
.build();
}
JSpecify를 적용했기 때문에 null safety를 위해서 경고를 피하기 위해서는 아래와 같이 step 메서드에 선언을 변경할 수 있다.
@Bean
@JobScope
Step step(@Value("#{jobParameters['date']}") @Nullable String date) {
하지만 실제 애플리케이션에서 date가 필수 값이라면 위 방법은 올바른 해결방법이 아니다.
그렇다면 step 메서드를 호출하는 job메서드에서 아래와 같이 코드를 변경할 수 있다.
@Bean
Job job() {
return new JobBuilder("testJob", this.jobRepository)
.start(step("")) // or .start(step("20250616"))
하지만 위 방법도 단지 null safety를 피하기 위한 방법이지 실제 코드를 읽는 사람과 Sprng Batch에 대한 이해가 떨어지는 사람이 봤을 때 좋은 코드는 아니다. 빈문자열이나 임의에 date 값을 입력하더라도 step 메서드에서는 Sprinb Batch 실행 시 입력한 파라미터 값이 입력된다. 그러므로 코드상의 step 메서드에 임의에 값을 입력하는 방법은 코드를 읽는데 어려움을 줄 수 있다.
TO-BE
조금 더 가독성이 좋은 방법으로 변경을 해보자. 앞에서는 JobParamter를 @Value 어노테이션을 사용하여 바로 String 변수로 입력을 받았지만 이번에는 JobParameter를 처리하는 Bean 객체를 만들어서 처리를 해본다. 변경에 핵심은 null을 사용하지 않고 처음과 동일하게 JobParamter를 처리하는 것이다.
먼저 JobParameter를 위한 Java 객체를 만들어 준다.
date 멤버 변수를 선언하고 setter에서 @Value 어노테이션을 사용하여 JobParameter를 선언한다.
public class DateJobParamter {
private String date;
public String getDate() {
return date;
}
@Value("#{jobParameters['date']}")
public void setDate(String date) {
this.date = date;
}
}
위에서 만든 Java 객체를 @Bean으로 선언한다. Batch Job에서만 사용하는 Bean으로 @JobScope를 추가해 준다.
@Configuration
class JobParameterConfig {
@Bean
@JobScope
DateJobParamter dateJobParamter() {
return new DateJobParamter();
}
}
DateJobParameter 객체는 Job을 구성하는 생성자에서 주입받는다.
step 메서드에서는 파라미터를 삭제하고 생성자에서 주입받은 DateJobParamter 객체를 바로 사용할 수 있다.
public BatchJobConfig(JobRepository jobRepository, PlatformTransactionManager transactionManager,
DateJobParamter dateJobParamter) {
this.jobRepository = jobRepository;
this.transactionManager = transactionManager;
this.dateJobParamter = dateJobParamter;
}
@Bean
Job job() {
return new JobBuilder("testJob", this.jobRepository)
.start(step())
.build();
}
@Bean
@JobScope
Step step() {
return new StepBuilder("testStep", this.jobRepository)
.tasklet((s, c) -> {
System.out.println("Date: " + this.dateJobParamter.getDate());
return RepeatStatus.FINISHED;
}, this.transactionManager)
.build();
}
마무리
String Batch로 개발할 때 Job을 구성하는 코드에 대해서는 크게 신경을 쓰지 않고 코드를 작성했는데, JSpecify를 적용하면서 기존에 JobParamter를 사용하면서 null로 처리했던 코드들을 정리할 수 있었고, 기존보다 더욱 가독성 있는 코드를 작성할 수 있게 되었다.
혹시나 JSpecify를 Spring Batch에 적용하게 된다면 한 번쯤 고려해 보자
전체 소스코드는 GitHub에서 확인할 수 있습니다.
'dev > spring' 카테고리의 다른 글
Spring Boot에서 Project Leyden을 사용하는 방법 (2) | 2025.06.09 |
---|---|
Spring AI MCP with IntelliJ IDEA (0) | 2025.05.26 |
MCP with Spring Boot (0) | 2025.04.04 |
Spring Boot ShedLock in Action (with MongoDB) (0) | 2025.03.18 |
Spring Boot를 사용하여 MongoDB Auto-Generated Field 사용하기 (1) | 2025.03.12 |