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.

8.4 KiB

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 정보 입력:
    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에 데이터베이스 및 사용자를 생성합니다:

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 파일을 실행하여 필요한 테이블을 생성합니다:

mysql -u batch_user -p batch_db < src/main/resources/db/schema.sql

또는 MySQL 클라이언트에서:

USE batch_db;
SOURCE D:/workspace/springbatch-test/src/main/resources/db/schema.sql;

3. application.yml 수정

src/main/resources/application.yml에서 데이터베이스 연결 정보를 수정합니다:

spring:
  datasource:
    url: jdbc:mariadb://localhost:3306/batch_db
    username: batch_user
    password: batch_password

4. 빌드 및 실행

# Gradle 빌드
./gradlew clean build

# 애플리케이션 실행
./gradlew bootRun

# 또는 JAR 파일 실행
java -jar build/libs/springbatch-test-1.0.0.jar

Windows에서는:

gradlew.bat clean build
gradlew.bat bootRun

배치 Job 실행 방법

1. 스케줄러에 의한 자동 실행

  • 기본 설정: 매일 새벽 2시 실행
  • Quartz Trigger 설정 변경: BatchScheduler.java

2. 수동 실행 (테스트용)

REST API를 추가하여 수동 실행할 수 있습니다:

@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:

private static final int CHUNK_SIZE = 5000;  // 원하는 크기로 변경
private static final int PAGE_SIZE = 5000;   // 원하는 크기로 변경

2. 스케줄 변경

BatchScheduler.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:

.faultTolerant()
.skip(Exception.class)
.skipLimit(100)     // Skip 허용 횟수
.retryLimit(3)      // Retry 횟수
.retry(Exception.class)

4. API 엔드포인트 변경

CustomerBatchJobConfig.javacallExternalApi() 메서드:

WebClient webClient = WebClient.builder()
    .baseUrl("https://your-api-endpoint.com")  // 실제 API URL로 변경
    .build();

모니터링

1. 배치 실행 로그 확인

-- 최근 배치 실행 내역
SELECT * FROM TB_BATCH_LOG ORDER BY CREATED_AT DESC LIMIT 10;

-- 실패한 배치 조회
SELECT * FROM TB_BATCH_LOG WHERE STATUS = 'FAILED';

2. Spring Batch 메타데이터 확인

-- Job 실행 내역
SELECT * FROM BATCH_JOB_EXECUTION ORDER BY CREATE_TIME DESC;

-- Step 실행 상세
SELECT * FROM BATCH_STEP_EXECUTION ORDER BY START_TIME DESC;

3. Quartz 스케줄러 상태 확인

-- 등록된 Job 확인
SELECT * FROM QRTZ_JOB_DETAILS;

-- Trigger 상태 확인
SELECT * FROM QRTZ_TRIGGERS;

-- 클러스터링 상태 확인
SELECT * FROM QRTZ_SCHEDULER_STATE;

성능 튜닝 가이드

1. 대용량 데이터 처리 최적화

# application.yml
batch:
  chunk-size: 5000          # 한 번에 처리할 레코드 수
  page-size: 5000           # DB에서 읽어올 레코드 수
  max-thread-pool-size: 5   # 병렬 처리 스레드 수

2. DB Connection Pool 조정

spring:
  datasource:
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5

3. MyBatis Batch Insert

CustomerMapper.xmlinsertProcessedCustomerBatch를 사용하면 성능 향상

다중 서버 운영

Quartz Clustering 설정

  1. 모든 서버가 같은 데이터베이스를 바라보도록 설정
  2. application.yml에서 클러스터링 활성화 (기본 설정됨)
  3. 각 서버는 자동으로 인스턴스 ID를 할당받음
  4. 한 서버에서만 Job이 실행되며, 장애 시 다른 서버가 인계받음

문제 해결

1. 배치가 실행되지 않을 때

  • Quartz 테이블이 생성되었는지 확인
  • QRTZ_SCHEDULER_STATE 테이블에서 스케줄러 상태 확인
  • 로그에서 에러 메시지 확인

2. 중복 실행이 발생할 때

  • Quartz 클러스터링이 올바르게 설정되었는지 확인
  • 모든 서버가 같은 DB를 사용하는지 확인
  • @DisallowConcurrentExecution 어노테이션 확인

3. 데이터베이스 연결 오류

  • MariaDB가 실행 중인지 확인
  • 방화벽 설정 확인
  • 연결 정보(URL, 사용자명, 비밀번호) 확인

라이선스

MIT License