> For the complete documentation index, see [llms.txt](https://leehyokyun.gitbook.io/openbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://leehyokyun.gitbook.io/openbook/2-9.-spring-batch.md).

# 2-9. Spring Batch

Spring Batch에 대하여

## 📌 Spring Batch Execution

### Spring Batch Job End-to-End 실행 흐름 (최초 실행 기준)

> **목표** Application 실행 시점부터 **Job 시작 → Step 실행 → Tasklet 실행 → Step 종료 → Job 종료**까지의 흐름을 *Spring Batch 내부 클래스 기준*으로 **한 번에 조망**하고, 필요 시 **단계별로 복기**할 수 있도록 정리한다.

***

### 1️⃣ 전체 End-to-End 한눈에 보기 (요약 도식)

```
[Application 시작]
        |
        v
SpringApplication.run()
        |
        v
ApplicationRunner / CommandLineRunner
        |
        v
JobLauncher.run(job, jobParameters)
        |
        v
SimpleJobLauncher
        |
        v
Job.execute()
        |
        v
AbstractJob.execute()
        |
        +--> JobExecution 생성 (STARTING)
        |
        +--> doExecute()
                |
                v
            SimpleJob.doExecute()
                |
                v
            Step 순차 실행
                |
                v
            Step.execute()
                |
                v
            AbstractStep.execute()
                |
                +--> StepExecution 생성 (STARTING)
                |
                +--> beforeStep()
                |
                +--> doExecute()
                        |
                        v
                    TaskletStep.doExecute()
                        |
                        v
                    RepeatTemplate.iterate()
                        |
                        v
                    StepContextRepeatCallback
                        |
                        v
                    doInChunkContext()
                        |
                        v
                    TransactionTemplate.execute()
                        |
                        v
                    ChunkTransactionCallback.doInTransaction()
                        |
                        v
                    Tasklet.execute()
                        |
                        v
                    RepeatStatus 반환
                        |
                        v
            StepExecution 상태 업데이트 (COMPLETED / FAILED)
                |
                v
        JobExecution 상태 업데이트 (COMPLETED / FAILED)
                |
                v
[Application 종료]
```

***

### 2️⃣ 단계별 상세 흐름 (실행 → 실행 → 종료 → 종료)

***

### 🟢 1단계: Application → Job 실행 시작

```
SpringApplication.run()
   |
   v
ApplicationRunner / CommandLineRunner
   |
   v
JobLauncher.run(Job, JobParameters)
```

* Spring Boot는 **ApplicationRunner / CommandLineRunner**를 통해 배치 실행 진입
* `spring.batch.job.enabled=true` 또는 직접 `JobLauncher` 호출

***

### 🟢 2단계: Job 실행 (SimpleJob / AbstractJob)

```
SimpleJobLauncher.run()
   |
   v
Job.execute()
   |
   v
AbstractJob.execute()
   |
   +--> JobExecution 생성
   |        상태: STARTING
   |
   +--> validate()
   |
   +--> doExecute()
```

#### 핵심 포인트

* `AbstractJob.execute()`는 **템플릿 메서드**
* 실제 Step 실행 로직은 `doExecute()`에 위임

***

### 🟢 3단계: Step 실행 (AbstractStep)

```
SimpleJob.doExecute()
   |
   v
for (Step step : steps)
   |
   v
Step.execute()
   |
   v
AbstractStep.execute()
   |
   +--> StepExecution 생성
   |        상태: STARTING
   |
   +--> JobRepository.update(stepExecution)
   |
   +--> beforeStep()  (StepExecutionListener)
   |
   +--> doExecute(stepExecution)
```

#### 🔍 AbstractStep.execute() 내부 핵심 포인트

* **트랜잭션 경계는 Step이 아니라 Step 구현체(TaskletStep / ChunkOrientedStep)에 위임**
* `execute()`는 *라이프사이클 관리 + 상태 관리* 역할
* 실제 비즈니스 실행은 반드시 `doExecute()`에서 발생

***

### 🟢 4단계: TaskletStep.doExecute() 상세 (Chunk / Transaction / Callback)

```
TaskletStep.doExecute(stepExecution)
   |
   v
RepeatTemplate.iterate(
   └─ StepContextRepeatCallback
         |
         v
     doInChunkContext()
         |
         v
     TransactionTemplate.execute()
         |
         v
     ChunkTransactionCallback.doInTransaction()
         |
         v
     Tasklet.execute()
```

***

#### 🔥 핵심 콜백 체인 구조

```
RepeatTemplate
  └─ RepeatCallback
       └─ StepContextRepeatCallback
            └─ ChunkTransactionCallback
                 └─ Tasklet.execute()
```

***

#### 4-1️. doInChunkExecution (RepeatTemplate)

```
RepeatTemplate.iterate()
   |
   v
RepeatCallback.doInIteration()
   |
   v
StepContextRepeatCallback.doInChunkContext()
```

* StepExecutionContext를 **Chunk 단위로 바인딩**
* 반복 실행 가능 구조 (RepeatStatus.CONTINUABLE)
* Tasklet / Chunk 공통 기반 구조

***

#### 4-2️. doInTransaction (TransactionTemplate)

```
TransactionTemplate.execute()
   |
   v
ChunkTransactionCallback.doInTransaction()
```

* **실질적인 트랜잭션 시작 지점**
* PlatformTransactionManager 사용
* 예외 발생 시 Rollback

***

#### 4-3️. Tasklet.execute() 호출

```
Tasklet.execute(StepContribution, ChunkContext)
   |
   v
RepeatStatus 반환
   - FINISHED
   - CONTINUABLE
```

* Tasklet의 비즈니스 로직 진입 지점
* 반환값에 따라 RepeatTemplate 반복 여부 결정

***

### 🔵 5단계: Step 종료

```
Tasklet.execute() 종료
   |
   v
StepExecution.apply(contribution)
   |
   v
StepExecution 상태 변경
   - COMPLETED / FAILED
   |
   v
afterStep() (StepExecutionListener)
```

***

### 🔵 6단계: Job 종료

```
모든 Step 완료
   |
   v
JobExecution 상태 변경
   - COMPLETED / FAILED
   |
   v
JobRepository.update(jobExecution)
```

***

### 🟢 7단계: Tasklet 실행 + 트랜잭션

```
TaskletStep.doExecute()
   |
   v
TransactionTemplate.execute()
   |
   v
Tasklet.execute(StepContribution, ChunkContext)
   |
   v
RepeatStatus 반환
```

#### 🔥 핵심 메서드

* `TaskletStep.doExecute()`
* `doInTransaction()` 내부에서 실행됨

#### 트랜잭션 의미

* **Tasklet 단위 = 트랜잭션 단위**
* 예외 발생 시 Rollback

***

### 🔵 8단계: Step 종료

```
Tasklet.execute() 종료
   |
   v
StepExecution 상태 변경
   - COMPLETED / FAILED
   |
   v
afterStep()
```

* Step 상태가 Job의 흐름 제어 기준
* FAILED 시 Job 중단 가능

***

### 🔵 9단계: Job 종료

```
모든 Step 완료
   |
   v
JobExecution 상태 변경
   - COMPLETED / FAILED
   |
   v
JobRepository 업데이트
```

* JobExecution은 **Job의 최종 결과**
* ExitStatus / BatchStatus 확정

***

### 3️⃣ 핵심 클래스 관계 요약

```
Application
  └─ JobLauncher (SimpleJobLauncher)
       └─ Job (SimpleJob)
            └─ AbstractJob.execute()
                 └─ Step (TaskletStep)
                      └─ AbstractStep.execute()
                           └─ Tasklet.execute()
```

***

### 4️⃣ 복기용 핵심 문장 요약

* **Job / Step은 모두 템플릿 메서드 구조**
* `execute()`는 공통 흐름, `doExecute()`가 실제 구현
* Tasklet은 **트랜잭션 내부에서 실행**
* Step의 성공/실패가 Job의 흐름을 결정
* JobExecution / StepExecution은 상태 머신 역할

***

### 📌 Batch와 Application을 바라보아야 하는 관점

### 비동기 스레드

* 비동기 스레드는 JVM에서 스레드를 생성한 후, 비동기 스레드 풀에 제출하여 제어권을 넘겨받아 작업을 진행하는 처리 단위이다.
* Batch는 JVM의 일반적인 스레드일 뿐이고, 비동기 스레드와는 관련이 없다.

### Scheduler

* Scheduler는 별도의 스케쥴러 스레드라는 비동기 스레드 풀이 존재하여, 마찬가지로 main application의 통제를 받지 않고 자체적인 동작 및 처리를 진행한다.

### Batch / Scheduler에 대한 스레드 관점

* Scheduler 스레드 풀로 부터 스레드를 생성 및 제출, main application 제어권을 넘겨받아 비동기적으로 작업을 실행한다. 특히, Scheduler 스레드의 실행은 이전의 스케쥴러 스레드의 진행 내역에 관심이 없고, 시간이 되면 본인의 작업을 그대로 진행한다.
* 최초 실행의 진입점은 Scheduler 스레드이며, Spring batch의 jobLauncer 스레드는 JVM의 스레드이다.
* 여기서 비동기적 실행이 가능한 것은 Batch의 스레드가 아닌, Scheduler의 스레드이다.

### 📌 Batch와 Application을 바라보아야 하는 관점

### Batch Job Execution 및 Job Instance 관련 유의사항

* Spring Batch Job은 내부적으로 Job / Job Instance / Job Execution / Step Execution의 구조를 구성하여 실행한다.
* 이때 Job Instance는 실행내역에 ID (cf. Key)로 구분되며, 한 Job 실행 체계 내에서 중복이 불가능하다. 참고로, Job Instance의 Id 체계는 Job Name과 Job Parameter의 조합으로 이루어진다.
* 따라서, 고정된 Job Name / Job Parameter는 Job을 실행할때마다 새로운 Job Instance을 생성하는 것이 아닌, 동일한 Job Instance를 생성하는 실행 방식과 동일하다.
  * 다만, 기존의 Job 실행이 실패하였을 경우(FAILED) 해당 Job Instance를 찾아 재실행한다.
  * 기존의 Job을 성공하였을 경우(COMPLETED) 해당 Job Instance를 중복 실행할 수 없기에 오류가 발생한다.
* Job Parameter를 다른 값으로 넣는다면 Job Instance를 중복 여부에 상관없이 무조건적으로 실행 가능하겠지만, 기존의 실패여부 상관없이 새로운 Job을 실행하기에, 실패 시 작업을 모두 잃어버리므로 신중한 작업 구성이 필요하다.
* 따라서 실패에 대한 재시도 정책, Job Parameter의 카디널리티 수준 및 구별 정도를 적정 수준으로 맞추어 알맞은 Job 실행을 할 수 있도록 설계를 시도해야 한다.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://leehyokyun.gitbook.io/openbook/2-9.-spring-batch.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
