이전에 스프링 부트 2버전과 3버전에서 스프링 배치 프로그램을 간단하게 작성했는데, 이번에는 메타데이터 스키마(테이블)을 한번 확인해볼 것이다.
프로젝트 설정은 이전 포스팅 설정을 그대로 사용한다.
메타데이터 스키마(Meta-Data Schema)
출처: Appendix B: Meta-Data Schema
스프링 배치는 Job과 Step의 실행 상태, 결과를 관리하기 위해서 메타데이터 스키마를 사용한다. 각 테이블은 배치 작업의 상태 정보를 저장하며, 표시된 테이블 외에도 키를 관리하기 위한 시퀀스 테이블들이 있다. JobRepository를 통해서 Job, Step의 실행 상태, 시간, 파라미터 정보 등을 저장하고 관리하게 된다.
각 테이블의 ID 값은 레코드를 식별하기 위한 PK(대체키)다.
그리고 BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION, BATCH_STEP_EXECUTION 테이블에 있는 VERSION 컬럼은 낙관적 락을 위해 존재하는 컬럼이다.
이 메타데이터 스키마는 직접 DB에 맞는 스키마를 생성할 수 도 있고 애플리케이션 설정 파일에 정의하여 자동으로 생성되게 할 수 있다.
메타데이터 스키마 생성
인텔리제이 기준에서 쉬프트 두 번으로 "schema-" 를 검색해서 사용하는 DB에 맞는 스키마를 찾을 수 있다.
외부 라이브러리에서 spring-batch-core 라이브러리를 직접 찾아도 된다.
그리고 application.yml 설정 파일을 통해서 생성하는 방법이 있다.
spring:
batch:
jdbc:
initialize-schema: always
프로퍼티 값에는 always, embedded, never가 있다.
- always: 애플리케이션이 시작될 때마다 메타데이터 테이블을 생성한다.
- embedded(기본값): 내장 데이터베이스를 사용할 때만 메타데이터 테이블을 생성한다.
- never 메타데이터 테이블을 생성하지 않는다.
이제 테이블들을 한번 확인해보자. 실행코드는 이전 포스팅 설정을 사용한다.
BATCH_JOB_INSTANCE 테이블
배치 작업의 인스턴스를 저장한다. 동일한 배치 작업을 여러 번 실행할 때, 각 배치 작업을 구분하는 테이블이다. 이 테이블에서 JOB_KEY 컬럼은 Job의 이름과 JobParameters의 조합으로 생성되는 직렬화된 값이다.
JobParameters가 없는 동일한 Job에 대해서 여러번 실행하면, 처음 실행된 Job의 정보면 레코드로 저장되고 이후 중복된 실행은 새로운 인스턴스가 생성되지 않는다. 같은 Job을 실행할 때 JobParameters값은 달라야 한다.
우선 JobParameters가 없을 때 데이터가 어떻게 저장되는지 확인해보자
코드에서 @JobScope는 Job의 실행 동안에만 빈이 유효하도록 설정하는 애노테이션이고, @StepScope는 Step 실행 동안에만 빈이 유효하도록 설정하는 애노테이션이다. Job과 Step 범위에서 빈의 라이프사이클을 정의하게 되고 Job과 Step이 끝나면 빈이 소멸되므로 메모리를 효율적으로 사용할 수 있다. 그리고 각 실행마다 새로운 빈을 생성하기 때문에 상태를 공유하지 않도록 할 수 있다.
코드를 실행 시 Job과 Setp에 대한 로그와 Tasklet의 로그까지 출력됐음을 확인할 수 있다.
BATCH_JOB_INSTANCE 테이블에도 실행한 Job이름으로 레코드가 하나 생성됐음을 확인했다.
이제 동일한 로직으로 애플리케이션을 다시 한 번 실행시켜본다.
애플리케이션 실행 시 "Step already complete or not restartable, so no action to execute..." 메시지가 출력되는 것을 볼 수 있다. 이미 실행한 작업이기 때문에 다시 시작할 Job이 없다는 것이다. Step과 Tasklet의 로그도 출력되지 않는 것을 볼 수 있다.
이번에는 JobParameters를 설정한 뒤 실행 결과를 확인해보자. ProgramArguments에 값을 설정해준다.
Program Arguments로 설정한 인자를 @Value 애노테이션을 사용해서 SpEL 문법으로 얻어올 수 있다.
로그를 확인해보면 읽어온 JobParameters의 batchDate 값이 잘 출력되는 것을 볼 수 있다.
그러면 동일한 Job을 실행할 때 JobParameters값도 같으면 어떻게 출력되는지 확인한다. 그대로 애플리케이션을 재실행한다.
코드를 실행하면 JobInstanceAlreadyCompleteException 이 발생한 것을 볼 수 있는데, 이미 완료된 Job 인스턴스를 동일한 JobParameters로 다시 실행했을 때 발생하는 예외다.
스프링 배치는 기본적으로 Job이 동일한 JobParameters로는 한 번만 실행된다.
테이블에도 하나의 레코드만 존재하는 것을 확인할 수 있다.
JobParameters의 batchDate를 변경해서 다시 실행해본다.
로그에 변경된 JobParameters의 batchDate가 출력되고 테이블의 레코드도 하나 추가된 것을 확인할 수 있다.
동일한 Job에서 동일한 JobParameters를 사용하면서 Job 인스턴스를 생성하는 방법은 JobParameters에 고유하게 식별 가능한 값을 생성하면 된다.
아래는 JobBuilderFactory에서 제공하는 incrementer 메서드로 id를 추가하는 방법이다.
RunIdIncrementer는 Job 실행 시 고유한 run.id 값을 생성해서 JobParameters에 추가해서 각 실행을 고유하게 식별할 수 있게 해준다. 이 때 테이블은 초기화하고 처음부터 실행하자.
BATCH_JOB_EXECUTION 테이블
배치 작업 인스턴스의 실행 정보를 저장하는 테이블이다. Job에 대한 시작 시간(START_TIME), 종료 시간(END_TIME), 상태(STATUS), 종료 코드(EXIT_CODE) 등의 정보를 저장한다.
종료 시간은 성공 또는 실패와 상관없이 실행이 완료된 시간을 나타낸다.
BATCH_JOB_EXECUTION_CONTEXT 테이블
배치 작업 실행 시의 컨텍스트 정보를 저장한다. 각 Job 간의 공유할 데이터나 정보들을 저장할 수 있는데 JobExecution객체에서 ExecutionContext를 찾아서 상태 정보를 저장하고 사용할 수 있다.
BATCH_JOB_EXECUTION_PARAMS 테이블
배치 작업 실행 시 사용된 파라미터 정보를 저장한다. 이 테이블에서 JobParameters가 어떤 것들이 사용됐는지 확인할 수 있다.
BATCH_STEP_EXECUTION 테이블
배치 작업의 Step 정보를 저장한다. 각 Step의 시작 시간(START_TIME), 종료 시간(END_TIME), 실행 상태(STATUS), 커밋 횟수(COMMIT_COUNT), 읽은 아이템 수(READ_COUNT), 필터링된 아이템 수(FILTER_COUNT), WRITER_COUNT(작성된 아이템 수), 배치 종료 코드(EXIT_CODE) 등의 정보를 저장한다.
각 컬럼이 아직 이해되지 않아도 이후에 Chunk를 사용하면 하나씩 알게될 것이다.
BATCH_STEP_EXECUTION_CONTEXT 테이블
배치 작업 실행 시의 컨텍스트 정보를 저장한다. 각 Step 간의 공유할 데이터나 정보들을 저장할 수 있는데 StepExecution객체에서 ExecutionContext를 찾아서 상태 정보를 저장하고 사용할 수 있다.
메타데이터 스키마는 스프링 배치를 사용하면서 Job을 실행하면서 확인해보면 어렵지 않게 이해할 수 있다.
다음에는 Chunk를 사용하면서 ItemReader, ItemProcessor, ItemWriter를 사용해볼 것이다.
'Spring' 카테고리의 다른 글
Spring Rest Docs 사용하기 (0) | 2024.08.23 |
---|---|
[Spring Batch] JobParameters와 검증(JobParametersValidator) (2) | 2024.07.21 |
[Spring Batch] Chunk 지향 처리 (0) | 2024.07.19 |
[Spring Batch] 스프링 배치 개념 및 사용해보기 (0) | 2024.07.14 |
Spring MVC 동작 구조 및 순서 (1) | 2024.05.06 |