3 min read

Part 12. 통합 레퍼런스 아키텍처와 최종 선택 가이드

@Scheduled, Quartz, Spring Batch, 수동 배치를 실제 운영 조건에 맞게 조합하는 최종 의사결정 매트릭스와 참조 아키텍처를 제시한다.

Series: Spring Boot 배치 전략 완전 정복

12편 구성. 현재 12편을 보고 있습니다.

Progress100% Complete
SERIES COMPLETE

썸네일 - 운영 아키텍처 통합
썸네일 - 운영 아키텍처 통합

출처: Pexels - Server racks on data center

버전 기준

  • Java 21
  • Spring Boot 3.3.x
  • Spring Batch 5.2.x
  • Quartz 2.3.x
  • PostgreSQL 15
  • OpenSearch 2.x

1) 문제 제기

실무에서 흔한 실패는 기술 선택 자체가 아니라 "모든 배치를 하나의 도구로 해결하려는 시도"에서 시작된다. 정시 정산, 재색인, 운영자 재처리, 이벤트 보정은 요구사항이 다르다. 따라서 단일 정답은 없다. 정답은 조합이다.

이 최종편의 목표는 두 가지다.

  • 요구사항을 빠르게 분류해 적절한 실행 모델을 고른다.
  • 장애/성능/운영 복잡도를 함께 고려한 현실적인 기준을 제공한다.

2) 핵심 개념 정리

통합 선택 매트릭스

요구사항1차 선택2차 보완비고
단순 주기 작업(인스턴스 1~2)@Scheduled멱등 키 + 실행 이력빠른 시작에 유리
복잡 스케줄/캘린더/MisfireQuartzJDBCJobStore + 대시보드운영 제어 강함
대량 데이터 변환/재시작 필요Spring BatchKeyset Reader + Chunk 튜닝표준 선택
운영자 개입 재처리수동 배치 API/UI권한/감사/롤백통제/재현성 확보
대량 검색 색인Spring Batch + OpenSearch BulkPIT + Search After검색 클러스터 한도 반영

실행 계층 분리 원칙

  • 트리거 계층: @Scheduled/Quartz/K8s CronJob
  • 처리 계층: Spring Batch Step/Chunk
  • 데이터 계층: DB Keyset/Range + OpenSearch Bulk
  • 제어 계층: 락/리더 선출/멱등성
  • 운영 계층: 관측성/경보/DLQ/수동 재처리

참조 아키텍처 다이어그램

Mermaid diagram rendering...

본문 이미지 - 운영팀 협업
본문 이미지 - 운영팀 협업

출처: Pexels - Security control room team

3) 코드 예시

예시 A: 통합 오케스트레이터 인터페이스

public interface BatchOrchestrator {
    Long launchScheduled(String jobName, LocalDateTime scheduledAt);
    Long launchManual(String jobName, Map<String, String> params, String requestedBy);
    Long launchRecovery(String jobName, Long failedExecutionId);
}

@Service
@RequiredArgsConstructor
public class DefaultBatchOrchestrator implements BatchOrchestrator {

    private final ExecutionGuard executionGuard;
    private final JobLauncher jobLauncher;

    @Override
    public Long launchScheduled(String jobName, LocalDateTime scheduledAt) {
        String dedupKey = jobName + ":" + scheduledAt.toString();
        executionGuard.assertNotRunning(dedupKey);
        return run(jobName, Map.of("scheduledAt", scheduledAt.toString(), "dedupKey", dedupKey));
    }

    private Long run(String jobName, Map<String, String> params) {
        // 실행 이력 저장 후 Spring Batch Job launch
        return 1L;
    }
}

예시 B: 운영 대시보드용 SQL

SELECT job_name,
       COUNT(*) FILTER (WHERE status = 'SUCCEEDED') AS success_count,
       COUNT(*) FILTER (WHERE status = 'FAILED') AS failed_count,
       AVG(duration_ms) AS avg_duration_ms,
       PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY duration_ms) AS p99_duration_ms
FROM batch_job_execution
WHERE started_at >= NOW() - INTERVAL '24 hour'
GROUP BY job_name
ORDER BY failed_count DESC, p99_duration_ms DESC;

예시 C: 재처리 대상 Keyset 조회

SELECT id, job_name, error_code, started_at
FROM batch_job_execution
WHERE status = 'FAILED'
  AND id > :last_id
ORDER BY id ASC
LIMIT 300;

예시 D: OpenSearch 증분 동기화 Query

POST /_search
{
  "size": 1000,
  "sort": [
    { "updated_at": "asc" },
    { "_id": "asc" }
  ],
  "search_after": ["2026-03-03T08:00:00Z", "product-9988"],
  "query": {
    "range": {
      "updated_at": { "gte": "2026-03-03T00:00:00Z" }
    }
  }
}

4) 실제 장애/운영 시나리오

상황: 블랙프라이데이 트래픽에서 주문 정산(Quartz), 상품 색인(Spring Batch+OpenSearch), 운영자 재처리 API가 동시에 증가했다. 공통 DB 커넥션 풀이 고갈되며 전체 배치가 지연되고 일부는 timeout으로 실패했다.

원인:

  • 각 배치가 개별 최적화되어 전체 시스템 한도 모델이 없었다.
  • 리소스 우선순위(정산 > 재색인 > 리포트)가 설정되지 않았다.
  • 실패 배치 재시도가 즉시 수행되어 부하를 증폭했다.

개선:

  1. 배치 유형별 리소스 버짓(CPU/DB pool/IO) 고정.
  2. 우선순위 큐 도입과 저우선 작업의 자동 지연.
  3. 실패 재시도에 지수 백오프 + 혼잡 시간대 실행 금지 윈도우 적용.

5) 설계 체크리스트

  • 배치 요구사항을 스케줄/이벤트/수동/대량/NRT로 먼저 분류하는가?
  • 실행 주체(@Scheduled/Quartz/K8s/수동)를 명확히 정의했는가?
  • DB 조회 전략을 Keyset/Range 중심으로 설계했는가?
  • OpenSearch는 PIT + Search After + Bulk 제어를 사용하는가?
  • 락/리더 선출/멱등성/펜싱 토큰이 함께 설계되어 있는가?
  • DLQ와 재처리 운영 절차가 문서화되어 있는가?
  • 성능 목표와 장애 복구 목표(RTO/RPO)가 수치로 관리되는가?

6) 요약

이 시리즈의 결론은 단순하다. 배치는 기술 문제가 아니라 운영 시스템 문제다. @Scheduled, Quartz, Spring Batch, 수동 배치는 경쟁 관계가 아니라 역할 분담 관계다. 요구사항, 실패 모델, 운영 역량에 맞춰 조합해야 한다.

7) 다음 편 예고

이번 편으로 시리즈는 종료된다. 후속 글에서는 실제 샘플 프로젝트를 기반으로 "단일 서비스에서 4가지 배치 모델을 공존"시키는 구현 레포 구조와 관측 대시보드 템플릿을 다룰 예정이다.

참고 링크

시리즈 네비게이션

댓글