Spring Batch 입문 2편. Spring Batch 의 3계층 아키텍처 — Application·Core·Infrastructure 의 정확한 분담. JobOperator·Job·Step 의 자리, ItemReader·Writer 가 어디서 동작하나, 사용자 코드와 framework 코드의 분리까지 풀어쓴 학습 노트.
이 글은 Spring Batch 입문에서 운영까지 시리즈 48편 중 2편이에요. 1편 에서 Spring Batch 의 정체성 을 잡았다면, 이번 2편은 그 안이 어떻게 구성됐나 — 3계층 아키텍처.
Architecture가 어렵게 느껴지는 이유
처음 reference 를 펴면 JobOperator·Job·Step·ItemReader·ItemWriter·ItemProcessor·RetryTemplate... 같은 이름이 섞여서 나와요. 어떤 게 framework 가 제공하는 것이고 어떤 게 내가 짜야 하는 것인지 한 번에 잡히지 않고, 계층(layer) 의 의미도 — Application·Core·Infrastructure 가 물리적 패키지 분리인지 논리적 역할 분리인지 — 명확하지 않아요. 거기에 General Batch Principles 는 Spring Batch 특화가 아닌 모든 batch 시스템의 일반 원칙이라, 이 원칙들이 framework 의 설계 결정에 어떻게 녹았나를 잡으면 왜 이렇게 만들어졌나가 보여요.
이 글에서 3계층 종합 + 일반 batch 원칙 8가지 + Spring Batch 의 차별점 까지.
3계층 — Application · Core · Infrastructure
┌─────────────────────────────────────────────┐
│ Application (사용자 코드) │
│ - 비즈니스 로직 │
│ - 우리가 짜는 Job·Step·Processor 구현 │
└─────────────────────────────────────────────┘
↑
┌─────────────────────────────────────────────┐
│ Core (framework runtime) │
│ - JobOperator │
│ - Job·Step (인터페이스+기본 구현체) │
│ - JobLauncher·JobRepository │
└─────────────────────────────────────────────┘
↑
┌─────────────────────────────────────────────┐
│ Infrastructure (공통 readers·writers·services) │
│ - ItemReader·ItemWriter 표준 구현체 들 │
│ - RetryTemplate·RepeatTemplate │
│ - Transaction Management │
└─────────────────────────────────────────────┘
핵심을 풀면, Application 은 내가 직접 짜는 코드 — 비즈니스 로직·Job 정의·Custom Processor 등이 여기 들어가요. Core 는 Job 실행과 라이프사이클 관리 영역으로 JobOperator·Job·Step·JobRepository 가 모여 있고, Infrastructure 는 공통 도구 — 일반 ItemReader·Writer·retry·transaction 모음이에요.
여기서 짚을 점 하나 — Application 과 Core 모두 Infrastructure 위에 빌드된다는 것. 사용자 코드든 framework 코드든 같은 infrastructure (예: ItemReader) 를 그대로 씁니다.
각 계층의 책임
Application — 우리가 책임지는 자리
이 자리에서 결정하는 건 네 가지예요. 어떤 데이터를 읽나 (DB·파일·Kafka?), 어떤 가공을 하나 (변환·검증·enrichment), 어디로 쓰나 (DB·파일·S3?), 그리고 언제 skip·retry 하나 (비즈니스 규칙). 코드 모양으로 보면 @Configuration + @Bean 으로 설정과 우리 Processor 구현체를 박는 자리.
Core — Framework 가 책임지는 라이프사이클
JobOperator= Job 실행·중지·재시작 제어Job= 여러 Step 으로 구성된 단위 작업Step= 한 단계의 처리 (chunk-oriented 또는 tasklet)JobLauncher= 실제 Job 실행JobRepository= Job·Step 의 실행 상태 영속화
3편 Domain Language 에서 깊이.
Infrastructure — 재사용 도구
ItemReader·ItemWriter표준 구현체 — Flat file·XML·JSON·DB·JPA·JDBC·MongoDB 등RetryTemplate— 재시도 패턴RepeatTemplate— 반복 패턴- Transaction Management — chunk 단위 commit·rollback
framework 도 application 도 같은 infrastructure 를 쓰니까 재사용성·일관성 이 자연스럽게 따라옵니다.
일반 Batch 설계 원칙 8가지
공식 문서가 정리한 General Batch Principles. Spring Batch 특화가 아닌 모든 batch 시스템에 통용되는 원칙이에요.
1. 온라인·배치 아키텍처는 서로 영향
"A batch architecture typically affects on-line architecture and vice versa."
같은 DB·시스템을 공유하니 batch 가 온라인 응답에 영향을 주고, 반대로 온라인 트래픽이 batch 시간에 영향을 줘요. 공통 building block 으로 분리해 재사용하는 게 답.
2. 가능한 한 단순하게
"Simplify as much as possible and avoid building complex logical structures in single batch applications."
한 batch 안에 너무 많은 로직이 들어가면 디버깅·유지보수 비용이 폭증해요. 하나의 batch = 하나의 명확한 작업.
3. 데이터·처리는 물리적으로 가깝게
"Keep the processing and storage of data physically close together."
원격 DB 에 건마다 query 를 던지면 네트워크 비용이 폭증합니다. 데이터 가까이서 처리 하거나 로컬 cache·메모리 를 활용.
4. I/O 최소화
"Minimize system resource use, especially I/O. Perform as many operations as possible in internal memory."
batch 성능의 가장 큰 bottleneck 은 I/O 예요. 자주 보이는 안티 패턴은 같은 데이터를 매 트랜잭션마다 read 하는 것 (cache·working storage 로 피할 수 있어요), 같은 트랜잭션 안에서 같은 데이터를 두 번 read 하는 것, 불필요한 table·index scan, 그리고 WHERE 절에 key 를 지정하지 않는 것.
5. 같은 작업 두 번 하지 않기
"Do not do things twice in a batch run."
데이터 처리 단계에서 집계를 누적해두면 별도 report batch 로 재처리할 필요가 없어요.
6. 메모리 미리 할당
"Allocate enough memory at the beginning of a batch application."
batch 실행 중에 메모리 재할당이 일어나면 JVM (자바 가상 머신) GC (가비지 컬렉션) 부담이 커져요. 처음에 충분히 할당해두는 게 안전.
7. 데이터 무결성 항상 의심
"Always assume the worst with regard to data integrity. Insert adequate checks and record validation."
대량 데이터에는 반드시 일부 손상·이상이 섞여 들어옵니다. 검증 로직을 미리 박아두세요.
8. 운영 부담 고려
원칙은 아니지만 reference 가 곳곳에서 강조해요 — 로깅·모니터링·재시작·skip 같은 운영 요소 가 배치 시스템의 80% 라는 점. Spring Batch 가 이걸 기본 제공한다는 게 핵심 가치.
Spring Batch의 차별점 — 위 원칙들이 어떻게 녹았나
여기까지 따라오셨다면 왜 Spring Batch 가 이렇게 만들어졌나 가 잡혀요.
Chunk-oriented Processing (11~18편)
원칙 4 (I/O 최소화) + 원칙 6 (메모리 미리) 의 결과:
대량 record 를 한 건씩 처리 (X)
↓
N개씩 묶어 batch processing (chunk)
↓
N개마다 한 번에 transaction commit
개별 transaction overhead 를 N분의 1 로 줄여 I/O 효율을 끌어올리는 구조.
JobRepository (5~10편)
원칙 7 (데이터 무결성) + 재시작 보장 의 결과:
모든 Job·Step 실행 상태를 별도 DB 에 영속 저장
↓
중단 시 마지막 성공 지점부터 재시작 가능
직접 짜면 수천 줄이 되는 상태 관리 코드를 framework 가 제공.
Skip·Retry·Listener (14·15·18편)
원칙 7 + 원칙 8 의 결과:
일부 record 실패 → skip
일시적 실패 → retry
주요 시점 → listener 로 모니터링·알림
비즈니스 흐름이 끊기지 않게 자동 처리.
ItemReader·Writer 의 표준 인터페이스
원칙 1 (공통 building block) 의 결과:
새 데이터 source = 새 ItemReader 구현만
나머지 Job·Step·Processor·Writer = 그대로 재사용
확장성의 핵심.
Spring Batch 와 Spring Framework 의 관계
"Spring Batch builds upon the characteristics of the Spring Framework that people have come to expect (productivity, POJO-based development approach, and general ease of use)."
핵심은 Spring Framework 의 익숙한 패턴 그대로 라는 점이에요. @Configuration + @Bean 으로 Job 을 정의하고, @Autowired 로 의존성을 주입하고, @Transactional 을 자주 자동으로 활용하고, AOP (관점 지향 프로그래밍)·exception handling 표준 패턴을 그대로 쓰고, Spring Boot starter 로 boilerplate 를 최소화 — 모두 자바 백엔드에서 익숙한 그림.
자바 백엔드 입문 (시리즈 1) 을 본 사람 에게 낯선 framework 가 아니라 새 영역의 Spring 도구로 자연스럽게 들어옵니다. (POJO 는 평범한 자바 객체, AOP 는 횡단 관심사를 모듈화하는 기법 — 둘 다 시리즈 1 에서 다룬 개념이에요.)
의존성·시작
의존성
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<!-- DB (JobRepository 용 + business 데이터 용) -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
활성
@SpringBootApplication
public class MyBatchApplication {
public static void main(String[] args) {
SpringApplication.run(MyBatchApplication.class, args);
}
}
Spring Boot 가 Batch 자동 구성 을 해줘서 JobRepository·JobLauncher·JobOperator 가 자동으로 Bean 으로 올라와요.
여기서 시험 함정이 하나 있어요 — Spring Batch 는 DB 가 필수 입니다 (JobRepository 영속화를 위해). 임시 검증용으로는 H2 in-memory 가 가능하고, 운영 환경에서는 PostgreSQL·MySQL 등이 들어가요.
디렉토리 구조 — 일반적 권장
src/main/java/com/example/batch/
├── BatchApplication.java
├── config/
│ ├── BatchInfrastructureConfig.java # JobRepository·JobLauncher (자주 Spring Boot 자동)
│ └── BatchJobConfig.java # Job·Step 정의
├── reader/
│ ├── CustomerCsvReader.java
│ └── ...
├── processor/
│ ├── CustomerValidationProcessor.java
│ └── ...
├── writer/
│ ├── CustomerDbWriter.java
│ └── ...
├── tasklet/
│ └── ArchiveTasklet.java
└── domain/
└── Customer.java
이 구조가 표준은 아니에요 — 회사·팀마다 자유롭게 잡습니다. 다만 reader·processor·writer 를 분리 하는 건 일반적인 그림.
모니터링·로깅
reference 가 강조하는 batch 운영의 핵심 부분.
logging:
level:
org.springframework.batch: INFO
org.springframework.batch.core.JobExecution: DEBUG
기본 로그는 Job 시작·종료·각 Step 결과·예외를 찍어주고, DEBUG 로 내리면 chunk 단위 처리 내역까지 보여요.
JobRepository 가 모든 실행 이력을 영속 저장 하니까 직접 SELECT 로 디버깅이 가능해요. 47편 Meta-Data Schema 에서 깊이.
한계·실무 함정
1. JobRepository DB 필수
운영 환경에서는 반드시 운영 DB 가 들어가야 해요. in-memory H2 는 학습·테스트용. 7편에서 깊이.
2. Application Context 시작 비용
Spring Boot 의 큰 ApplicationContext + Spring Batch 의 Job·Step Bean 들이 합쳐져서 시작 시간이 수 초로 잡혀요. 작은 batch 라도 이 고정 비용은 따라옵니다.
매번 short-lived process 로 돌려야 한다면 Spring Cloud Data Flow 또는 Kubernetes Job 같은 인프라를 같이 검토.
3. 메모리 누적
batch 실행 중에 전체 데이터를 메모리에 통째로 로드하면 OOM (메모리 초과 오류) 으로 떨어져요. chunk-oriented 가 N건씩 처리하고 release 하는 구조라 이 함정을 피할 수 있어요.
4. 트랜잭션 timeout
대량 트랜잭션은 DB lock·timeout 위험을 끌고 와요. chunk size 를 적절히 잡고 short transaction 원칙을 지키는 게 답.
시험 직전 한 번 더 — Spring Batch Architecture 함정 압축 노트
- 3계층 = Application (사용자 코드) · Core (framework runtime) · Infrastructure (공통 도구)
- Application =
@Configuration·@Bean·Custom Processor 등 우리 코드 - Core =
JobOperator·Job·Step·JobLauncher·JobRepository - Infrastructure =
ItemReader·ItemWriter·RetryTemplate·RepeatTemplate·Transaction - 사용자 코드도 framework 도 같은 infrastructure 사용
- 일반 Batch 원칙 8가지 — 온라인/배치 영향·단순화·데이터 근접·I/O 최소·중복 처리 X·메모리 미리·무결성 의심·운영 부담
- 자주 안티 패턴 — 매 트랜잭션 같은 데이터 read·같은 데이터 두 번·불필요 scan·WHERE key 누락
- Spring Batch 의 차별점 = 이 원칙들이 framework 안에 녹음
- Chunk-oriented Processing = I/O 최소 + 메모리 효율 (11~18편)
- JobRepository = 모든 실행 상태 영속, 재시작 보장 (7편)
- Skip·Retry·Listener = 무결성·운영 자동 (14·15·18편)
- 표준 ItemReader/Writer = 새 데이터 source 만 새로 (5·6편)
- Spring Framework 위 —
@Configuration·@Bean·@Autowired·@Transactional그대로 - 의존성 =
spring-boot-starter-batch+ DB driver - DB 가 필수 (JobRepository) — 운영 PostgreSQL·MySQL, 학습 H2
- 디렉토리 구조 =
config·reader·processor·writer·tasklet·domain일반적 - 모니터링 =
org.springframework.batch로그 + JobRepository 직접 SELECT - 함정 — Application Context 시작 시간·메모리 누적·트랜잭션 timeout
공식 문서: Spring Batch Architecture 에서 원문을 확인할 수 있어요.
시리즈 다른 편 (앞뒤 글 모음)
이전 글:
다음 글: