Spring Batch Job 파라미터 완벽 가이드: 동적 배치 설계의 핵심 원리와 실무 예제

안녕하세요.

Spring Batch Job 파라미터 완벽 가이드: 동적 배치 설계의 핵심 원리와 실무 예제 이미지 1

Spring Batch를 이용해 배치 시스템을 구축할 때, 가장 먼저 마주하게 되는 과제 중 하나는 “어떻게 하면 매번 다른 조건으로 배치를 실행할 수 있을까?” 하는 점입니다. 고정된 로직만 수행하는 배치는 활용도가 매우 제한적입니다. 예를 들어, 특정 날짜의 정산 데이터만 처리하고 싶거나, 특정 업체 ID를 파라미터로 받아 해당 업체만 필터링하여 배치 작업을 수행해야 하는 경우가 실무에서는 비일비재합니다.

이때 핵심적인 역할을 하는 것이 바로 JobParameters입니다. 하지만 단순히 값을 전달하는 기능을 넘어, Spring Batch가 왜 이러한 파라미터 구조를 가졌는지, 그리고 이 파라미터가 어떻게 배치의 ‘상태’를 결정하고 ‘재시작’ 여부에 영향을 미치는지 깊이 있게 이해하는 것이 중요합니다. 단순히 코드를 복사해 붙여넣는 수준을 넘어, 아키텍처 관점에서 파라미터를 다루는 능력을 갖추어야 진정한 배치 전문가로 성장할 수 있습니다.

오늘은 JobParameters의 기본 개념부터, Spring Batch만의 독특한 기능인 ‘Late Binding(늦은 바인딩)’, 그리고 실무에서 파라미터를 안전하게 검증하고 활용하는 전략을 7,000자 이상의 상세한 텍스트로 풀어내 보겠습니다.


1. JobParameters: 배치의 유일성을 결정하는 신분증

Spring Batch에서 JobParameters는 단순히 메서드에 전달되는 인자가 아닙니다. 이는 해당 Job의 JobInstance를 식별하는 핵심 데이터입니다. Spring Batch 메타 테이블 중 BATCH_JOB_INSTANCE를 보면, Job 이름과 JobParameters의 해시값을 조합하여 유니크한 레코드를 생성하는 것을 볼 수 있습니다.

이는 매우 중요한 의미를 가집니다. 만약 동일한 Job 이름과 동일한 파라미터로 배치를 다시 실행한다면, Spring Batch는 이를 “새로운 작업”이 아니라 “기존 작업의 재시도”로 인식합니다. 만약 이전 실행이 성공했다면, “이미 성공한 작업입니다”라며 실행을 거부하게 됩니다. 따라서 배치를 매번 새롭게 실행하고 싶다면 타임스탬프와 같은 고유한 파라미터를 섞어주어야 하고, 반대로 특정 날짜의 실패한 작업을 정확히 재개하고 싶다면 그날의 파라미터를 정확히 유지해야 합니다. 이러한 매커니즘을 이해하는 것이 동적 배치 설계의 시작입니다.


2. Late Binding (늦은 바인딩)과 Scope의 마법

Spring Batch의 파라미터 활용에서 가장 강력한 기능 중 하나는 바로 Late Binding입니다. 일반적인 스프링 빈(Bean)은 애플리케이션 컨텍스트가 로딩되는 시점에 생성됩니다. 하지만 배치 파라미터는 배치가 ‘실행되는 시점’에 결정됩니다. 컨텍스트 로딩 시점에는 아직 어떤 파라미터가 들어올지 알 수 없는데, 어떻게 이 값을 빈 설정에 사용할 수 있을까요?

그 해답은 바로 @StepScope@JobScope에 있습니다. 이 어노테이션들이 선언된 빈은 애플리케이션 구동 시점이 아니라, 해당 Step이나 Job이 실제로 실행되는 시점에 빈이 생성됩니다. 이때 비로소 실행 시점에 전달된 jobParameters에 접근하여 그 값을 빈의 속성으로 주입할 수 있게 됩니다. 이를 통해 우리는 실행 시점의 날짜에 따라 파일 경로를 동적으로 바꾸거나, 특정 파라미터에 따라 쿼리 조건을 변경하는 유연한 설계를 할 수 있습니다.


3. 실무에서의 파라미터 활용 전략

