[스프링 배치] Flow 사용하기

조갱·2025년 5월 4일
0

스프링 배치

목록 보기
8/9

Flow

아키텍쳐 톺아보기

사진으로 보는 아키텍처

Flow 사용하기

스프링 배치에서 Flow 를 사용하기 위해서는 FlowJob 을 생성해야한다.
위 사진은 Flow 생성과 관련된 아키텍처와 플로우를 그림으로 정리했다.

Flow 는 말 그대로 실행 흐름 전환 을 목표로 하기에, 이를 위한 Transition을 잘 이해하는 것이 중요하다.

FlowJob 을 만들기 위해서는 우선 JobFlowBuilder 를 만들고,
.end().build() 를 통해 FlowJob 을 생성할 수 있다.

JobFlowBuilder 는 위 그림과 같이 SimpleJobBuilder, FlowJobBuilder 모두를 통해 생성이 가능하다.

Transition

  • Step의 실행 흐름을 "조건에 따라 전환" 을 정의한다.
  • on (pattern: String) 메소드를 통해 TransitionBuilder 를 생성하고, Transition Flow 를 구성한다.
  • Step의 실행 결과 (ExitStatus) 를 기반으로 on (pattern: String) 을 정의하며, step 의 실행 결과 (ExitStatus) 가 on (pattern: String) 의 어떠한 패턴과도 매칭되지 않으면 예외를 발생한다.
  • 구체적인 것부터, 구체적이지 않은 순서대로 적용된다.

on (pattern: String)

분기를 위한 첫 단계. 분기를 위한 패턴(조건식)을 설정한다.

JobFlowBuilder 에서 유일하게 TransitionBuilder 를 생성한다.
Step의 실행 결과인 ExitStatus 와 매칭된다. (BatchStatus 가 아니니 주의)

특수문자는 아래 2개만 지원한다.

  • * : 0개 이상의 아무 임의의 문자(열)과 매칭.
  • ? : 1개의 아무 임의의 문자와 매칭.

예를 들어, 문자열이 apple 인 경우 pattern 에
apple, apple*, *apple, app*le, app*, *e, * -> 매칭됨
apple, app??, ap?le, ?pple, ????? -> 매칭됨
appl, a*l, ?le, apple?, ? -> 매칭 안됨

to (Step / Flow / JobExecutionDecider)

on절에 매칭이 됐을 때, 다음으로 실행할 단계를 정의

from (Step / Flow / JobExecutionDecider)

이전에 정의한 Step, Flow, JobExecutionDecider 로부터 새로운 분기를 추가할 때 사용.
이전에 정의된 적이 없는 경우, 신규로 등록한다.

(FlowBuilder.java 중)

private void doFrom(Object input) {
    if (this.currentState == null) {
        this.doStart(input);
    }
    ...
}

stop ()

FlowExecutionStatus 가 STOPPED 상태로 종료되는 transition
Job 의 BatchStatus 와 ExitStatus 가 STOPPED 으로 종료됨

fail ()

FlowExecutionStatus 가 FAILED 상태로 종료되는 transition
Job 의 BatchStatus 와 ExitStatus 가 FAILED 으로 종료됨

end ()

FlowExecutionStatus 가 COMPLETED 상태로 종료 되는 transition
Job 의 BatchStatus 와 ExitStatus 가 COMPLETED 으로 종료됨

Step 의 ExitStatus 가 FAILED 이더라도 Job 의 BatchStatus 가 COMPLETED 로 종료하도록 가능하며 이 때 Job의 재시작은 불가능함

stopAndRestart (Step / Flow / JobExecutionDecider)

stop() 과 기본적으로 흐름은 동일하다.
(= FlowExecutionStatus 가 STOPPED 상태로 종료되며, Job 의 BatchStatus 와 ExitStatus 가 STOPPED 상태로 종료된다.)

차이점이라면, 다음에 Job 을 재시작 할 때 여기에 명시된 Step / Flow / JobExecutionDecider 부터 시작되도록 강제된다.

SimpleFlow 생성하기

@Bean
public Job batchJob() {
	return jobBuilderFactory.get(“batchJob")
		.start(Step1 / Flow1) // 최초에 실행할 Step / Flow 지정
		.on(pattern: String) // Step, Flow 의 ExitStatus 와 패턴 비교
		.to(Step2 / Flow2) // 위 on절과 패턴이 일치할 경우 실행할 Step / Flow
		.stop() / fail() / end() / stopAndRestart() // 위에 to 또는 이런것들도 쓸 수 있다.
		.from(Step1) // 위에 정의한 Step1 로부터
		.next(Step3) // 그 다음에는 Step3 을 실행한다.
		.end() // SimpleFlow 를 생성하고, SimpleFlow 를 래핑한 FlowJobBuilder 반환
		.build() // FlowJob 반환
}

step1 을 실행한 후에, ExitStatus 에 따라 분기하기

@Bean
public Job batchJob() {
	return jobBuilderFactory.get(“batchJob")
		.start(step1) // 최초에 step1 을 실행한다.
		    .on("COMPLETED") // ExitStatus 가 COMPLETED 이면
		    .to(step2) // step2 를 실행한다.
		.from(step1) // step1 로부터
        	.on("*") // 모든 패턴 (COMPLETED 를 위에서 걸렀기 때문에, else 가 된다.)
            .to(step3) // step3 을 실행한다.
		.end() // SimpleFlow 를 생성하고, SimpleFlow 를 래핑한 FlowJobBuilder 반환
		.build() // FlowJob 반환
}

이러저러 조건들에 따라 분기하기.

@Bean
public Job batchJob() {
	return jobBuilderFactory.get(“batchJob")
		.start(step1) // 최초에 step1 을 실행한다.
		    .on("COMPLETED") // ExitStatus 가 COMPLETED 이면
		    .to(step2) // step2 를 실행한다.
            	.on("*") // (1)... step2 의 실행 결과와 상관없이
                .stop() // Stop 상태로 종료
		.from(step1) // step1 로부터
        	.on("*") // 모든 패턴 (COMPLETED 를 위에서 걸렀기 때문에, else 가 된다.)
            .to(step3) // step3 을 실행한다.
            .next(step4) // (2)... 이후 step4 를 실행한다.
            	.on("*") // step4 의 실행 결과와 상관없이
                .end() // End 상태로 종료
		.end() // SimpleFlow 를 생성하고, SimpleFlow 를 래핑한 FlowJobBuilder 반환
		.build() // FlowJob 반환
}

주석에 보면 (1) 과 (2) 로 달아둔 부분이 있다.
결과와 상관 없이 다음 스텝을 호출 하는 부분인데, on("*") 을 사용하기도, 안하기도 해서 관련 내용을 적어보기로 한다.

(1) 을 보면, step2 의 결과와 상관없이 stop() 하는데 on("*") 을 사용했으며,
(2) 를 보면, step3 의 결과와 상관없이 step4를 호출하는데, on("*") 을 사용하지 않았다.

이는 위에 아키텍처 사진을 다시 보면 답을 알 수 있다.
(1) 에서 to, stop, fail, end, stopAndRestart 는 Transition 이기 때문에 TransitionBuilder 를 필요로 한다.
따라서 on 을 통해 TransitionBuilder 를 생성했다.

(2) 에서 next() 는 flow 로 다음에 실행할 흐름을 지정하기 때문에, FlowBuilder 에서 처리된다.
이 또한 위에 아키텍처 사진을 보면 to 의 반환값이 FlowBuilder 임을 알 수 있다.

profile
A fast learner.

0개의 댓글