스프링 배치 필기노트

devswansong·2025년 3월 22일

패스트캠퍼스 스프링 배치 관련 강의를 듣고 개인적으로 정리한 글입니다.

현재 시점에서 필요하지 않는 기술로 판단되어 추가 공부는 보류

배치란

배치 작업 예시

  • 예약 시간에 광고성 메시지 발송
  • 결제 정산 작업
  • 운영을 위해 필요한 통계 데이터 구축
  • 대량 데이터를 필요로 하는 모델 학습 작업

배치는 실시간성이 아닌 데이터를 일괄처리하는 작업

작업 특성 상 일괄적으로 해야할 수 있다.

자원을 효율적으로 사용할 수 있는 것도 이유 중 하나이다.

주간, 월간 보고를 해야한다면 실시간으로 매번 그 데이터들을 처리하기 보단 주나 월마다 일괄적으로 데이터 처리하는게 나을 수 있다. (데이터 처리 시에만 고성능 하드웨어를 빌리면 된다.)

하나의 예시로 100만건 수준의 데이터를 Export 해줘야할 때 이 데이터 csv 로 만들어준다고 유저가 아무것도 못하게 하면 안된다. 그래서 백그라운드로 처리한 뒤 완료되면 사용되게끔 할 수 있다.


스케쥴링과 배치 개념도 좀 잘 구분해야한다.

만약 서버에서 배치 하나만 돌릴 수 있고 그 하나의 작업이 너무 오래 걸린다면 내가 추가하고싶은 작업은 실행하지도 못한다.

그래서 작업이 끝나고 예약해서 작업을 할 수 있게도 할 수 있다.

스프링 배치

  • 스프링 배치를 쓰는 이유는 스프링에서 제공하는 특성을 그대로 쓸 수 있기 때문이다.

  • 스프링, 자바다 보니 플랫폼 종속적이지 않고 스프링의 DI를 이용한 객체결합 구성, AOP 를 이용한 부가적인 역할 분리 등 장점을 가져온다. 테스트에서도 잘 지원한다.

  • 데이터 신뢰성도 높다 스프링 배치에는 다양한 데이터 수치가 있는데 우리 로그와 그 수치들을 합쳐서 어떠한 이유로 이런 데이터 결과가 나왔는지 확인이 가능하다. 이런 걸 통해 데이터 신뢰성을 지킬 수 있다.

  • 배치와 스케쥴러는 다른 개념

  • 특정 시간, 이벤트에 실행되는 방식은 없어 쿼츠 같은 걸로 스프링 기능으로 할 순 있지..

  • 세 가지 레이어 존재

  • Application : 사용자 코드 및 구성

  • 배치 처리를 위한 사용자의 코드 (배치 코어, 인프라도 사용자가 커스텀 할 수 있어)

    • Core : Job, Step, JobLauncher, JobParameter
    • Infrastructure : File, DB (데이터를 읽고 쓸 수 있는 리더 라이터를 가진다.)

설계

각 피쳐들이 있고 이 피쳐들은 잡이라 부른다.
잡은 스텝들로 구성된다.

스텝

배치 처리 정의하고 제어하는 독립 작업 단위
tasklet step : 간단히 정의한 하나의 작업 단위
ex 데이터 하나를 삭제한다 같이

chunk-oriented step : 한 번에 하나씩 데이터를 읽고 chunk 를 만든 후 chunk 단위로 트랜잭션을 처리

아이템 단위로 한다네.. ItemReader 로 읽고 ItemProcessor로 처리하고 ItemWriter 로 저장하고 etl 그런건가
아이템 프로세서는 필수 요소 아니라 괜찮다하고
아이템리더로 하나씩 읽고 읽고 라이터로 결과 뱉네

리드, 프로세스, 라이터를 일괄적으로 처리된다.
청크 기반은 세 가지 루프가 있는데 리드에서 읽는거 프로세스에서 처리하는거 그리고 이 전체 과정을 마지막 루프로..

청크 단위로 트랜잭션이 구성되어 커밋과 롤백 발생

처음부터 끝까지 독립적이며 스탭들로 이루어진 집합, 유일하고 여러 순서가 있는 스텝들로 이루어짐. 외부 영향 받지 않고 실행

Job Repository 는 RDB 로 배치수행 관련 데이터 저장 (시간, 읽기 쓰기 횟수, 상태)

Job Launcher 에서 Job 을 실행. 현재 쓰레드 이용할지 풀 이용할지 파라미터 유효한지 검색.

잡 런처로 잡 실행하면 스텝이 돌아간다.

JobRepository

BATCH_JOB_INSTANCE : 배치 첨 시작하면 단일 잡 인스턴스가 등록

BATCH_JOB_EXECUTION : 배치 시작하고 실행 결과를 꾸준히 생성한다. 언제 시작하고 끝났으며 상태를 자꾸 반영한다.

BATCH_JOB_EXECUTION_CONTEXT : 리트라이 시도같은거 하떄 유용한 값들 배치 재시작.. 여러번 실행할 떄 유용한

BATCH_JOB_EXECUTION_PARAMS : 잡에서 사용된 파라미터들을 저장

BATCH_STEP_EXECUTION : 배치에 사용되는 스텝들의 상태를 저장, 데이터 읽고 쓰고 건너띄고 그런걸 기록