실무에서 파라미터를 다룰 때는 몇 가지 주의사항과 베스트 프랙티스가 있습니다.

첫째, 데이터 타입의 제한입니다. JobParameters는 기본적으로 String, Long, Double, Date 타입만 지원합니다. 만약 복잡한 객체나 리스트를 전달하고 싶다면, 이를 JSON 문자열로 변환하여 String으로 넘기거나, 해당 객체의 식별자(ID)만 넘기고 Processor에서 DB를 조회하여 객체를 복원하는 방식을 택해야 합니다.

둘째, 파라미터 검증(Validation)입니다. 잘못된 파라미터가 전달되어 배치가 한참 돌다가 중간에 실패하는 것은 시간과 자원의 낭비입니다. Spring Batch는 JobParametersValidator 인터페이스를 제공하여, Job이 시작되기 직전에 필수 파라미터의 존재 여부나 값의 유효 범위를 체크할 수 있게 해줍니다. 예를 들어 날짜 형식이 올바른지, 시작일이 종료일보다 앞서는지 등을 미리 검증하여 시스템의 안정성을 높일 수 있습니다.

셋째, Incrementer의 활용입니다. 매일 돌아가는 배치에서 파라미터가 매번 같으면 중복 실행 방지 로직에 걸려 배치가 돌지 않습니다. 이때 RunIdIncrementer를 사용하면 내부적으로 run.id라는 파라미터를 매번 자동으로 증가시켜 주어, 논리적으로는 같은 작업이더라도 물리적으로는 매번 새로운 실행으로 인식되게 할 수 있습니다.


4. 예제 코드 분석

이제 위에서 설명한 개념들이 실제 코드에서 어떻게 구현되는지 살펴보겠습니다.

코드 1: @StepScope와 파라미터 주입

Reader에서 실행 시점의 파라미터를 받아 동적으로 데이터를 조회하는 예제입니다.

@Bean
@StepScope // 파라미터 주입을 위해 필수!
public JpaPagingItemReader<Order> orderReader(
        @Value("#{jobParameters['requestDate']}") String requestDate) {

    log.info(">>>>> requestDate = {}", requestDate);

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("requestDate", requestDate);

    return new JpaPagingItemReaderBuilder<Order>()
            .name("orderReader")
            .entityManagerFactory(entityManagerFactory)
            .pageSize(100)
            .queryString("SELECT o FROM Order o WHERE o.orderDate = :requestDate")
            .parameterValues(parameters)
            .build();
}

코드 2: JobParametersValidator를 통한 검증

배치 시작 전 파라미터를 꼼꼼하게 체크하는 검증기 설정입니다.

public class SettlementJobValidator implements JobParametersValidator {
    @Override
    public void validate(JobParameters parameters) throws JobParametersInvalidException {
        String requestDate = parameters.getString("requestDate");
        if (!StringUtils.hasText(requestDate)) {
            throw new JobParametersInvalidException("requestDate 파라미터가 빈 값입니다.");
        }
        // 추가적인 날짜 형식 검증 로직 등...
    }
}

// Job 설정에서의 적용
@Bean
public Job settlementJob() {
    return new JobBuilder("settlementJob", jobRepository)
            .validator(new SettlementJobValidator())
            .start(settlementStep())
            .build();
}

Spring Batch Job 파라미터 완벽 가이드: 동적 배치 설계의 핵심 원리와 실무 예제 이미지 2

5. 결론

JobParameters는 Spring Batch를 살아 움직이게 만드는 ‘입력 값’입니다. 단순히 값을 전달하는 도구를 넘어, JobInstance의 생명주기를 관리하고 배치의 유연성을 결정짓는 핵심 설계 요소임을 잊지 말아야 합니다.

효과적인 파라미터 설계는 배치의 재사용성을 높이고, 운영 중 발생하는 다양한 요구사항에 기민하게 대응할 수 있는 기반이 됩니다. 오늘 배운 Late Binding 기술과 Validator 활용법을 여러분의 프로젝트에 적용하여, 더욱 견고하고 똑똑한 배치 시스템을 구축해 보시기 바랍니다.

다음 시간에는 이렇게 파라미터를 활용해 실행한 배치가 실패했을 때, 어떻게 하면 실패한 지점부터 안전하게 재시작(Restart)할 수 있는지 그 매커니즘과 방법을 상세히 다뤄보겠습니다.

관련 글 보기