Spring Batch를 공부하기 전에 우선 Batch 용어에 대해 살펴보도록 하겠습니다.
배치(Batch)란 데이터를 실시간으로 처리하는 게 아니라, 일괄적으로 모아서 한꺼번에 처리하는 작업을 의미합니다.
예를 들어, 하루 동안 쌓인 데이터들 등 대용량 데이터를 배치 작업을 통해 특정 시간에 한꺼번에 처리하는 경우가 이에 해당합니다. 은행의 정산 작업과 같은 업무에서 이런 일괄 처리를 수행하게 되며 사용자에게 빠른 응답이 필요하지 않은 서비스에 적용할 수 있습니다.
배치 작업은 사전에 정의된 순서에 따라 자동으로 실행되며, 일반적으로 사용자의 개입 없이 자동으로 처리됩니다. 이를 통해 효율적으로 대용량 데이터를 처리할 수 있기 때문에, 시스템 자원을 절약하고 작업을 최적화하는데 상당한 도움을 줍니다.
자동화 : 작업들이 사전에 프로그램된 스케줄에 따라 사용자 개입없이 자동으로 실행됩니다.
대용량 데이터 처리 : 대용량 데이터를 처리하거나 복잡한 계산을 수행하는데 적합합니다.
비동기 실행 : 배치 작업은 보통 백그라운드에서 실행되며, 다른 프로세스와 동시에 실행될 수 있습니다.
효율적인 리소스 사용 : 시스템의 비활성 시간에 배치 작업을 스케줄하여 리소스를 효율적으로 사용할 수 있습니다.
Spring Batch
는 대량의 데이터를 처리하기 위한 경량화된 프레임워크로, 반복적인 작업을 수행하는 일괄 처리(Batch Processing) 작업을 효율적으로 처리할 수 있는 기능을 제공해줍니다.
기본적으로 로깅/추적, 트랜잭션 관리, 작업 처리 통계, 작업 재시작, 작업 건너뛰기, 리소스 관리
등 대용량 데이터를 처리하는데 필수적인 기능을 제공해줍니다.
또한 최적화 및 파티셔닝 기술을 통해 대용량 및 고성능 배치 작업을 가능하게 하는 고급 기술 서비스를 제공해주기도 합니다.
Spring Batch
를 사용하면 Chunk
기반의 처리 모델을 사용하여 데이터를 작은 단위의 Chunk
로 나누고 각 Chunk
를 순차적 혹은 병렬적으로 처리할 수 있습니다.
쉽게 말해 전체를 작은 단위의 조각으로 나눠 처리한다는 얘기입니다. Chunk
단위로 데이터를 커밋할 수 있기 때문에 해당 작업이 실패할 시 해당 Chunk
만 롤백하고 재처리할 수 있는 용이성을 제공해줍니다.
Chunk
기반의 처리 방식은 메모리 사용량을 관리하고 처리 속도를 최적화하는데 상당한 도움을 줍니다.
멀티 쓰레드, 병렬 처리, 원격 분산 처리
를 포함한 고급 배치 처리 기능을 지원하여 대규모 데이터를 효율적으로 신속하게 처리할 수 있으며, 시스템 리소스 또한 효율적으로 활용할 수 있게 도와줍니다.
실패한 배치 작업을 자동으로 재시작하거나, 특정 조건에 따라 데이터를 건너뛸 수 있는 기능을 제공해줍니다.
데이터베이스와의 효율적인 상호 작용을 위해 JDBC 배치 연산을 사용하여 여러 개의 쿼리를 하나의 배치로 그룹화하여 처리해줍니다.
이를 통해 네트워크 비용을 줄이고, 데이터베이스의 커넥션 사용을 최적화하여 전체 처리 성능을 향상시킬 수 있습니다.
배치 처리(Batch Processing)는 여러 개의 데이터베이스 쿼리나 트랜잭션을 그룹화하여 한 번에 처리하는 기술입니다.
개별 쿼리를 하나씩 순차적으로 실행하는 것보다 데이터베이스와의 통신 오버헤드를 줄이고 성능을 향상시키는데 사용됩니다.
쉽게 말해, DB와의 커넥션을 연결한 상태에서 그룹화한 쿼리를 한꺼번에 실행시키는 작업입니다.
벌크 연산(Bulk Operations)은 대량의 데이터에 대해 단일 쿼리나 명령을 실행하여, 한 번의 데이터베이스 호출로 많은 양의 데이터를 처리하는 기술입니다.
대량의 데이터를 삽입, 갱신, 삭제할 때 유용하며, 이 과정에서 데이터베이스 엔진이 최적화를 수행할 수 있어 성능적인 이점을 제공해줍니다.
내부적으로 데이터베이스 엔진에 의해 최적화 되어, 전체 작업에 대한 처리 시간을 크게 단축시킬 수 있습니다.
배치 처리(Batch Processing)는 주로 애플리케이션 레벨에서 데이터베이스 쿼리를 최적화하는 방식입니다.
여러 개의 쿼리를 한 번에 데이터베이스로 보내어 처리함으로써 네트워크 지연 시간과 데이터베이스 호출 오버헤드를 줄일 수 있죠.
반면, 벌크 연산(Bulk Operations)은 데이터베이스 레벨에서의 최적화를 의미하며, 대량의 데이터를 한 번의 연산으로 처리할 수 있게 해줍니다. 데이터베이스 엔진에 의해 내부적으로 처리되므로, 종종 배치 처리(Batch Processing)보다 더 빠른 성능을 제공합니다.
배치 처리 과정을 하나의 단위로 만들어 놓은 객체를 의미합니다. 배치 처리 과정에 있어 전체 계층의 최상단에 위치하고 있습니다.
특정 Job
이 실행될 때마다 생성되는 논리적 실행 단위를 의미합니다.
Job
설정과 입력 파라미터의 조합으로 정의되며, Job
이 실행될 때마다 새로운 JobInstance
가 생성될 수 있습니다. Job
파라미터에 의해 결정되는 고유한 비즈니스 식별자를 가지고 있습니다.
만약 같은 파라미터로 Job을 실행하려고 하면, Spring Batch
는 이미 존재하는 JobInstance
을 재사용합니다.
예시를 한번 들어보겠습니다.
매일 실행되는 배치 작업이 있고, 실행될 때마다 해당 날짜를 파라미터로 전달한다고 가정했을 때 1월 1일에 실행되었을 때의 파라미터와 1월 2일에 실행되었을 때의 파라미터가 서로 다르기 때문에, 각각의 실행에 대해 별도의 JobInstance
가 생성됩니다.
생성된 JobInstance
는 그 실행에 대한 상태 정보(성공, 실패 등)를 관리하게 됩니다. 만약 1월 1일 실행한 JobInstance
가 실패하여 다시 실행한다면, 같은 JobInstance
에 대한 재시도로 간주되며, 동일한 JobInstance
내에서 새로운 JobExecution
(실행)이 발생됩니다.
JobParameters
는 JobInstance
에 전달되는 매개변수를 의미합니다. 이를 통해 JobInstance
객체를 구별할 수 있고 String, Double, Long, Date
4가지 형식을 지원하고 있습니다.
JobExecution
은 JobInstance
의 실행 시도에 대한 객체를 말합니다.
예를 들어, 1월 1일에 실행한 JobInstance
가 실패하여 재실행을 하여도 동일한 JobInstance
를 실행시키지만 2번의 실행에 대한 JobExecution
은 개별로 생기게 됩니다.
JobExecution
은 JobInstance
실행에 대한 상태, 시작시간, 종료시간, 생성시간 등의 정보를 담고 있습니다.
Step
은 Job
의 세부 실행 단위를 의미합니다. Job
내에서 하나의 작업 단위 또는 배치 처리 단계를 캡슐화하는데 사용됩니다.
Job
은 최소한 1개 이상의 Step
을 가져야 하며 Job
은 이러한 여러 Step을 조정하고 관리하는 역할을 하며, 전체적인 일괄 처리 흐름을 제어합니다.
각 Step
은 데이터 읽기(Read), 처리(Process), 쓰기(Write) 등의 배치 처리 과정을 정의합니다. 일반적으로 ItemReader
, ItemProcessor
, ItemWriter
의 세 부분으로 구성되며 각각 데이터를 읽고, 처리하고, 쓰는 역할을 담당합니다.
StepExecution
은 Step
의 한번 실행을 나타내는 객체를 의미합니다.
JobExecution
이 Job
의 한번 실행을 나타내듯, StepExecution
은 특정 Step
의 실행 정보와 상태(성공, 실패 등) 등 상세 정보가 저장됩니다.
읽은 항목의 수, 쓴 항목의 수, 커밋된 트랜잭션의 수, 스킵된 항목의 수
등을 포함하고 이 정보를 통해 배치 처리의 성능과 결과를 분석할 수 있습니다.`
만약 Job
이 여러 Step
으로 구성되어 있고, 어떤 Step
에서 실패한다면, 해당 Step
이후의 Step
들은 실행되지 않습니다.
또한 StepExecution
은 실제로 Step
이 실행될 때만 생성되므로, 실패로 인해 실행되지 않은 Step
에 대한 StepExecution
은 생성되지 않습니다.
ExecutionContext
은 Job
에서 데이터를 공유할 수 있는 데이터 저장소입니다.
Spring Batch
에서 제공하는 ExecutionContext
는 JobExecutionContext
, StepExecutionContext
2가지 종류가 있습니다.
JobExecutionContext
의 경우 Commit 시점에 저장되며 StepExecutionContext
의 경우 실행 사이에 저장됩니다.
ExecutionContext
를 통해 Step
간 데이터 공유가 가능하며 Job
실패 시 ExecutionContext
를 통해 마지막 실행 값을 재구성할 수 있습니다.
JobRepository
는 모든 배치 처리 정보를 담고 있는 메커니즘입니다. Job
이 실행되면 JobRepository
에 JobExecution
과 StepExecution
을 생성하게 되며 JobRepository
에서 Execution
정보들을 저장하고 조회하여 사용할 수 있습니다.
JobLauncher
은 Job
과 JobParameters
를 입력으로 받아서 Job
을 실행하는 객체를 의미합니다.
ItemReader
는 Step
에서 Item
을 읽어오는 역할을 하는 인터페이스입니다. 다양한 방법으로 데이터 소스(Ex: 데이터베이스, 파일, 큐 등)에서 데이터(Item
)을 읽어올 수 있습니다.
ItemWriter
는 처리된 데이터를 Write
할 때 사용됩니다. 처리된 데이터들을 최종 목적지(Ex: 데이터베이스, 파일, 다른 시스템)에 저장하거나 전송하는데 사용됩니다.
Writer
는 다양한 인터페이스가 존재하고 기본적으로 데이터(Item
)를 Chunk
단위로 묶어 일괄적으로 처리합니다.
ItemProcessor
는 Reader
에서 읽어온 데이터(Item
)에 대해 필요한 처리(변환, 필터링, 검증 등)를 수행하는 역할을 합니다.
Processor
는 배치를 처리하는데 필수 요소는 아닙니다.
Tasklet
은 하나의 메서드로 구성 되어 있는 간단한 인터페이스입니다.
Tasklet
의 execute
메서드는 반환값으로 RepeatStatus
를 반환합니다. 일반적으로 작업이 성공적으로 완료되면 RepeatStatus.FINISHED
를 반환하고 같은 Tasklet
을 다시 실행하려면 RepeatStatus.CONTINUABLE
를 반환합니다.
만약 작업 실행 중에 예외가 발생하면, 예외를 throw하여 실패를 알립니다.
Tasklet
은 주로 단일 작업이나 간단한 작업을 수행할 때 유용합니다. 예를 들어 배치 작업 전에 데이터베이스를 초기화하거나, 파일을 다운로드 하는 등의 작업에 적합합니다.
Chunk
는 데이터를 한 번에 하나씩 읽어서 처리한 후, 설정된 Chunk
크기 만큼의 데이터가 모이면 이를 일괄적으로 처리하는 방식입니다. 해당 과정은 ItemReader
, ItemProcessor
, ItemWriter
를 통해 이루어집니다.
일반적으로 대용량 데이터라 할지라도 ItemReader
는 데이터를 모두 한 번에 메모리에 로드하지 않습니다. 대신, 한 번에 하나의 Item
을 읽거나, 설정된 Chunk
크기만큼 데이터를 순차적으로 읽어서 처리 과정으로 넘기게 됩니다.
ItemReader
로부터 받은 각 Item
에 대해 필요한 처리(변환, 필터링 등)를 수행하게 됩니다. ItemProcessor
의 처리는 기본적으로 Item
단위로 이루어지기 때문에 ItemReader
로부터 받은 각 Item
을 하나씩 처리하게 됩니다.
즉, Chunk
단위로 데이터를 읽더라도, 처리 자체는 각 Item
마다 개별적으로 실행됩니다.
ItemWriter
는 처리된 데이터를 Chunk
크기만큼 모아서 일괄적으로 데이터베이스에 저장 혹은 전송하게 됩니다.
앞서 설명했던 세 가지 과정은 모든 데이터가 처리될 때까지 반복됩니다.
참고로 Spring Batch Reader
에서는 Paging
처리를 지원하고 있습니다.
예를 들어 Paging Size
가 5이며, Chunk Size
가 10일 경우 2번의 Read
가 이루어진 후에 1번의 Transaction
이 수행되게 됩니다.
참고 자료
JungChihoon님의 [한 줄 용어]배치(Batch)란?
히진쓰의 서버 사이드 기술 블로그
무명소졸의 웹개발 블로그