[1회차] SpringBatch 빠르게 시작하기

아래 글은 한국 스프링 사용자 모임(KSUG)에서 진행된 스프링 배치 스터디 내용을 정리한 게시글입니다.
DEVOCEAN에 연재 중인 KIDO님의 글을 참고하여 실습한 내용을 기록했습니다.

 

 

[SpringBatch 연재 01] SpringBatch 빠르게 시작하기

 

devocean.sk.com

원본: [SpringBatch 연재 01] SpringBatch 빠르게 시작하기

 

1. 기본 프로젝트 구성하기

Spring Batch 의존성 추가

@EnableBatchProcessing // 해당 애노테이션을 사용하면 배스프링 배치 모드로 동작하게 된다.
@SpringBootApplication
public class BatchSampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(BatchSampleApplication.class, args);
    }

}

 

2. 실행해보기

./gradlew bootRun

명령을 통해 실행 하면 아래의 오류와 함께 실패합니다.

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

해당 메시지는 Spring Boot에서 데이터베이스(DataSource) 설정을 찾지 못했음을 의미합니다.

 

DataSource를 구성 해보겠습니다.

 

3. DataSource 구성하기

실습을 위해 MemoryDB를 활용해보겠습니다.

 

MemoryDB에는 H2, HSQL, Apache Derby 가 존재합니다.

각각의 특징은 다음과 같습니다.

 

데이터베이스 특징
H2 Database - 메모리 데이터베이스 - 주로 테스트 및 개발 전용으로 사용 - 경량/빠른 속도 - 자체 웹 콘솔 제공
HSQL Database - 경량 데이터베이스 - 메모리 또는 파일 기반 데이터 저장 - 자바 기반 - SQL-92 호환
Apache Derby Database - 자바 기반 데이터베이스 - 네트워크 및 임베디드 모드 - 트랜잭션 지원(ACID 제공)

 

이 중 간단하게 사용하기 위해 H2 데이터베이스를 사용해 보겠습니다.

 

이를 위해 build.gradle에 의존성을 추가하고 applicaion.yaml 파일에 설정을 추가합니다.

# build.gradle 의존성 추가
implementation 'com.h2database:h2:2.2.224'
# application.yaml
spring:
  datasource:
    hikari:
      maximum-pool-size: 10
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password: password

해당 설정을 마치고 동일한 명령어로 실행을 해보면 오류 없이 실행됨을 확인할 수 있습니다.

 

4. 들어가기 전 용어 알기 - 배치 작업에서 인스턴스와 파라미터란?

4.1. 인스턴스(Instance)란?

인스턴스는 특정 배치 작업이 실행된 결과물을 의미합니다. 예를 들어, 데이터 백업 배치 작업을 매일 한 번씩 실행한다고 가정해 봅시다. 이때 매일 실행된 각각의 배치 작업을 인스턴스라고 부를 수 있습니다. 즉, 배치 작업을 한 번 실행할 때마다 그에 대한 인스턴스가 생성됩니다.

같은 배치 작업이라도 여러 번 실행할 수 있기 때문에, 각 실행을 구분하기 위해 인스턴스를 사용합니다. Spring Batch에서는 이 인스턴스를 관리하여 작업의 중복 실행을 방지하고, 과거의 실행 내역을 확인할 수 있습니다.

 

4.2. 파라미터(Parameters)란?

파라미터는 배치 작업을 실행할 때 함께 전달되는 입력 값입니다. 배치 작업이 어떻게 동작해야 할지를 결정하는 데 중요한 역할을 합니다. 예를 들어, 특정 날짜의 데이터를 백업하는 배치 작업이 있을 때, 백업할 날짜를 파라미터로 전달하여 그 날짜의 데이터를 처리하게 됩니다.

같은 배치 작업이라도 파라미터에 따라 작업의 결과가 달라질 수 있으며, 파라미터는 Spring Batch가 인스턴스를 구분하는 기준이 됩니다.

 

4.3. 인스턴스와 파라미터의 관계

