| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- TypeScript
- jwt
- TS
- es6
- github
- ES5
- angular
- 클론코딩
- 당근마켓
- ZOOM
- 문서번호
- Strict
- 컴포넌튼
- 0.5px border
- 으
- Props
- 0.25px border
- entity
- 전역변수
- 0.75px border
- 서버리스 #
- 1px border
- 타입스크립트
- npm
- &연산
- Websocket
- 데이터베이스 #try #이중
- 10px
- literal
- font-size
- Today
- Total
복잡한뇌구조마냥
[Spring] Spring Batch + Scheduler 정리 본문
실제 서비스를 운영하다 보면 아래 같은 요구가 반드시 생긴다.
- 매일 0시에 통계 집계 돌리기
- 예약일 하루 전 알림 보내기
- 오래된 로그 삭제하기
- 대량 데이터 업데이트 또는 ETL 실행
이런 작업들은 정상적인 요청/응답 기반 API에서 처리하기 어렵고,
정해진 시점(time-based)에 반복 실행되어야 하는 로직이기 때문에
스케줄러와 배치가 필요해진다.
하지만 개발자들이 헷갈리는 대표적인 질문이 하나 있다.
“스케줄러는 @Scheduled? Quartz? Spring Batch랑은 어떻게 연결하지?
배치랑 스케줄러를 같이 써도 되는 건가?”
1. 🔥 스케줄러와 배치의 본질적인 차이
먼저 개념부터 명확하게 정리하자.
| 역할 | 도구 | 핵심 포인트 |
| 언제(When) 실행할 것인가? | @Scheduled, Quartz | 실행 스케줄 관리 |
| 무엇(What)을 어떻게 처리할 것인가? | Spring Batch | 대량 처리/청크 처리/재시작/로직 관리 |
👉 스케줄러 = 언제 실행할지 결정
👉 배치 = 실제 비즈니스 로직을 어떻게 실행할지 정의
이 둘은 경쟁 관계가 아니라, 책임을 나눠 갖는 보완 관계다.
서로 필요할 때 함께 쓰는 것이 오히려 정석이다.
2. 🧩 @Scheduled — 가장 간단한 스케줄러
Spring이 기본 제공하는 스케줄러로 가장 사용하기 쉽다.
✔ 설정
@Configuration
@EnableScheduling
public class SchedulerConfig {}
✔ 사용 예시
@Component
public class SimpleScheduler {
// 10초마다 실행
@Scheduled(fixedRate = 10_000)
public void run() {
System.out.println("10초마다 실행");
}
// 매일 0시 실행
@Scheduled(cron = "0 0 0 * * *")
public void runMidnightTask() {
System.out.println("매일 0시에 실행");
}
}
✔ 장점
- 설정 간단
- 코드만으로 쉽게 가능
- 작은 규모의 주기 작업에 최적
✔ 단점
- 멀티 인스턴스 환경에서는 중복 실행될 수 있음
- 스케줄 시간 변경하려면 코드 수정 + 재배포 필요
- misfire 처리, 재시도, 잡 이력 관리 없음
👉 단일 서버 + 단순 작업일 경우 매우 좋음.
3. 🧩 Quartz — 스케줄링 자체가 중요한 경우의 끝판왕
Quartz는 독립적인 스케줄링 프레임워크다.
스케줄 자체를 운영과 분리하여 정교하게 관리해야 할 때 유일한 선택지 중 하나다.
✔ 특징
- Cron 표현식 + Calendar + misfire 정책 지원
- DB 기반 Job 관리 가능
- 여러 서버에서도 중복 실행 없이 클러스터링 가능
- 스케줄을 운영에서 수정 가능
✔ 기본 코드 구조
Job 정의
public class SampleJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) {
System.out.println("Quartz Job 실행");
}
}
Trigger + JobDetail 설정
@Configuration
public class QuartzConfig {
@Bean
public JobDetail jobDetail() {
return JobBuilder.newJob(SampleJob.class)
.withIdentity("sampleJob")
.storeDurably()
.build();
}
@Bean
public Trigger trigger() {
return TriggerBuilder.newTrigger()
.forJob(jobDetail())
.withIdentity("sampleTrigger")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 * * ?"))
.build();
}
}
✔ 장점
- 정교하고 안정적인 스케줄 관리
- 분산 환경 대응
- 다양한 트리거 정책
- 실행 이력 관리 가능
✔ 단점
- 설정 복잡
- 작은 프로젝트에서는 과한 선택
- 스케줄 실행만 책임지고 실제 로직은 직접 작성해야 함
4. 🧩 Spring Batch — “배치 로직”을 담당하는 프레임워크
스케줄러는 단순히 “언제” 실행할지만 결정할 뿐,
배치 작업의 핵심은 대량 데이터 처리 로직 관리이다.
Spring Batch는 아래 같은 기능을 제공한다.
✔ Spring Batch가 해결하는 문제
| 기능 | 설명 |
| 청크(chunk) 기반 처리 | 100개씩 읽고 → 처리 → 커밋 형태 |
| 재시작(restart) | 실패한 지점부터 이어서 처리 |
| skip/retry 정책 | 오류 허용/재시도 처리 |
| Job / Step / Reader / Processor / Writer 구조 | 책임 명확 |
| Job Repository | 실행 이력, 상태 관리 |
| 트랜잭션 관리 | 대량 처리에서 핵심 |
즉, 배치 로직을 안정적으로, 대량 데이터를 처리하기 위한 프레임워크이다.
5. 🔗 “배치 + 스케줄러” 같이 쓰는 게 정석인 이유
배치를 실행하기 위해서는 트리거(trigger) 가 필요하다.
즉, 배치 자체에는 “언제”라는 개념이 없다.
그래서:
- @Scheduled → 배치 Job 실행
- Quartz → 배치 Job 실행
6. 스케줄러 + 배치 예
🧩 @Scheduled → Spring Batch 실행 (코드 예시)
@Component
@RequiredArgsConstructor
public class SampleBatchScheduler {
private final JobLauncher jobLauncher;
private final Job sampleJob;
@Scheduled(cron = "0 0 0 * * *") // 매일 0시
public void runSampleJob() throws Exception {
JobParameters params = new JobParametersBuilder()
.addLong("timestamp", System.currentTimeMillis()) // 재실행 구분자
.toJobParameters();
jobLauncher.run(sampleJob, params);
}
}
🧩 Quartz → Spring Batch 실행 (고급 패턴)
@Component
@RequiredArgsConstructor
public class QuartzBatchJob extends QuartzJobBean {
private final JobLauncher jobLauncher;
private final Job batchJob;
@Override
protected void executeInternal(JobExecutionContext context) {
JobParameters params = new JobParametersBuilder()
.addLong("runId", System.currentTimeMillis())
.toJobParameters();
try {
jobLauncher.run(batchJob, params);
} catch (Exception e) {
// 실패 관리 가능
}
}
}
여러 서버에서 Quartz 클러스터링을 사용하면
→ 배치 실행을 안전하게 단일 실행으로 보장할 수 있다.
8. 🧨 @Scheduled vs Quartz vs Spring Batch 비교표 (핵심 요약)
| 항목 | @Scheduled | Quartz | Spring Batch |
| 역할 | 간단 스케줄러 | 고급 스케줄러 | 배치 처리 로직 |
| 목적 | “언제” 실행할지 | “언제” + “어떻게 스케줄 관리할지” | “무엇을 어떻게 처리할지” |
| 난이도 | 매우 쉬움 | 중간~높음 | 중간 |
| 분산 환경 | ❌ | ⭕ | ⭕ |
| 재시작/재실행 | ❌ | ⭕ | ⭕ |
| 대량 처리 | ❌ | ❌ | ⭕ |
| 실행 이력 관리 | ❌ | DB 저장 가능 | JobRepository에서 기본 제공 |
| 운영에서 스케줄 수정 | ❌ | ⭕ | — |
📌 Spring Batch 구성요소 정리

