1. Spring Batch Job 실행 개요
- 이번 글에서는 Spring Batch에서 Job을 실행하는 방법에 대해 알아봅니다.
- Spring Batch에서 배치 작업을 실행하기 위해서는 최소한 두 가지 요소가 필요합니다.
- 실행할 Job
- Job을 시작하는 JobLauncher
- 이 두 요소는 같은 컨텍스트 내에 있을 수도 있고, 서로 다른 컨텍스트에 있을 수도 있습니다.
- 커맨드라인에서 실행하면 각 Job마다 독립된 JVM과 JobLauncher가 생성되지만, 웹 애플리케이션에서는 하나의 JobLauncher를 여러 요청이 공유하게 됩니다.
- 웹 컨테이너 환 경에서는 일반적으로 하나의 JobLauncher가 여러 요청에서 공유되어 사용됩니다. 이때는 비동기 Job 실행을 위해 구성되는 것이 일반적입니다.
2. 커맨드라인에서 Job 실행하기
2.1 엔터프라이즈 스케줄러와의 연동
- 실제 운영 환경에서는 대부분 엔터프라이즈 스케줄러(cron, Autosys, Control-M 등)를 통해 배치 작업을 관리합니다.
- 이런 스케줄러들은 Quartz와 달리 Java 애플리케이션과 직접 통신하지 않고, 운영체제 프로세스 레벨에서 작업을 수행합니다.
- 따라서 스케줄러가 배치 작업을 실행하려면 다음과 같은 방법들을 사용해야 합니다.
- 셸 스크립트 (가장 일반적)
- Perl, Ruby 등의 스크립트 언어
- Ant, Maven 같은 빌드 도구
2.2 CommandLineJobRunner 사용법
- Spring Batch는 커맨드라인 실행을 위한
CommandLineJobRunner클래스를 제공합 니다. - 이 클래스는 main 메서드를 가진 진입점 역할을 하며, 다음 네 가지 작업을 수행합니다.
- ApplicationContext를 로드하여 Spring 컨테이너 구성
- 전달받은 커맨드라인 인수를 JobParameters 객체로 변환
- 지정된 Job 이름으로 실행할 Job을 찾아서 위치 확인
- Spring 컨테이너에서 JobLauncher를 가져와서 Job 실행
- 이 모든 과정이 커맨드라인에서 전달받은 인수만으로 처리되기 때문에, 별도의 복잡한 설정 없이도 배치 작업을 실행할 수 있습니다.
2.2.1 필수 인수
| 인수 | 설명 |
|---|---|
| jobPath | ApplicationContext 생성에 사용되는 XML 파일의 위치 또는 Java 설정 클래스의 완전한 이름 |
| jobName | 실행할 Job의 이름 |
- CommandLineJobRunner를 사용할 때 반드시 전달해야 하는 인수는 두 개입니다.
- 이 두 인수는 순서가 중요합니다. 첫 번째가 jobPath, 두 번째가 jobName이어야 하며, 그 뒤의 모든 인수들은 JobParameters로 인식됩니다.
2.2.2 실행 예시
# Java 설정 클래스를 사용한 실행
java CommandLineJobRunner io.spring.EndOfDayJobConfiguration endOfDay schedule.date=2007-05-05,java.time.LocalDate
# identifying 파라미터와 non-identifying 파라미터 구분
java CommandLineJobRunner io.spring.EndOfDayJobConfiguration endOfDay \
schedule.date=2007-05-05,java.time.LocalDate,true \
vendor.id=123,java.lang.Long,false
- JobParameters에서 identifying 여부를 명시적으로 지정할 수 있습니다.
- 파라미터 끝에
true또는false를 추가하여 해당 파라미터가 Job 인스턴스를 식별하는 데 사용되는지 여부를 결정할 수 있 습니다.
파라미터 구분의 중요성
Spring Batch에서는 JobParameters를 identifying과 non-identifying으로 구분합니다. Identifying 파라미터는 Job 인스턴스를 구별하는 데 사용되므로, 같은 값으로는 중복 실행이 불가능합니다. 반면 non-identifying 파라미터는 실행 로직에만 영향을 주고 중복 실행을 허용합니다. 예를 들어, 매일 실행되는 배치에서 날짜는 identifying으로, 처리 모드 같은 옵션은 non-identifying으로 설정하는 것이 일반적입니다.
2.2.3 Java 설정 예시
@Configuration
@EnableBatchProcessing
public class EndOfDayJobConfiguration {
@Bean
public Job endOfDay(JobRepository jobRepository, Step step1) {
return new JobBuilder("endOfDay", jobRepository)
.start(step1)
.build();
}
@Bean
public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
return new StepBuilder("step1", jobRepository)
.tasklet((contribution, chunkContext) -> null, transactionManager)
.build();
}
}
2.3 Spring Boot에서 커맨드라인 실행
- Spring Boot 애플리케이션을 커맨드라인에서 실행할 때는 별도의 CommandLineJobRunner 없이도 배치 Job을 실행할 수 있습니다.
- Spring Boot는
--로 시작하는 커맨드라인 인수를 Environment 프로퍼티로 변환합니다. - 하지만 배치 Job에 파라미터를 전달할 때는
--없이 일반 형식을 사용해야 합니다.
2.3.1 Spring Boot 실행 예시
# 정확한 방법: -- 없이 파라미터 전달
java -jar myapp.jar someParameter=someValue anotherParameter=anotherValue
# 혼용 예시: 서버 설정과 배치 파라미터를 함께 전달
java -jar myapp.jar --server.port=7070 someParameter=someValue
- 위의 혼용 예시에서
--server.port=7070은 Environment 프로퍼티가 되고,someParameter=someValue만 배치 Job에 전달됩니다. - Spring Boot에서 배치 Job에 파라미터를 전달할 때는 반드시
--없는 형식을 사용해야 합니다.- Environment 프로퍼티(
--로 시작)는 배치 Job에서 무시됩니다.
- Environment 프로퍼티(
3. Exit Code 처리
3.1 Exit Code의 중요성
- 실제 운영 환경에서 배치 작업을 관리하다 보면, 스케줄러가 작업의 성공/실패 여부를 어떻게 알 수 있는지가 중요한 문제가 됩니다.
- 대부분의 엔터프라이즈 스케줄러는 Java 애플리케이션 내부의 상태를 직접 확인할 수 없고, 오직 프로세스가 반환하는 숫자(Exit Code)로만 결과를 판단합니다.
- 일반적인 Exit Code 규칙은 다음과 같습니다.
- 0: 성공적으로 완료
- 1: 일반적인 오류 발생
- 기타 숫자: 특별한 시나리오 처리
3.2 ExitCodeMapper 인터페이스
public interface ExitCodeMapper {
public int intValue(String exitCode);
}
- Spring Batch는 Job의 실행 결과를 Exit Code로 변환하기 위해 ExitCodeMapper 인터페이스를 제공합니다.
- 이 인터페이스의 역할은 간단합니다. Spring Batch 내부에서 생성되는 문자열 형태의 exit code를 스케줄러가 이해할 수 있는 숫자로 변환하는 것입니다.
3.2.1 기본 구현체: SimpleJvmExitCodeMapper
- 별도의 설정 없이 사용할 수 있는 기본 구현체의 동작 방식입니다.
- 0: Job이 정상적으로 완료된 경우
- 1: Job 실행 중 일반적인 오류가 발생한 경우
- 2: CommandLineJobRunner 자체의 문제 (Job을 찾을 수 없는 경우 등)
- 이 정도면 대부분의 기본적인 배치 관리 시나리오를 커버할 수 있습니다.
- 더 복잡한 워크플로우가 필요한 경우, 자신만의 ExitCodeMapper를 구현할 수 있습니다.
- 예를 들어, 데이터 처리량에 따라 다른 Exit Code를 반환하거나, 특정 비즈니스 조건에 따라 후속 작업을 분기하고 싶을 때 유용합니다.
- 커스텀 구현체는 Spring ApplicationContext에서 루트 레벨 빈으로 등록하면 CommandLineJobRunner가 자동으로 감지하여 사용합니다.
4. 웹 컨테이너에서 Job 실행하기
4.1 웹 환경에서의 배치 실행 필요성
- 전통적으로는 배치 작업을 커맨드라인에서 실행하는 것이 일반적이었지만, 현대의 웹 애플리케이션 환경에서는 HTTP 요청을 통해 배치를 실행해야 하는 경우가 점점 늘어나고 있습니다.
- 다음과 같은 상황에서 웹 기반 실행이 유용합니다.
- 리포팅 작업: 사용자가 요청한 시점에 즉시 보고서 생성
- 임시(ad-hoc) 작업: 정기적이지 않은 일회성 데이터 처리
- 관리자 기능: 웹 관리 페이지에서 배치 작업 수동 실행
- API 기반 통합: 다른 시스템에서 REST API를 통한 배치 작업 트리거