You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
335 lines
8.4 KiB
Markdown
335 lines
8.4 KiB
Markdown
# Spring Batch 대용량 처리 프로젝트
|
|
|
|
Spring Boot + Spring Batch + Quartz를 사용한 대용량 데이터 처리 배치 프로젝트입니다.
|
|
|
|
## 기술 스택
|
|
|
|
- **Java**: OpenJDK 1.8
|
|
- **Framework**: Spring Boot 2.3.12
|
|
- **Batch**: Spring Batch
|
|
- **Scheduler**: Quartz (Clustering 지원)
|
|
- **Database**: MariaDB
|
|
- **ORM**: MyBatis
|
|
- **Build Tool**: Gradle
|
|
|
|
## 주요 기능
|
|
|
|
### 1. 대용량 데이터 처리
|
|
- Chunk 기반 처리 (5,000건씩)
|
|
- JdbcPagingItemReader를 사용한 효율적인 데이터 읽기
|
|
- MyBatis Batch Insert를 통한 성능 최적화
|
|
|
|
### 2. 배치 처리 흐름
|
|
```
|
|
파일/DB 읽기 → 데이터 처리 → API 호출 → 결과 저장
|
|
```
|
|
|
|
### 3. 실패 대응
|
|
- Skip 처리: 최대 100건까지 오류 허용
|
|
- Retry 처리: 실패 시 최대 3회 재시도
|
|
- 실패 로그 자동 저장
|
|
- JobExecutionListener를 통한 모니터링
|
|
|
|
### 4. 스케줄링 관리
|
|
- Quartz Scheduler 사용
|
|
- Cron 표현식을 통한 유연한 스케줄링
|
|
- 기본 설정: 매일 새벽 2시 실행
|
|
|
|
### 5. 서버 다중화 지원
|
|
- Quartz Clustering 설정
|
|
- DB 기반 Job 동기화
|
|
- 중복 실행 방지 (@DisallowConcurrentExecution)
|
|
|
|
### 6. Transaction 관리
|
|
- Spring Batch의 Chunk 단위 트랜잭션
|
|
- MyBatis 트랜잭션 통합
|
|
|
|
## 프로젝트 구조
|
|
|
|
```
|
|
src/main/java/com/example/batch/
|
|
├── BatchApplication.java # Main 클래스
|
|
├── config/
|
|
│ ├── BatchConfig.java # Spring Batch 설정
|
|
│ └── MyBatisConfig.java # MyBatis 설정
|
|
├── domain/
|
|
│ ├── Customer.java # 고객 도메인
|
|
│ ├── CustomerProcessed.java # 처리된 고객 데이터
|
|
│ └── BatchLog.java # 배치 로그
|
|
├── job/
|
|
│ ├── CustomerBatchJobConfig.java # 배치 Job 설정
|
|
│ └── CustomerJobExecutionListener.java # Job 실행 리스너
|
|
├── mapper/
|
|
│ ├── CustomerMapper.java # 고객 Mapper
|
|
│ └── BatchLogMapper.java # 로그 Mapper
|
|
└── scheduler/
|
|
├── BatchScheduler.java # Quartz 스케줄러 설정
|
|
└── CustomerBatchQuartzJob.java # Quartz Job
|
|
|
|
src/main/resources/
|
|
├── application.yml # 애플리케이션 설정
|
|
├── db/
|
|
│ └── schema.sql # DB 스키마
|
|
└── mapper/
|
|
├── CustomerMapper.xml # 고객 쿼리
|
|
└── BatchLogMapper.xml # 로그 쿼리
|
|
```
|
|
|
|
## 폐쇄망 환경 지원 (Nexus)
|
|
|
|
이 프로젝트는 폐쇄망 환경에서 내부 Nexus Repository Manager를 사용할 수 있도록 설정되어 있습니다.
|
|
|
|
### 빠른 시작
|
|
|
|
폐쇄망에서 사용하려면 다음 파일들을 참고하세요:
|
|
|
|
- **QUICK_START_NEXUS.md**: Nexus 빠른 설정 가이드
|
|
- **NEXUS_SETUP.md**: Nexus 상세 설정 가이드
|
|
- **NEXUS_LOCAL_SETUP.md**: Docker로 로컬 Nexus 테스트 환경 구성
|
|
|
|
### Nexus 설정 방법
|
|
|
|
1. `gradle.properties.example`을 복사하여 `gradle.properties` 생성
|
|
2. Nexus 정보 입력:
|
|
```properties
|
|
nexusUrl=http://nexus.your-company.com:8081
|
|
nexusUsername=your-username
|
|
nexusPassword=your-password
|
|
```
|
|
3. `build.gradle`에서 Nexus 주석 해제 및 mavenCentral() 주석 처리
|
|
4. 빌드: `gradlew.bat clean build`
|
|
|
|
자세한 내용은 **NEXUS_SETUP.md**를 참고하세요.
|
|
|
|
## 설치 및 실행
|
|
|
|
### 1. 데이터베이스 설정
|
|
|
|
MariaDB에 데이터베이스 및 사용자를 생성합니다:
|
|
|
|
```sql
|
|
CREATE DATABASE batch_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
CREATE USER 'batch_user'@'%' IDENTIFIED BY 'batch_password';
|
|
GRANT ALL PRIVILEGES ON batch_db.* TO 'batch_user'@'%';
|
|
FLUSH PRIVILEGES;
|
|
```
|
|
|
|
### 2. 스키마 생성
|
|
|
|
`src/main/resources/db/schema.sql` 파일을 실행하여 필요한 테이블을 생성합니다:
|
|
|
|
```bash
|
|
mysql -u batch_user -p batch_db < src/main/resources/db/schema.sql
|
|
```
|
|
|
|
또는 MySQL 클라이언트에서:
|
|
|
|
```sql
|
|
USE batch_db;
|
|
SOURCE D:/workspace/springbatch-test/src/main/resources/db/schema.sql;
|
|
```
|
|
|
|
### 3. application.yml 수정
|
|
|
|
`src/main/resources/application.yml`에서 데이터베이스 연결 정보를 수정합니다:
|
|
|
|
```yaml
|
|
spring:
|
|
datasource:
|
|
url: jdbc:mariadb://localhost:3306/batch_db
|
|
username: batch_user
|
|
password: batch_password
|
|
```
|
|
|
|
### 4. 빌드 및 실행
|
|
|
|
```bash
|
|
# Gradle 빌드
|
|
./gradlew clean build
|
|
|
|
# 애플리케이션 실행
|
|
./gradlew bootRun
|
|
|
|
# 또는 JAR 파일 실행
|
|
java -jar build/libs/springbatch-test-1.0.0.jar
|
|
```
|
|
|
|
Windows에서는:
|
|
```cmd
|
|
gradlew.bat clean build
|
|
gradlew.bat bootRun
|
|
```
|
|
|
|
## 배치 Job 실행 방법
|
|
|
|
### 1. 스케줄러에 의한 자동 실행
|
|
- 기본 설정: 매일 새벽 2시 실행
|
|
- Quartz Trigger 설정 변경: `BatchScheduler.java`
|
|
|
|
### 2. 수동 실행 (테스트용)
|
|
|
|
REST API를 추가하여 수동 실행할 수 있습니다:
|
|
|
|
```java
|
|
@RestController
|
|
@RequestMapping("/api/batch")
|
|
public class BatchController {
|
|
|
|
@Autowired
|
|
private JobLauncher jobLauncher;
|
|
|
|
@Autowired
|
|
@Qualifier("customerProcessingJob")
|
|
private Job customerProcessingJob;
|
|
|
|
@PostMapping("/run")
|
|
public String runBatch() throws Exception {
|
|
JobParameters jobParameters = new JobParametersBuilder()
|
|
.addLong("timestamp", System.currentTimeMillis())
|
|
.toJobParameters();
|
|
|
|
jobLauncher.run(customerProcessingJob, jobParameters);
|
|
return "Batch job started";
|
|
}
|
|
}
|
|
```
|
|
|
|
## 설정 커스터마이징
|
|
|
|
### 1. Chunk Size 변경
|
|
|
|
`CustomerBatchJobConfig.java`:
|
|
|
|
```java
|
|
private static final int CHUNK_SIZE = 5000; // 원하는 크기로 변경
|
|
private static final int PAGE_SIZE = 5000; // 원하는 크기로 변경
|
|
```
|
|
|
|
### 2. 스케줄 변경
|
|
|
|
`BatchScheduler.java`:
|
|
|
|
```java
|
|
// Cron 표현식 예시:
|
|
// "0 0 2 * * ?" - 매일 02:00
|
|
// "0 0 */6 * * ?" - 6시간마다
|
|
// "0 0/30 * * * ?" - 30분마다
|
|
CronScheduleBuilder.cronSchedule("0 0 2 * * ?")
|
|
```
|
|
|
|
### 3. Skip/Retry 정책 변경
|
|
|
|
`CustomerBatchJobConfig.java`:
|
|
|
|
```java
|
|
.faultTolerant()
|
|
.skip(Exception.class)
|
|
.skipLimit(100) // Skip 허용 횟수
|
|
.retryLimit(3) // Retry 횟수
|
|
.retry(Exception.class)
|
|
```
|
|
|
|
### 4. API 엔드포인트 변경
|
|
|
|
`CustomerBatchJobConfig.java`의 `callExternalApi()` 메서드:
|
|
|
|
```java
|
|
WebClient webClient = WebClient.builder()
|
|
.baseUrl("https://your-api-endpoint.com") // 실제 API URL로 변경
|
|
.build();
|
|
```
|
|
|
|
## 모니터링
|
|
|
|
### 1. 배치 실행 로그 확인
|
|
|
|
```sql
|
|
-- 최근 배치 실행 내역
|
|
SELECT * FROM TB_BATCH_LOG ORDER BY CREATED_AT DESC LIMIT 10;
|
|
|
|
-- 실패한 배치 조회
|
|
SELECT * FROM TB_BATCH_LOG WHERE STATUS = 'FAILED';
|
|
```
|
|
|
|
### 2. Spring Batch 메타데이터 확인
|
|
|
|
```sql
|
|
-- Job 실행 내역
|
|
SELECT * FROM BATCH_JOB_EXECUTION ORDER BY CREATE_TIME DESC;
|
|
|
|
-- Step 실행 상세
|
|
SELECT * FROM BATCH_STEP_EXECUTION ORDER BY START_TIME DESC;
|
|
```
|
|
|
|
### 3. Quartz 스케줄러 상태 확인
|
|
|
|
```sql
|
|
-- 등록된 Job 확인
|
|
SELECT * FROM QRTZ_JOB_DETAILS;
|
|
|
|
-- Trigger 상태 확인
|
|
SELECT * FROM QRTZ_TRIGGERS;
|
|
|
|
-- 클러스터링 상태 확인
|
|
SELECT * FROM QRTZ_SCHEDULER_STATE;
|
|
```
|
|
|
|
## 성능 튜닝 가이드
|
|
|
|
### 1. 대용량 데이터 처리 최적화
|
|
|
|
```yaml
|
|
# application.yml
|
|
batch:
|
|
chunk-size: 5000 # 한 번에 처리할 레코드 수
|
|
page-size: 5000 # DB에서 읽어올 레코드 수
|
|
max-thread-pool-size: 5 # 병렬 처리 스레드 수
|
|
```
|
|
|
|
### 2. DB Connection Pool 조정
|
|
|
|
```yaml
|
|
spring:
|
|
datasource:
|
|
hikari:
|
|
maximum-pool-size: 10
|
|
minimum-idle: 5
|
|
```
|
|
|
|
### 3. MyBatis Batch Insert
|
|
|
|
`CustomerMapper.xml`의 `insertProcessedCustomerBatch`를 사용하면 성능 향상
|
|
|
|
## 다중 서버 운영
|
|
|
|
### Quartz Clustering 설정
|
|
|
|
1. 모든 서버가 같은 데이터베이스를 바라보도록 설정
|
|
2. `application.yml`에서 클러스터링 활성화 (기본 설정됨)
|
|
3. 각 서버는 자동으로 인스턴스 ID를 할당받음
|
|
4. 한 서버에서만 Job이 실행되며, 장애 시 다른 서버가 인계받음
|
|
|
|
## 문제 해결
|
|
|
|
### 1. 배치가 실행되지 않을 때
|
|
|
|
- Quartz 테이블이 생성되었는지 확인
|
|
- `QRTZ_SCHEDULER_STATE` 테이블에서 스케줄러 상태 확인
|
|
- 로그에서 에러 메시지 확인
|
|
|
|
### 2. 중복 실행이 발생할 때
|
|
|
|
- Quartz 클러스터링이 올바르게 설정되었는지 확인
|
|
- 모든 서버가 같은 DB를 사용하는지 확인
|
|
- `@DisallowConcurrentExecution` 어노테이션 확인
|
|
|
|
### 3. 데이터베이스 연결 오류
|
|
|
|
- MariaDB가 실행 중인지 확인
|
|
- 방화벽 설정 확인
|
|
- 연결 정보(URL, 사용자명, 비밀번호) 확인
|
|
|
|
## 라이선스
|
|
|
|
MIT License
|