✔ Job
Spring Batch의 가장 큰 실행 단위.
여러 Step으로 구성되며 Step들을 순차적으로 실행한다.
✔ Step
Job을 구성하는 실행 단계.
Tasklet 방식 또는 Chunk 방식으로 처리된다.
✔ Tasklet
Step 내부에서 동작하는 최소 실행 단위.
단일 작업(파일 생성, 테이블 초기화 등)에 적합.
✔ Chunk 지향 처리
대량 데이터를 효율적으로 처리하는 방식.
정해진 chunk size만큼 데이터를 읽고(Reader) → 가공(Processor) → 저장(Writer) 한다.
✔ ItemReader
외부 데이터(DB, 파일 등)를 한 건씩 읽어오는 역할.
데이터가 끝나면 null 반환하여 Step 종료.
✔ ItemProcessor
Reader가 읽은 데이터를 가공하거나 필터링하는 역할.
✔ ItemWriter
가공된 데이터를 저장(DB, 파일, 외부 시스템 등).
청크 단위로 커밋되어 성능적으로 유리함.
✔ JobRepository
Job/Step 실행 이력, 상태, 실패 지점 등을 저장하는 저장소.
재시작·재실행 기능이 여기에 기반한다.
✔ JobInstance
Job의 “논리적 실행 단위”.
예: 날짜별로 다른 JobInstance로 취급됨.
✔ JobExecution
JobInstance의 실제 실행 기록(성공/실패/재시작 등).
✔ StepExecution
각 Step의 실행 이력(읽은 데이터 수, 성공/실패 기록 등).
✔ ExecutionContext
Job 또는 Step 실행 중 임시 데이터를 저장하는 공간.
재시작 시 이전 진행 정보를 활용하기 위해 존재.
✔ JobLauncher
코드에서 Job을 실행할 때 사용하는 인터페이스.
스케줄러(@Scheduled, Quartz)가 Job을 실행할 때 호출한다.
✔ JobOperator
Job 중지, 재시작, 실행 이력 조회 등 운영 제어 기능을 제공.
9. 🧩 결론 — "언제"와 "무엇"을 분리해서 생각하면 쉽다
정리하면 이렇게 된다:
- 스케줄러(@Scheduled / Quartz)
→ “언제 실행할지” 관리하는 도구 - Spring Batch
→ “비즈니스 로직을 어떻게 처리할지” 관리하는 도구
참고자료:
https://ittrue.tistory.com/326#google_vignette
[Spring Batch] 스프링 배치란 무엇인가? - 개념, 아키텍처, 구성요소
본 내용은 온라인 강의 사이트 인프런의 정수원 님의 강의 내용이 포함되어 있습니다. 스프링 배치 - Spring Boot 기반으로 개발하는 Spring Batch 스프링 배치 - Spring Boot 기반으로 개발하는 Spring Batch -
ittrue.tistory.com
https://velog.io/@yjc1116/Spring-Batch
Spring Batch
이번 취밋 프로젝트를 작업하면서 스케줄 기반으로 처리해야 하는 작업들이 점점 많아지면서 Quartz를 도입하게 되었다. 하지만 Quartz를 설명하기 전에, 먼저 배치 처리의 기본 개념과 Spring Batch가
velog.io
'BE > Spring' 카테고리의 다른 글
| [Spring] Flyway DB 스키마 관리 (0) | 2025.12.07 |
|---|---|
| [Spring] SMTP 기반 메일 인증 ( + 비동기 처리 ) (0) | 2025.11.30 |
| [JPA] OSIV ( Open Session In View ) (0) | 2025.11.25 |
| [Spring] JOOQ ( + QueryDSL vs JOOQ ) (0) | 2025.11.21 |
| [Spring] Spring AI ( OpenAI + Rag + MariaDB Vector ) (0) | 2025.11.18 |