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.
378 lines
8.8 KiB
Markdown
378 lines
8.8 KiB
Markdown
|
3 weeks ago
|
# Spring Batch 프로젝트 설정 가이드
|
||
|
|
|
||
|
|
## 1. 개발 환경 준비
|
||
|
|
|
||
|
|
### 필수 설치 항목
|
||
|
|
- OpenJDK 1.8 이상
|
||
|
|
- MariaDB 10.x 이상
|
||
|
|
- Gradle 6.x 이상 (또는 Wrapper 사용)
|
||
|
|
|
||
|
|
## 2. 데이터베이스 설정
|
||
|
|
|
||
|
|
### 2.1 MariaDB 설치 및 실행
|
||
|
|
|
||
|
|
Windows:
|
||
|
|
```cmd
|
||
|
|
# MariaDB 다운로드 및 설치
|
||
|
|
# https://mariadb.org/download/
|
||
|
|
|
||
|
|
# MariaDB 서비스 시작
|
||
|
|
net start MySQL
|
||
|
|
```
|
||
|
|
|
||
|
|
Linux:
|
||
|
|
```bash
|
||
|
|
sudo systemctl start mariadb
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2.2 데이터베이스 및 사용자 생성
|
||
|
|
|
||
|
|
```sql
|
||
|
|
-- MariaDB에 접속
|
||
|
|
mysql -u root -p
|
||
|
|
|
||
|
|
-- 데이터베이스 생성
|
||
|
|
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;
|
||
|
|
|
||
|
|
-- 확인
|
||
|
|
SHOW DATABASES;
|
||
|
|
SELECT user, host FROM mysql.user WHERE user = 'batch_user';
|
||
|
|
|
||
|
|
-- 종료
|
||
|
|
EXIT;
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2.3 스키마 생성
|
||
|
|
|
||
|
|
#### 방법 1: 명령줄에서 실행 (권장)
|
||
|
|
|
||
|
|
Windows:
|
||
|
|
```cmd
|
||
|
|
cd D:\workspace\springbatch-test
|
||
|
|
mysql -u batch_user -p batch_db < src\main\resources\db\schema.sql
|
||
|
|
```
|
||
|
|
|
||
|
|
Linux:
|
||
|
|
```bash
|
||
|
|
cd /path/to/springbatch-test
|
||
|
|
mysql -u batch_user -p batch_db < src/main/resources/db/schema.sql
|
||
|
|
```
|
||
|
|
|
||
|
|
#### 방법 2: MySQL 클라이언트에서 실행
|
||
|
|
|
||
|
|
```sql
|
||
|
|
mysql -u batch_user -p
|
||
|
|
USE batch_db;
|
||
|
|
SOURCE D:/workspace/springbatch-test/src/main/resources/db/schema.sql;
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2.4 테이블 생성 확인
|
||
|
|
|
||
|
|
```sql
|
||
|
|
USE batch_db;
|
||
|
|
SHOW TABLES;
|
||
|
|
|
||
|
|
-- 예상 출력:
|
||
|
|
-- BATCH_JOB_EXECUTION
|
||
|
|
-- BATCH_JOB_EXECUTION_CONTEXT
|
||
|
|
-- BATCH_JOB_EXECUTION_PARAMS
|
||
|
|
-- BATCH_JOB_EXECUTION_SEQ
|
||
|
|
-- BATCH_JOB_INSTANCE
|
||
|
|
-- BATCH_JOB_SEQ
|
||
|
|
-- BATCH_STEP_EXECUTION
|
||
|
|
-- BATCH_STEP_EXECUTION_CONTEXT
|
||
|
|
-- BATCH_STEP_EXECUTION_SEQ
|
||
|
|
-- QRTZ_* (Quartz 관련 테이블들)
|
||
|
|
-- TB_CUSTOMER
|
||
|
|
-- TB_CUSTOMER_PROCESSED
|
||
|
|
-- TB_BATCH_LOG
|
||
|
|
```
|
||
|
|
|
||
|
|
## 3. 애플리케이션 설정
|
||
|
|
|
||
|
|
### 3.1 application.yml 수정
|
||
|
|
|
||
|
|
`src/main/resources/application.yml` 파일에서 데이터베이스 연결 정보를 확인/수정:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
spring:
|
||
|
|
datasource:
|
||
|
|
url: jdbc:mariadb://localhost:3306/batch_db
|
||
|
|
username: batch_user
|
||
|
|
password: batch_password
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3.2 스케줄 설정 (선택사항)
|
||
|
|
|
||
|
|
테스트를 위해 스케줄을 짧게 설정하려면 `src/main/java/com/example/batch/scheduler/BatchScheduler.java` 수정:
|
||
|
|
|
||
|
|
```java
|
||
|
|
// 기본: 매일 새벽 2시
|
||
|
|
CronScheduleBuilder.cronSchedule("0 0 2 * * ?")
|
||
|
|
|
||
|
|
// 테스트용: 30초마다 실행
|
||
|
|
CronScheduleBuilder.cronSchedule("0/30 * * * * ?")
|
||
|
|
```
|
||
|
|
|
||
|
|
## 4. 프로젝트 빌드 및 실행
|
||
|
|
|
||
|
|
### 4.1 Gradle Wrapper 생성 (처음 한 번만)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
gradle wrapper
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4.2 빌드
|
||
|
|
|
||
|
|
Windows:
|
||
|
|
```cmd
|
||
|
|
gradlew.bat clean build
|
||
|
|
```
|
||
|
|
|
||
|
|
Linux/Mac:
|
||
|
|
```bash
|
||
|
|
./gradlew clean build
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4.3 실행
|
||
|
|
|
||
|
|
Windows:
|
||
|
|
```cmd
|
||
|
|
gradlew.bat bootRun
|
||
|
|
```
|
||
|
|
|
||
|
|
Linux/Mac:
|
||
|
|
```bash
|
||
|
|
./gradlew bootRun
|
||
|
|
```
|
||
|
|
|
||
|
|
또는 JAR 파일로 실행:
|
||
|
|
```bash
|
||
|
|
java -jar build/libs/springbatch-test-1.0.0.jar
|
||
|
|
```
|
||
|
|
|
||
|
|
## 5. 배치 실행 테스트
|
||
|
|
|
||
|
|
### 5.1 수동 실행 (REST API)
|
||
|
|
|
||
|
|
배치 잡을 수동으로 실행:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl -X POST http://localhost:8080/api/batch/customer/run
|
||
|
|
```
|
||
|
|
|
||
|
|
또는 브라우저/Postman에서:
|
||
|
|
```
|
||
|
|
POST http://localhost:8080/api/batch/customer/run
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5.2 상태 확인
|
||
|
|
|
||
|
|
Health Check:
|
||
|
|
```bash
|
||
|
|
curl http://localhost:8080/api/batch/health
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5.3 배치 실행 로그 확인
|
||
|
|
|
||
|
|
데이터베이스에서 확인:
|
||
|
|
```sql
|
||
|
|
-- 배치 실행 로그
|
||
|
|
SELECT * FROM TB_BATCH_LOG ORDER BY CREATED_AT DESC;
|
||
|
|
|
||
|
|
-- 처리된 고객 데이터
|
||
|
|
SELECT * FROM TB_CUSTOMER_PROCESSED ORDER BY PROCESSED_AT DESC;
|
||
|
|
|
||
|
|
-- Spring Batch 메타데이터
|
||
|
|
SELECT
|
||
|
|
je.JOB_EXECUTION_ID,
|
||
|
|
ji.JOB_NAME,
|
||
|
|
je.STATUS,
|
||
|
|
je.START_TIME,
|
||
|
|
je.END_TIME
|
||
|
|
FROM BATCH_JOB_EXECUTION je
|
||
|
|
JOIN BATCH_JOB_INSTANCE ji ON je.JOB_INSTANCE_ID = ji.JOB_INSTANCE_ID
|
||
|
|
ORDER BY je.CREATE_TIME DESC;
|
||
|
|
```
|
||
|
|
|
||
|
|
## 6. 다중 서버 테스트
|
||
|
|
|
||
|
|
### 6.1 동일한 애플리케이션을 다른 포트로 실행
|
||
|
|
|
||
|
|
터미널 1:
|
||
|
|
```bash
|
||
|
|
java -jar build/libs/springbatch-test-1.0.0.jar --server.port=8080
|
||
|
|
```
|
||
|
|
|
||
|
|
터미널 2:
|
||
|
|
```bash
|
||
|
|
java -jar build/libs/springbatch-test-1.0.0.jar --server.port=8081
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6.2 클러스터링 확인
|
||
|
|
|
||
|
|
Quartz 스케줄러 상태 확인:
|
||
|
|
```sql
|
||
|
|
SELECT * FROM QRTZ_SCHEDULER_STATE;
|
||
|
|
```
|
||
|
|
|
||
|
|
두 개의 인스턴스가 표시되어야 하며, 배치는 한 서버에서만 실행됩니다.
|
||
|
|
|
||
|
|
## 7. 대용량 데이터 테스트
|
||
|
|
|
||
|
|
### 7.1 테스트 데이터 생성
|
||
|
|
|
||
|
|
대용량 데이터 삽입 스크립트:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
-- 100만 건 테스트 데이터 생성 (약 1-2분 소요)
|
||
|
|
DELIMITER $$
|
||
|
|
|
||
|
|
DROP PROCEDURE IF EXISTS generate_customers$$
|
||
|
|
|
||
|
|
CREATE PROCEDURE generate_customers(IN num_rows INT)
|
||
|
|
BEGIN
|
||
|
|
DECLARE i INT DEFAULT 0;
|
||
|
|
DECLARE batch_size INT DEFAULT 10000;
|
||
|
|
|
||
|
|
WHILE i < num_rows DO
|
||
|
|
INSERT INTO TB_CUSTOMER (CUSTOMER_NAME, EMAIL, PHONE, ADDRESS, STATUS)
|
||
|
|
SELECT
|
||
|
|
CONCAT('Customer ', i + seq) as CUSTOMER_NAME,
|
||
|
|
CONCAT('customer', i + seq, '@example.com') as EMAIL,
|
||
|
|
CONCAT('010-', LPAD(FLOOR(RAND() * 10000), 4, '0'), '-', LPAD(FLOOR(RAND() * 10000), 4, '0')) as PHONE,
|
||
|
|
CONCAT('Address ', FLOOR(RAND() * 1000)) as ADDRESS,
|
||
|
|
'ACTIVE' as STATUS
|
||
|
|
FROM (
|
||
|
|
SELECT @row := @row + 1 as seq
|
||
|
|
FROM (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
|
||
|
|
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,
|
||
|
|
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
|
||
|
|
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2,
|
||
|
|
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
|
||
|
|
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t3,
|
||
|
|
(SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
|
||
|
|
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t4,
|
||
|
|
(SELECT @row := 0) r
|
||
|
|
LIMIT batch_size
|
||
|
|
) seq_table
|
||
|
|
WHERE i + seq <= num_rows;
|
||
|
|
|
||
|
|
SET i = i + batch_size;
|
||
|
|
|
||
|
|
-- 진행 상황 출력
|
||
|
|
SELECT CONCAT('Inserted ', i, ' / ', num_rows, ' records') AS Progress;
|
||
|
|
END WHILE;
|
||
|
|
END$$
|
||
|
|
|
||
|
|
DELIMITER ;
|
||
|
|
|
||
|
|
-- 100만 건 생성 (테스트용)
|
||
|
|
CALL generate_customers(1000000);
|
||
|
|
|
||
|
|
-- 데이터 확인
|
||
|
|
SELECT COUNT(*) FROM TB_CUSTOMER;
|
||
|
|
```
|
||
|
|
|
||
|
|
### 7.2 성능 측정
|
||
|
|
|
||
|
|
배치 실행 후 성능 확인:
|
||
|
|
```sql
|
||
|
|
SELECT
|
||
|
|
JOB_NAME,
|
||
|
|
STATUS,
|
||
|
|
START_TIME,
|
||
|
|
END_TIME,
|
||
|
|
TIMESTAMPDIFF(SECOND, START_TIME, END_TIME) as DURATION_SECONDS,
|
||
|
|
TOTAL_COUNT,
|
||
|
|
SUCCESS_COUNT,
|
||
|
|
FAIL_COUNT,
|
||
|
|
ROUND(TOTAL_COUNT / TIMESTAMPDIFF(SECOND, START_TIME, END_TIME), 2) as RECORDS_PER_SECOND
|
||
|
|
FROM TB_BATCH_LOG
|
||
|
|
ORDER BY START_TIME DESC
|
||
|
|
LIMIT 10;
|
||
|
|
```
|
||
|
|
|
||
|
|
## 8. 트러블슈팅
|
||
|
|
|
||
|
|
### 8.1 데이터베이스 연결 오류
|
||
|
|
|
||
|
|
```
|
||
|
|
Error: Communications link failure
|
||
|
|
```
|
||
|
|
|
||
|
|
해결방법:
|
||
|
|
1. MariaDB 서비스 실행 확인
|
||
|
|
2. 포트 확인 (기본: 3306)
|
||
|
|
3. 방화벽 설정 확인
|
||
|
|
4. application.yml의 연결 정보 확인
|
||
|
|
|
||
|
|
### 8.2 Quartz 테이블 오류
|
||
|
|
|
||
|
|
```
|
||
|
|
Error: Table 'batch_db.QRTZ_LOCKS' doesn't exist
|
||
|
|
```
|
||
|
|
|
||
|
|
해결방법:
|
||
|
|
schema.sql 파일을 다시 실행하여 Quartz 테이블 생성
|
||
|
|
|
||
|
|
### 8.3 Batch 테이블 오류
|
||
|
|
|
||
|
|
```
|
||
|
|
Error: Table 'batch_db.BATCH_JOB_INSTANCE' doesn't exist
|
||
|
|
```
|
||
|
|
|
||
|
|
해결방법:
|
||
|
|
schema.sql 파일을 다시 실행하여 Spring Batch 메타데이터 테이블 생성
|
||
|
|
|
||
|
|
### 8.4 메모리 부족 오류
|
||
|
|
|
||
|
|
```
|
||
|
|
java.lang.OutOfMemoryError: Java heap space
|
||
|
|
```
|
||
|
|
|
||
|
|
해결방법:
|
||
|
|
JVM 힙 메모리 증가:
|
||
|
|
```bash
|
||
|
|
java -Xmx2g -jar build/libs/springbatch-test-1.0.0.jar
|
||
|
|
```
|
||
|
|
|
||
|
|
또는 Chunk Size 감소:
|
||
|
|
```java
|
||
|
|
private static final int CHUNK_SIZE = 1000; // 5000 -> 1000
|
||
|
|
```
|
||
|
|
|
||
|
|
## 9. 프로덕션 체크리스트
|
||
|
|
|
||
|
|
- [ ] 데이터베이스 연결 정보를 환경변수로 관리
|
||
|
|
- [ ] 로그 레벨을 INFO로 변경
|
||
|
|
- [ ] 스케줄 시간을 프로덕션 요구사항에 맞게 조정
|
||
|
|
- [ ] API 엔드포인트를 실제 서비스로 변경
|
||
|
|
- [ ] 에러 알림 시스템 연동 (이메일, Slack 등)
|
||
|
|
- [ ] 모니터링 도구 연동 (Prometheus, Grafana 등)
|
||
|
|
- [ ] Chunk Size와 성능 튜닝
|
||
|
|
- [ ] 배치 실행 결과 알림 설정
|
||
|
|
- [ ] 데이터베이스 백업 정책 수립
|
||
|
|
- [ ] 서버 리소스 모니터링 설정
|
||
|
|
|
||
|
|
## 10. 다음 단계
|
||
|
|
|
||
|
|
1. **파일 기반 배치 추가**: CSV/Excel 파일 읽기 처리
|
||
|
|
2. **멀티 스레드 처리**: 병렬 처리로 성능 향상
|
||
|
|
3. **파티셔닝**: 대용량 데이터를 분할 처리
|
||
|
|
4. **동적 Job Parameter**: UI에서 파라미터 설정
|
||
|
|
5. **배치 모니터링 대시보드**: Web UI 추가
|
||
|
|
6. **실패 재처리**: 실패한 건만 재실행하는 기능
|
||
|
|
7. **알림 시스템**: 배치 완료/실패 시 알림
|
||
|
|
|
||
|
|
## 참고 자료
|
||
|
|
|
||
|
|
- [Spring Batch Documentation](https://docs.spring.io/spring-batch/docs/current/reference/html/)
|
||
|
|
- [Quartz Scheduler Documentation](http://www.quartz-scheduler.org/documentation/)
|
||
|
|
- [MyBatis Documentation](https://mybatis.org/mybatis-3/)
|