[Spring Batch][공식 문서 번역] 도메인 언어(The Domain Language of Batch)
경험 많은 배치 아키텍트에게 Spring Batch에서 사용되는 배치 처리 개념은 익숙하고 편안하게 다가올 것입니다. 여기에는 “Job”과 “Step”이 있으며, 개발자가 제공하는 ItemReader와 ItemWriter라는 처리 단위가 있습니다. 그러나 Spring 패턴, 운영, 템플릿, 콜백 및 관용구 덕분에 다음과 같은 기회를 제공합니다.
- 명확한 관심사의 분리에 대한 높은 수준의 준수
- 인터페이스로 제공되는 명확하게 구분된 아키텍처 레이어와 서비스
- 바로 사용할 수 있도록 간단하고 기본적인 구현체 제공
- 상당히 향상된 확장성
다음 다이어그램은 수십 년간 사용되어 온 배치 참조 아키텍처의 간소화된 버전입니다. 이는 배치 처리의 도메인 언어를 구성하는 구성 요소들에 대한 개요를 제공합니다. 이 아키텍처 프레임워크는 지난 수십 년 동안 메인프레임의 COBOL, 유닉스의 C, 그리고 이제는 모든 곳에서 사용할 수 있는 Java 플랫폼을 포함한 여러 세대의 플랫폼에서 입증된 청사진입니다. JCL과 COBOL 개발자들은 C, C#, Java 개발자들만큼이나 이 개념들에 편안함을 느낄 가능성이 큽니다. Spring Batch는 단순한 애플리케이션부터 복잡한 배치 애플리케이션을 구현하는 데 있어 견고하고 유지보수 가능한 시스템에서 일반적으로 사용되는 레이어, 구성 요소, 기술 서비스를 물리적으로 구현합니다. 복잡한 처리 요구를 해결하기 위한 인프라와 확장 기능도 제공합니다.
위의 도표는 Spring Batch의 도메인 언어를 구성하는 핵심 개념을 강조합니다. 하나의 Job은 하나 이상의 Step으로 구성되며, 각 Step은 정확히 하나의 ItemReader, 하나의 ItemProcessor, 그리고 하나의 ItemWriter를 가지고 있습니다. Job은 (JobLauncher를 사용해) 실행되어야 하고, 현재 실행 중인 프로세스에 대한 메타데이터는 (JobRepository에) 저장되어야 합니다.
Job
이 섹션에서는 배치 Job 개념과 관련된 스테레오타입을 설명합니다. Job은 전체 배치 프로세스를 캡슐화하는 엔티티입니다. 다른 Spring 프로젝트와 마찬가지로, Job은 XML 구성 파일이나 Java 기반 구성으로 연결됩니다. 이 구성을 “job configuration”이라고 합니다. 그러나 Job은 전체 계층 구조의 최상위일 뿐이며, 다음 다이어그램에서 보듯이 계층 구조의 일부로 작동합니다.
Spring Batch에서 Job은 Step 인스턴스의 컨테이너에 불과합니다. 논리적으로 함께 연결된 여러 Step을 하나의 흐름으로 결합하고, 모든 Step에 공통으로 적용되는 재시작 가능성과 같은 속성을 구성할 수 있습니다. Job 구성에는 다음이 포함됩니다:
- Job의 이름
- Step 인스턴스의 정의와 순서
- Job의 재시작 가능 여부
Java 기반 구성을 사용하는 경우, Spring Batch는 SimpleJob 클래스 형태로 Job 인터페이스의 기본 구현을 제공합니다. 이는 Job 위에 몇 가지 표준 기능을 추가합니다. Java 기반 구성을 사용할 때 Job의 인스턴스를 생성하기 위해 여러 빌더가 제공되며, 아래 예시와 같이 사용할 수 있습니다.
@Bean
public Job footballJob(JobRepository jobRepository) {
return new JobBuilder("footballJob", jobRepository)
.start(playerLoad())
.next(gameLoad())
.next(playerSummarization())
.build();
}
JobInstance
JobInstance는 논리적인 Job 실행을 나타내는 개념입니다. 예를 들어, 하루가 끝날 때마다 실행되어야 하는 EndOfDay Job을 생각해 볼 수 있습니다. EndOfDay라는 하나의 Job이 있지만, 각 Job의 개별 실행은 별도로 추적되어야 합니다. 이 Job의 경우 하루에 한 번 실행되는 논리적인 JobInstance가 존재합니다. 예를 들어, 1월 1일 실행, 1월 2일 실행이 있고, 이러한 방식으로 계속됩니다. 만약 1월 1일의 실행이 실패하고 다음 날 다시 실행된다면, 여전히 1월 1일 실행으로 간주됩니다. (보통 이는 처리하는 데이터와도 관련이 있어 1월 1일 실행이 1월 1일의 데이터를 처리하게 됩니다). 따라서 각 JobInstance는 여러 번의 실행(JobExecution)을 가질 수 있으며, 특정 Job과 이를 식별하는 JobParameters에 대응하는 하나의 JobInstance만이 한 번에 실행될 수 있습니다.
JobInstance의 정의는 로드할 데이터에 전혀 영향을 미치지 않습니다. 데이터 로드 방법은 전적으로 ItemReader 구현에 달려 있습니다. 예를 들어, EndOfDay 시나리오에서는 데이터에 해당 데이터가 속하는 유효 날짜 또는 스케줄 날짜를 나타내는 열이 있을 수 있습니다. 그러면 1월 1일 실행에서는 1일의 데이터만 로드하고, 1월 2일 실행에서는 2일의 데이터만 사용하게 됩니다. 이는 주로 비즈니스 결정에 따라 달라지기 때문에 ItemReader에 맡겨집니다. 하지만 동일한 JobInstance를 사용하는 경우, 이전 실행에서의 “상태”(즉, ExecutionContext)가 사용되는지 여부가 결정됩니다. 새로운 JobInstance를 사용하면 “처음부터 시작”을 의미하고, 기존 인스턴스를 사용하는 것은 일반적으로 “중단된 곳에서부터 시작”을 의미합니다.
JobParameters
JobInstance와 Job 간의 차이점을 다룬 후, 자연스럽게 떠오르는 질문은 "어떻게 하나의 JobInstance를 다른 것과 구별할 수 있는가?"입니다. 이에 대한 답은 JobParameters입니다. JobParameters 객체는 배치 Job을 시작하는 데 사용되는 일련의 매개변수를 보유합니다. 이는 식별 목적으로 사용될 수 있으며 실행 중 참조 데이터로도 사용할 수 있습니다. 아래 예시와 같이 사용됩니다.
앞선 예시에서 1월 1일과 1월 2일에 대해 각각 인스턴스가 있는 경우, 실제로는 하나의 Job만 있지만, '2017-01-01'이라는 JobParameter로 시작된 인스턴스와 '2017-01-02'이라는 매개변수로 시작된 인스턴스가 있습니다. 따라서 JobInstance = Job + 식별하는 JobParameters라는 계약을 정의할 수 있습니다. 이는 개발자가 전달할 매개변수를 제어할 수 있기 때문에 JobInstance를 효과적으로 정의할 수 있도록 합니다.
💡 모든 Job 매개변수가 JobInstance의 식별에 기여할 필요는 없습니다. 기본적으로는 그렇지만, 프레임워크는 또한 JobInstance의 식별에 기여하지 않는 매개변수를 사용하여 Job을 제출할 수 있도록 허용합니다.
JobExecution
JobExecution은 Job을 한 번 실행하려는 시도를 나타내는 기술적 개념입니다. 실행은 실패하거나 성공할 수 있지만, 특정 실행과 연결된 JobInstance는 실행이 성공적으로 완료될 때까지는 완료된 것으로 간주되지 않습니다. 이전에 설명한 EndOfDay Job을 예로 들면, 2017년 1월 1일에 해당하는 JobInstance가 처음 실행 시 실패했다고 가정합시다. 동일한 식별 Job 매개변수(01-01-2017)로 다시 실행되는 경우 새로운 JobExecution이 생성되지만, 여전히 하나의 JobInstance만 존재합니다.
Job은 작업이 무엇이며 어떻게 실행될지를 정의하며, JobInstance는 실행을 묶는 순수한 조직적 객체로, 올바른 재시작 구문을 가능하게 하기 위해 주로 존재합니다. 반면에 JobExecution은 실제 실행 중에 발생한 일을 저장하는 주요 메커니즘으로, 관리되고 지속되어야 하는 여러 속성을 포함합니다. 다음 표는 JobExecution의 주요 속성을 보여줍니다.
Table 1. JobExecution Properties
속성 | 정의 |
Status | 실행 상태를 나타내는 BatchStatus 객체. 실행 중일 때는 STARTED, 실패 시 FAILED, 성공적으로 완료되면 COMPLETED입니다. |
startTime | 실행이 시작된 현재 시스템 시간을 나타내는 java.time.LocalDateTime 객체. Job이 아직 시작되지 않은 경우 이 필드는 비어 있습니다. |
endTime | 실행이 완료된 현재 시스템 시간을 나타내는 java.time.LocalDateTime 객체. 성공 여부와 상관없이 실행이 완료되었을 때 기록됩니다. Job이 아직 끝나지 않은 경우 이 필드는 비어 있습니다. |
exitStatus | 실행 결과를 나타내는 ExitStatus. 실행 결과에 따라 호출자에게 반환되는 종료 코드를 포함하며, 이 필드는 Job이 끝나지 않은 경우 비어 있습니다. |
createTime | JobExecution이 처음 저장된 시점을 나타내는 java.time.LocalDateTime. Job이 아직 시작되지 않았을 수 있지만, 프레임워크가 관리하는 ExecutionContext를 위해 항상 createTime이 필요합니다. |
lastUpdated | JobExecution이 마지막으로 저장된 시점을 나타내는 java.time.LocalDateTime. Job이 아직 시작되지 않은 경우 이 필드는 비어 있습니다. |
executionContext | 실행 간 지속되어야 하는 사용자 데이터가 포함된 "속성 가방"입니다. |
failureExceptions | Job 실행 중 발생한 예외 목록. Job이 실패할 때 여러 예외가 발생할 경우 유용합니다. |
이러한 속성은 지속되고, 실행 상태를 완벽하게 결정하는 데 사용할 수 있기 때문에 중요합니다. 예를 들어, 1월 1일의 EndOfDay Job이 오후 9시에 실행되고 오후 9시 30분에 실패한 경우, 배치 메타데이터 테이블에 다음 항목이 기록됩니다.
Table 2: BATCH_JOB_INSTANCE
JOB_INST_ID | JOB_NAME |
1 | EndOfDayJob |
Table 3. BATCH_JOB_EXECUTION_PARAMS
JOB_EXECUTION_ID | TYPE_CD | KEY_NAME | DATE_VAL | IDENTIFYING |
1 | DATE | schedule.Date | 2017-01-01 | TRUE |
Table 4. BATCH_JOB_EXECUTION
JOB_EXEC_ID | JOB_INST_ID | START_TIME | END_TIME | STATUS |
1 | 1 | 2017-01-01 21:00 | 2017-01-01 21:30 | FAILED |
💡 여기서 명확성과 형식을 위해 열 이름은 약어 또는 생략될 수 있습니다.
이제 작업이 실패했고, 문제를 파악하는 데 밤새 걸렸다고 가정해 봅시다. 이에 따라 “배치 윈도우”는 이제 종료되었습니다. 윈도우가 오후 9시에 시작한다고 가정하면, 01-01 작업은 중단된 부분부터 다시 시작되어 오후 9시 30분에 성공적으로 완료됩니다. 이제 다음 날이 되었으므로 01-02 작업도 수행되어야 하며, 그 작업은 오후 9시 31분에 시작하여 정상적으로 1시간이 소요되어 오후 10시 30분에 완료됩니다. 두 JobInstance가 서로 다른 시간에 시작되어야 하는 필수 요건은 없습니다. 단, 두 작업이 동일한 데이터를 동시에 접근하여 데이터베이스 수준에서 잠금 문제가 발생할 가능성이 있는 경우에는 주의가 필요합니다. Job을 언제 실행할지는 전적으로 스케줄러에 달려 있으며, 두 JobInstance는 별도의 인스턴스이기 때문에 Spring Batch는 이들이 동시에 실행되는 것을 막지 않습니다. (같은 JobInstance가 이미 실행 중일 때 동일한 인스턴스를 다시 실행하려고 시도하면 JobExecutionAlreadyRunningException이 발생합니다).
이제 JobInstance 및 JobParameters 테이블에 하나의 항목이 추가되고, JobExecution 테이블에는 두 개의 항목이 추가되어야 하며, 다음과 같이 나타납니다:
Table 5. BATCH_JOB_INSTANCE
JOB_INST_ID | JOB_NAME |
1 | EndOfDayJob |
2 | EndOfDayJob |
Table 6. BATCH_JOB_EXECUTION_PARAMS
JOB_EXECUTION_ID | TYPE_CD | KEY_NAME | DATE_VAL | IDENTIFYING |
1 | DATE | schedule.Date | 2017-01-01 00:00:00 | TRUE |
2 | DATE | schedule.Date | 2017-01-01 00:00:00 | TRUE |
3 | DATE | schedule.Date | 2017-01-02 00:00:00 | TRUE |
Table 7. BATCH_JOB_EXECUTION
JOB_EXEC_ID | JOB_INST_ID | START_TIME | END_TIME | STATUS |
1 | 1 | 2017-01-01 21:00 | 2017-01-01 21:30 | FAILED |
2 | 1 | 2017-01-02 21:00 | 2017-01-02 21:30 | COMPLETED |
3 | 2 | 2017-01-02 21:31 | 2017-01-02 22:29 | COMPLETED |
💡 여기서 명확성과 형식을 위해 일부 열 이름은 약어로 표현되거나 생략될 수 있습니다.
Step
Step은 배치 작업의 독립적이고 순차적인 단계를 캡슐화하는 도메인 객체입니다. 따라서 모든 Job은 하나 이상의 Step으로 구성됩니다. Step에는 실제 배치 처리를 정의하고 제어하는 데 필요한 모든 정보가 포함됩니다. Step의 내용은 Job을 작성하는 개발자의 재량에 달려 있기 때문에 이 설명은 다소 모호할 수 있습니다. 간단한 Step은 파일에서 데이터베이스로 데이터를 로드하는 등, 거의 또는 전혀 코드가 필요하지 않을 수 있습니다. 반면에 복잡한 Step은 처리 중에 적용되는 복잡한 비즈니스 규칙을 포함할 수도 있습니다. Job과 마찬가지로, 각 Step은 고유한 JobExecution과 연관된 개별 StepExecution을 가지고 있으며, 아래 이미지가 이를 보여줍니다.
StepExecution
StepExecution은 Step을 실행하려는 단일 시도를 나타냅니다. JobExecution과 유사하게, Step이 실행될 때마다 새로운 StepExecution이 생성됩니다. 그러나 이전 Step이 실패하여 해당 Step이 실행되지 않는 경우에는 StepExecution이 생성되지 않습니다. StepExecution은 Step이 실제로 시작될 때만 생성됩니다.
각 StepExecution에는 해당 Step 및 JobExecution과 관련된 참조와 함께, 커밋 및 롤백 횟수, 시작 및 종료 시간을 포함한 트랜잭션 관련 데이터가 포함됩니다. 또한, 각 StepExecution에는 ExecutionContext가 포함되어 있어 통계나 재시작 시 필요한 상태 정보와 같은 데이터를 배치 실행 간에 지속할 수 있도록 합니다. 아래 표는 StepExecution의 주요 속성에 대해 설명합니다.
Table 8. StepExecution Properties
Property | Definition |
Status | 실행 상태를 나타내는 BatchStatus 객체입니다. 실행 중에는 BatchStatus.STARTED, 실패 시 BatchStatus.FAILED, 성공적으로 종료될 경우 BatchStatus.COMPLETED입니다. |
startTime | 실행이 시작된 현재 시스템 시간(java.time.LocalDateTime)을 나타냅니다. Step이 아직 시작되지 않은 경우 이 필드는 비어 있습니다. |
endTime | 실행이 종료된 현재 시스템 시간(java.time.LocalDateTime)을 나타내며, 성공 여부에 관계없이 기록됩니다. 아직 Step이 종료되지 않은 경우 이 필드는 비어 있습니다. |
exitStatus | 실행 결과를 나타내는 ExitStatus입니다. 호출자에게 반환되는 종료 코드가 포함되어 가장 중요한 필드 중 하나입니다. |
executionContext | 실행 간에 유지되어야 하는 사용자 데이터를 포함하는 “속성 백(property bag)”입니다. |
readCount | 성공적으로 읽은 항목 수입니다. |
writeCount | 성공적으로 기록한 항목 수입니다. |
commitCount | 이 실행에서 커밋된 트랜잭션 수입니다. |
rollbackCount | Step에서 제어하는 비즈니스 트랜잭션이 롤백된 횟수입니다. |
readSkipCount | 읽기가 실패하여 항목이 건너뛰어진 횟수입니다. |
processSkipCount | 프로세스가 실패하여 항목이 건너뛰어진 횟수입니다. |
filterCount | ItemProcessor에 의해 “필터링된” 항목 수입니다. |
writeSkipCount | 기록이 실패하여 항목이 건너뛰어진 횟수입니다. |
StepExecution 속성들은 실행 상태를 완전히 파악하는 데 중요한 역할을 하며, 각 속성은 Step 실행의 모든 면을 기록하고 관리하는 데 사용됩니다.
ExecutionContext
ExecutionContext는 키/값 쌍을 모아 StepExecution 객체나 JobExecution 객체의 범위 내에서 상태를 유지하도록 설계된 컬렉션입니다. 이 컬렉션은 주로 실행 중 발생할 수 있는 치명적 오류나 시스템 장애(예: 정전) 상황에서도 재시작을 가능하게 하는 데 유용합니다. 예를 들어, 파일을 읽을 때 일정 지점에서 ExecutionContext에 현재 처리한 행 수와 같은 상태를 저장하고, 문제가 발생했을 경우 이 데이터를 기반으로 중단된 지점부터 다시 시작할 수 있습니다.
executionContext.putLong(getKey(LINES_READ_COUNT), reader.getPosition());
다음과 같은 상황을 가정해 봅시다. EndOfDayJob을 실행 중 하나의 Step인 loadData가 파일을 데이터베이스로 로드하는 작업을 수행하며 중단됩니다. 이 경우, 데이터베이스의 메타데이터 테이블에 실패한 상태와 함께 각종 정보가 기록됩니다.
Table 9. BATCH_JOB_INSTANCE
JOB_INST_ID | JOB_NAME |
1 | EndOfDayJob |
Table 10. BATCH_JOB_EXECUTION_PARAMS
JOB_INST_ID | TYPE_CD | KEY_NAME | DATE_VAL |
1 | DATE | schedule.Date | 2017-01-01 |
Table 11. BATCH_JOB_EXECUTION
JOB_EXEC_ID | JOB_INST_ID | START_TIME | END_TIME | STATUS |
1 | 1 | 2017-01-01 21:00 | 2017-01-01 21:30 | FAILED |
Table 12. BATCH_STEP_EXECUTION
STEP_EXEC_ID | JOB_EXEC_ID | STEP_NAME | START_TIME | END_TIME | STATUS |
1 | 1 | loadData | 2017-01-01 21:00 | 2017-01-01 21:30 | FAILED |
Table 13. BATCH_STEP_EXECUTION_CONTEXT
STEP_EXEC_ID | SHORT_CONTEXT |
1 | {piece.count=40321} |
이전 예시에서 Step은 총 30분간 실행되었고 40,321개의 “pieces”(이 경우 파일의 줄 수)를 처리했습니다. 이러한 값은 커밋 직전에 프레임워크에 의해 ExecutionContext에 업데이트됩니다. ExecutionContext는 커밋 시마다 StepListener 또는 ItemStream을 통해 업데이트될 수 있습니다. 이를 통해 Step이 커밋하기 전에 통지받아 필요한 데이터를 ExecutionContext에 저장하도록 설정할 수 있습니다. 이러한 데이터는 오류로 작업이 중단될 경우 재시작 시 활용됩니다.
다음 날 Job을 재시작하면, 이전 실행에서 저장된 ExecutionContext의 값이 데이터베이스에서 복원됩니다. 예를 들어, ItemReader가 열리면서 ExecutionContext에 저장된 마지막 처리 줄 수를 확인하고, 중단된 지점에서 다시 시작할 수 있습니다.
if (executionContext.containsKey(getKey(LINES_READ_COUNT))) {
log.debug("Initializing for restart. Restart data is: " + executionContext);
long lineCount = executionContext.getLong(getKey(LINES_READ_COUNT));
LineReader reader = getReader();
Object record = "";
while (reader.getPosition() < lineCount && record != null) {
record = readLine();
}
}
ExecutionContext는 각 JobExecution 및 StepExecution에 대해 고유하게 유지되는 중요한 상태 저장 기능입니다. 다음과 같은 코드 스니펫을 통해 ExecutionContext의 범위를 확인할 수 있습니다:
ExecutionContext ecStep = stepExecution.getExecutionContext();
ExecutionContext ecJob = jobExecution.getExecutionContext();
// ecStep과 ecJob은 서로 다른 ExecutionContext를 참조합니다.
여기서 ecStep과 ecJob은 각각 StepExecution 및 JobExecution에 대해 고유한 ExecutionContext를 제공합니다. 즉, StepExecution과 JobExecution 각각에 대해 독립적인 컨텍스트가 생성되며, Step마다 커밋 포인트에서 StepExecution 범위의 ExecutionContext에 상태가 저장됩니다. 이처럼 재시작 기능을 지원하기 위해 정확한 시점에 적절한 컨텍스트가 제공되도록 Spring Batch 프레임워크는 개발자가 일일이 신경 쓰지 않도록 관리해 줍니다.
주요 개념 정리
- 재시작 기능: ExecutionContext는 StepExecution에 따른 진행 상황을 관리하여 실패 시 마지막 상태에서 작업을 재개할 수 있게 합니다. 예를 들어, 텍스트 파일에서 특정 줄까지 읽었다면 그 줄 번호가 저장되어, 중단된 시점의 줄에서 재개가 가능합니다.
- 통계 및 상태 저장: 재시작을 위한 상태 저장뿐 아니라 통계 데이터, 예를 들어 주문 처리 수 등도 ExecutionContext에 저장할 수 있습니다. 이러한 데이터를 활용하여 작업 완료 시 보고 이메일을 보낼 수도 있습니다.
- 동일 JobInstance의 ExecutionContext 복원: 동일한 JobInstance가 재시작되면, 이전 실행의 ExecutionContext 데이터가 데이터베이스에서 복원되어 전달됩니다. 반면 새로운 JobInstance가 실행될 때는 빈 ExecutionContext가 제공됩니다.
- 키스페이스 공유 문제 주의: ExecutionContext는 동일한 키스페이스를 공유하므로, 데이터를 추가할 때는 고유 키를 사용하여 다른 데이터와 충돌하지 않도록 주의가 필요합니다.
ExecutionContext를 올바르게 사용하는 것은 실패 대비 및 데이터 유지 관점에서 매우 중요한 역할을 합니다. Spring Batch는 각 Job과 Step에 필요한 컨텍스트를 자동으로 관리하며, 필요 시 커스터마이징할 수 있는 유연성도 제공합니다.
JobRepository
JobRepository는 앞서 언급한 모든 스테레오타입을 위한 영속성 메커니즘입니다. JobLauncher, Job, 그리고 Step 구현체에 대한 CRUD 작업을 제공합니다. Job이 처음 실행될 때, JobExecution은 이 리포지토리에서 획득됩니다. 또한 실행 과정에서 StepExecution과 JobExecution 구현체는 리포지토리에 전달되어 영속화됩니다.
JobLauncher
JobLauncher는 주어진 JobParameters 세트를 사용해 Job을 실행하는 간단한 인터페이스를 나타내며, 다음 예제와 같이 사용할 수 있습니다:
public interface JobLauncher {
public JobExecution run(Job job, JobParameters jobParameters)
throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException;
}
구현체는 JobRepository에서 유효한 JobExecution을 가져와 Job을 실행합니다.
ItemReader
ItemReader는 Step을 위한 입력을 하나씩 가져오는 역할을 하는 추상화입니다. ItemReader가 제공할 수 있는 모든 항목을 소진하면 null을 반환하여 이를 알립니다. ItemReader 인터페이스 및 다양한 구현체에 대한 자세한 내용은 Readers And Writers 챕터에서 확인할 수 있습니다.
ItemWriter
ItemWriter는 Step의 출력을 한 번에 한 배치(batch) 또는 청크(chunk)로 처리하는 추상화입니다. 일반적으로 ItemWriter는 다음에 받을 입력에 대해 알지 못하며, 현재 호출 시 전달된 항목만 처리합니다. ItemWriter 인터페이스 및 다양한 구현체에 대한 자세한 내용은 Readers And Writers 챕터에서 확인할 수 있습니다.
ItemProcessor
ItemProcessor는 항목의 비즈니스 처리를 담당하는 추상화입니다. ItemReader는 항목을 읽고, ItemWriter는 항목을 쓰는 반면, ItemProcessor는 항목을 변환하거나 다른 비즈니스 처리를 적용할 수 있는 액세스 포인트를 제공합니다. 항목을 처리하는 중에 유효하지 않은 항목으로 판단되면 null을 반환하여 해당 항목이 기록되지 않도록 할 수 있습니다. ItemProcessor 인터페이스에 대한 자세한 내용은 Readers And Writers 챕터에서 확인할 수 있습니다.
Batch Namespace
앞서 언급한 많은 도메인 개념들은 Spring ApplicationContext에서 구성되어야 합니다. 위의 인터페이스에 대한 구현체를 표준 빈 정의에서 사용할 수 있지만, 설정을 더 쉽게 하기 위해 네임스페이스가 제공되었습니다. 다음 예제는 이를 보여줍니다:
<beans:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch
https://www.springframework.org/schema/batch/spring-batch.xsd">
<job id="ioSampleJob">
<step id="step1">
<tasklet>
<chunk reader="itemReader" writer="itemWriter" commit-interval="2"/>
</tasklet>
</step>
</job>
</beans:beans>
배치 네임스페이스가 선언되어 있는 한, 해당 네임스페이스의 모든 요소를 사용할 수 있습니다. Configuring and Running a Job에서 Job 구성에 대한 자세한 내용을 찾을 수 있으며, Configuring a Step에서 Step 구성에 대한 자세한 내용을 확인할 수 있습니다.
연관 글
- [Spring Batch][공식문서 번역] 5.1 변경 사항(What's New in Spring Batch 5.1)