같은 배치 작업이라도 파라미터가 다르면 다른 인스턴스가 생성됩니다. 예를 들어, 2023-10-01 데이터를 백업하는 작업과 2024-10-05 데이터를 백업하는 작업은 파라미터가 다르기 때문에 서로 다른 인스턴스로 관리됩니다. 이렇게 Spring Batch는 파라미터를 기반으로 인스턴스를 관리하며, 이를 통해 중복 작업 실행을 방지하고 배치 작업을 체계적으로 운영할 수 있습니다.

 

5. Spring Batch 스키마 구조

스프링 배치를 수행하면 자동으로 배치를 위한 스키마가 생성이 됩니다.
아래는 해당 스키마 구조입니다.

spring docs(Meta-Data Schema) 참고: https://docs.spring.io/spring-batch/reference/schema-appendix.html

 

각 테이블들의 역할을 살펴 보겠습니다.

 

5.1. BATCH_JOB_INSTANCE Table

  • Spring Batch에서 배치 작업의 인스턴스를 관리하기 위해 사용되며, 가장 기본이 되는 테이블입니다.
  • 배치가 수행되면 Job이 생성되고, 해당 Job 인스턴스에 대해서 관련된 모든 정보를 가진 최상위 테이블입니다.이 테이블을 통해 Spring Batch는 배치 작업의 실행 내역을 관리하고, 동일한 작업이 중복으로 실행되지 않도록 제어할 수 있습니다.
CREATE TABLE BATCH_JOB_INSTANCE  (
  JOB_INSTANCE_ID BIGINT  PRIMARY KEY ,    -- 배치 작업 인스턴스의 고유 ID. JobInstance 객체의 getId로 획득 가능
  VERSION BIGINT,                        -- 이 테이블의 버전 관리 정보.
  JOB_NAME VARCHAR(100) NOT NULL ,        -- 배치 작업의 이름. 인스턴스를 식별하기 위해 필요함. 
  JOB_KEY VARCHAR(32) NOT NULL            -- 파라미터를 기반으로 생성된 고유 키. JobParameter를 직렬화한 데이터값.
);

 

5.2. BATCH_JOB_EXECUTION_PARAMS Table

  • 배치 작업이 실행될 때 사용된 파라미터들을 저장하는 테이블입니다.
  • 하나 이상의 key/value 쌍으로 Job에 전달됩니다.
  • 각 파라미터는 IDENTIFYING이 true로 설정되면, 배치 작업 인스턴스 생성시 유니크한 값으로 사용된 경우라는 의미가 됩니다.
  • 테이블은 비정규화 되어 있으며, 구조는 다음과 같습니다.
--   참고로 이 테이블에는 기본키가 없다.
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS  (
	JOB_EXECUTION_ID BIGINT NOT NULL ,		-- BATCH_JOB_EXECUTION으로 부터 온 외래키. 각 실행마다 여러 행(키/값)이 저장됨
	PARAMETER_NAME VARCHAR(100) NOT NULL ,	-- 파라미터 이름  
	PARAMETER_TYPE VARCHAR(100) NOT NULL ,	-- 파라미터 타입  
	PARAMETER_VALUE VARCHAR(2500) ,			-- 파라미터 값  
	IDENTIFYING CHAR(1) NOT NULL ,			-- 해당 파라미터가 배치 작업 인스턴스를 구분하는 데 사용되는지 여부  
	constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
	references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
);
❗️로그 테이블이나 임시 데이터를 저장하는 경우 기본 키를 만들지 않는 경우가 있다. BATCH_JOB_EXECUTION_PARAMS 테이블의 경우 파라미터 값만 기록하는 용도로, 기본 키 대신에 JOB_EXECUTION_ID와 파라미터 이름(KEY_NAME)의 조합을 통해 각 레코드를 고유하게 식별할 수 있기 때문에 기본 키 없이도 테이블이 설계될 수 있다.

 

5.3. BATCH_JOB_EXECUTION Table

  • 이 테이블은 배치 작업의 각 실행을 관리하는 핵심적인 테이블로, 작업의 실행 상태와 결과를 추적하는 데 사용됩니다.
  • 배치 작업의 실행 내역을 기록하는 테이블입니다.