BATCH_STEP_EXECUTION_CONTEXT : 리트라이나 여러번 재시도할 때 유용

RDB 말고 인메모리로도 가능


이용권 만료는 이용권 읽어서 만료된거 write 해주면 끝
청크기반으로 구성했다.

회원에게 일괄 지급하는건. 단순해서 데이터를 읽어서 일괄지급하는 청크 방식으로도 구성할 수 있지만, Tasklet 로 한 번 해보자.

병렬처리.. 확장이 편하게 해보자..
다중 쓰레드 청크를 사용해 오른쪽 세 개 청크.. 청크기반은 청크한테 트랜잭션을 먹고 쓰레드로 작업해.. 병렬로 ..
멀티 쓰레드를 쓰면 동시성 이슈.. 레이스 컨디션..

청크 방식인데 비동기로 진행한다. ItemProcessor 수학 복잡한거라던가 시간 걸리 API 쓰면 퓨처로 반환하고 완료가 되면 writer 한테 전달되어 실행 위임

통계 데이터만들고 파일로 반환.

원래 청크하나 있고 다음 스탭 나아갔는데 두 개의 스탭으로 간다. 앞에서 청크를 병렬적으로했는데 여기선 스탭을 병렬로 한다. (독립적이단 가정하에)

일간, 주간 보고서 작업..


ItemReader

대용량 데이터 다루는건 흔한 작업. 한 번에 다 가져오면 안되기에
커서, 페이징으로 접근한다.

읽고 처리하고 읽고 처리하고 이거 청크 사이즈 까지 만들어서
라이팅.

Cursor

Cursor ItemReader ->

  • java.sql.ResultSet
  • Database와 Connection 을 맺은 후 한 번에 하나씩 레코드를 Streaming 하며 다음 레코드로 진행한다. (Cursor 를 움직인다.)
  • JdbcCursorItemReader
  • HibernateCursorItemReader
  • JpaCrsorItemRader ..

커넥션 맺어서 하나씨 레코드를 스트리밍

Page

청크 사이즈만큼 데이터를 가져온다.

커서는 하나의 커넥션으로 동작하기에 빠를 수 있다.
수행 시간이 오래걸리면 커넥션이 끊길 수 있다.

페이지는 한 청크 가져올때마다 커넥션을 생성하기에 커서보다 좀 늦을 수 있다. 안정적일 순 있다.

ItemWriter

건건이 저장하는게 아니라 청크 단위로 진행 그래서 입력을 List 로 받는다.

만료 pass 상태 처리

청크로 가져와서 처리는 커서로 하는데 왜 그러느냐
status 때문에.. 처리 과정 중에 status 에 변경을 주게되는데 페이징으로 가져오면 데이터가 누락되는 경우가 있어
그래서 데이터 변경에 무관한 무결성 조회가 가능한 커서로 읽어온다.

JPACursorItemReader 는 Spring4.3 에 추가되었다한다.

스텝 구성을 참 재밌게 하시네.
스텝이 청크로 구성하셨는데 청크 단위로 했다가
내부에 리더를 박았는데 얘는 또 커서라네 뭐 우째되는기고


Tasklet execute 구현

tasklet 에 execute 반환은 RepeatStatus 로 이걸로 반복 가능

  • Spring Batch 는 Step 과 그 하위 Chunk의 반복 작업이며 Repeat 정책을 따른다.

Job -> Step -> [Tasklet ->[Chunk]]

name | desc
CONTINUABLE - 처리를 계속할 수 있음, Spring Batc에게 해당 Tasklet을 다시 실행하도록 정의
FINISHED - 처리가 완료되었음, 처리의 성공 여부에 관계없이 Tasklet의 처리를 완료하고 다음 처리를 진행


기본적으로 스텝은 단일 쓰레드로 진행된다. 직렬화란 얘기인듯

멀티스레드 스텝은 각 청크를 자바의 테스크익스큐터를 통해 멀티스레드로 실행하는 방식.
배치의 리더, 라이터가 쓰레드세이프한지도 봐야한다.

각 스탭

커서는 낫 스레드세이프..
페이지는 변경 잡업에 못써..
그래서 싱크로나이즈는 스트림리더 써..
라이트는 코스트가 많이들어 멀티쓰레드 좋아..

스텝에서 멀티스레드 결정 짓는구나..
이후 리더에선 커서로 할 경우 싱크로나이즈..

프로세서 그런 애들한테도 내부적으로 지정이 가능하다 TaskExecutor를 .. 이걸로 멀티스레드 처리
위임을 해버린다. 다른 스레드에게..


Bean Scope 개념

기본적으로 스프링 빈 스코프는 싱글톤
여기서 하려는건 빈 생성 시점을 지정된 Scope가 명시된 method가 실행된 시점으로 지연시키는 것

  • JobScope 잡이 실행될 때 생성되고 끝날 때 삭제되도록
  • StepScope 스텝이 실행될 때 생성되고 끝날 때 삭제
    Why
  1. JobParameter 를 method 실행하는 시점까지 지연시켜 할당할 수 있다.
  2. 동일한 Component 를 병렬로 처리할 때 안전할 수 있다. (돌려쓰지 않고 매번 자체 생산해서 사용한다.)

profile
unagi.zoso == ziggy stardust == devswansong

0개의 댓글