CREATE TABLE BATCH_JOB_EXECUTION  (
  JOB_EXECUTION_ID BIGINT  PRIMARY KEY ,    -- 배치자 실행 ID. 실행을 구분할 수 있음.
  VERSION BIGINT,                            -- 버전 정보
  JOB_INSTANCE_ID BIGINT NOT NULL,            -- BATCH_JOB_INSTANCE 테이블의 기본키(외래키). 하나의 인스턴스에는 여러 execution이 있을 수 있음
  CREATE_TIME TIMESTAMP NOT NULL,            -- 이 실행 레코드가 생성된 시간(execution이 생성된 시간)
  START_TIME TIMESTAMP DEFAULT NULL,        -- 배치 작업이 실행을 시작한 시간(execution이 시작된 시간)
  END_TIME TIMESTAMP DEFAULT NULL,            -- 배치 작업이 종료된 시간. 실패해도 남음. 실행중이 아닐때 열의 값이 비어 있다면, 특정 유형의 오류가 발생하여 프레임워크가 실패하기전 마지막 저장을 수행할 수 없음을 나타낸다.
  STATUS VARCHAR(10),                        -- 배치 작업의 실행 상태. COMPLETED, FAILED, STARTING, STOPPED 등(BatchStatus)
  EXIT_CODE VARCHAR(20),                    -- 배치 작업이 종료될 때의 결과 코드(성공/실패 기록)
  EXIT_MESSAGE VARCHAR(2500),                -- 작업 종료 시 메시지를 기록. 주로 작업 실패 시 원인 또는 에러 메시지를 담음
  LAST_UPDATED TIMESTAMP,                    -- 배치 작업의 상태가 마지막으로 업데이트된 시간(마지막으로 지속된 시간)
  constraint JOB_INSTANCE_EXECUTION_FK foreign key (JOB_INSTANCE_ID)
  references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;

 

5.4. BATCH_STEP_EXECUTION Table

  • 배치 작업 내 각 스텝(step)의 실행 내역을 기록하는 테이블입니다.
  • BATCH_JOB_EXECUTION 테이블과 유사합니다.
  • 배치 작업은 한 개 이상의 스텝으로 구성될 수 있으며, 각 스텝은 독립적으로 실행되며 성공 또는 실패 상태를 가질 수 있습니다.
CREATE TABLE BATCH_STEP_EXECUTION  (
  STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,    -- 각 스텝의 고유 ID
  VERSION BIGINT NOT NULL,                            -- 버전정보
  STEP_NAME VARCHAR(100) NOT NULL,                    -- 스텝의 이름. 어떤 스템이 실행되었는지 구분하는 이름
  JOB_EXECUTION_ID BIGINT NOT NULL,                    -- 스텝이 속한 배치 작업 실행(JobExcution)의 ID. BATCH_JOB_EXECUTION 테이블에 대한 외래키
  CREATE_TIME TIMESTAMP NOT NULL,                    
  START_TIME TIMESTAMP DEFAULT NULL ,                -- 스텝 실행이 시작된 시간
  END_TIME TIMESTAMP DEFAULT NULL,                    -- 스텝 실행이 종료된 시간
  STATUS VARCHAR(10),                                -- 스텝의 실행 상태. STARTING, COMPLETED, FAILED, STOPPED 등
  COMMIT_COUNT BIGINT ,                                -- 스텝 실행 중 커밋된 횟수를 기록
  READ_COUNT BIGINT ,                                -- 스텝 실행 중 읽은 데이터의 수
  FILTER_COUNT BIGINT ,                                -- 스텝 실행 중 필터링된 데이터의 수
  WRITE_COUNT BIGINT ,                                -- 스텝 실행 중 기록된 데이터의 수
  READ_SKIP_COUNT BIGINT ,                            -- 읽기 단계(ItemReader)에서 스킵된 데이터의 수
  WRITE_SKIP_COUNT BIGINT ,                            -- 쓰기 단계(ItemWriter)에서 스킵된 데이터 수
  PROCESS_SKIP_COUNT BIGINT ,                        -- 데이터 처리(프로세싱, ItemProcessor) 중 발생한 문제로 인해 스킵된 데이터의 수
  ROLLBACK_COUNT BIGINT ,                            -- 스텝 실행 중 롤백이 발생한 횟수
  EXIT_CODE VARCHAR(20) ,                            -- 스텝이 종료될 때의 결과 코드.(성공/실패 여부 판별)
  EXIT_MESSAGE VARCHAR(2500) ,                        -- 스텝이 실패하거나 종료될 때 관련된 메시지 기록. 주로 오류 메시지나 로그를 담음.
  LAST_UPDATED TIMESTAMP,                            -- 마지막으로 지속된 시간
  constraint JOB_EXECUTION_STEP_FK foreign key (JOB_EXECUTION_ID)
  references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

이때, '데이터'란 배치 작업이 처리하는 대상 데이터를 의미합니다. 이 데이터는 ItemReader(ItemProcessor, ItemWriter 등이 될 수 있음)가 소스로부터 읽어온 레코드, 데이터베이스의 한 행(row), 파일의 한 줄(line), 메시지 큐의 메시지 등 처리 대상이 되는 구체적인 데이터 단위를 말합니다.

 

5.5. BATCH_JOB_EXECUTION_CONTEXT Table

  • 배치 작업 실행 중인 컨텍스트 정보(ExecutionContext)를 저장하는 테이블입니다.
  • 배치 작업을 실행하면서 발생하는 다양한 상태 정보나 중간 데이터를 컨텍스트(Context)로 관리합니다.
  • 이 정보를 통해 작업의 종료 상태를 저장하고, 재시작 시 이전 상태를 복원할 수 있습니다. 또한, 여러 스텝 간 데이터를 공유하거나 작업간 필요한 정보를 안전하게 저장하고 유지할 수 있습니다.
CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT  (
  JOB_EXECUTION_ID BIGINT PRIMARY KEY,        -- JOB_EXECUTION_ID 테이블에 대한 외래키. 어떤 배치 작업 실행에 대한 컨텍스트 정보인지 연결.
  SHORT_CONTEXT VARCHAR(2500) NOT NULL,        -- 컨텍스트 데이터를 저장하는 JSON 또는 문자열 형태의 간단한 표현(SERIALIZED_CONTEXT 의 문자로된 버전)
  SERIALIZED_CONTEXT CLOB,                    -- 컨텍스트 데이터를 직렬화된 형태로 저장하는 필드. 복잡한 객체나 상태 정보가 포함될 수 있음
  constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
  references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;

 

6. Spring Batch Sequences

스프링배치는 기본적으로 시퀀스 테이블이 존재합니다.


"Sequences" 는 데이터베이스에서 고유한 ID 값을 생성하기 위한 시퀀스 객체를 의미합니다. Spring Batch Sequences는 별도의 테이블이 아니라 데이터베이스가 고유 ID를 생성하는 방식을 의미하며, Spring Batch의 주요 테이블(BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION, BATCH_STEP_EXECUTION 등)에서 고유한 ID를 부여하기 위해 사용됩니다.

 

6.1. Spring Batch에서 사용하는 시퀀스 테이블 종류

몇 가지 시퀀스 테이블을 살펴 보겠습니다.

시퀀스 이름 역할
BATCH_JOB_SEQ BATCH_JOB_INSTANCE 테이블에서 고유 ID(JOB_INSTANCE_ID)를 생성하는 시퀀스
BATCH_JOB_EXECUTION_SEQ BATCH_JOB_EXECUTION 테이블에서 고유 ID(JOB_EXECUTION_ID)를 생성하는 시퀀스
BATCH_STEP_EXECUTION_SEQ BATCH_STEP_EXECUTION 테이블에서 고유 ID(STEP_EXECUTION_ID)를 생성하는 시퀀스

정리

  • 스프링 배치를 위한 가장 기본적인 설정을 해보았습니다.
  • 스프링 배치는 자체 배치 작업을 수행하기 위해 @EnableBatchProcessor를 사용하면 배치를 위한 테이블이 실행시 자동 생성됩니다.
  • 자동 생성된 각 테이블들을 살펴 보았고, 어떤 데이터가 저장되는지 확인 했습니다.