MSA 환경에서 Spring Batch 메타 테이블 분리하다가 만난 장애

·2025년 12월 16일

troubleshooting

목록 보기
11/11

MSA 환경에서 여러 서비스가 각각 Spring Batch를 사용하는 경우, 배치 메타 테이블을 어떻게 관리할지는 중요한 설계 포인트가 된다고 생각합니다.

서비스별로 Spring Batch 메타 테이블을 분리하는 과정에서@EnableBatchProcessing 하나로 인해 발생한 장애를 정리한 글입니다.

1. 프로젝트 구조

MSA 환경에서 다음과 같은 두 서비스가 존재한다.

  • order-service
    • 주문 / 정산 도메인
    • Spring Batch 사용
  • product-service
    • 공동구매 도메인
    • Spring Batch 사용

각 서비스는 서로 다른 책임과 배치 성격을 가지고 있었기 때문에,
Spring Batch 메타 테이블을 공유하지 않고 서비스별로 분리하는 것이 맞다고 판단했다.


선택한 전략

  • 하나의 DB를 사용하되
  • schema + table prefix를 서비스별로 분리
order-service  → spring_batch_order.BATCH_*
product-service → spring_batch_product.BATCH_*

이를 위해 application.yml에 서비스별 batch 설정을 추가했다.


2. 문제상황

저는 order-service,
다른 팀원은 product-service의 배치를 담당하고 있었습니다.

  • order-service : 정상 동작
  • product-service : 스케줄러 실행 시 배치 실패

발생한 에러 로그

2025-12-15T09:30:00.022+09:00 ERROR 21134 --- [product] [   scheduling-1] [6ed7fab02e17e295683ebf388b58b4ed-0c2a9acf9b67a3c1] s._.p.b.s.GroupPurchaseOpenScheduler     : 공동 구매 오픈 배치 실패
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME
FROM BATCH_JOB_INSTANCE
WHERE JOB_NAME = ?
 AND JOB_KEY = ?]
	at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:134) ~[spring-jdbc-6.2.14.jar:6.2.14]
	
 // 생략   
	at java.base/java.lang.Thread.run(Thread.java:840) ~[na:na]
Caused by: org.postgresql.util.PSQLException: ERROR: relation "batch_job_instance" does not exist
  Position: 39
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2736) ~[postgresql-42.7.8.jar:42.7.8]

// 생략

팀원분께 에러 상황에 대해 공유 받았고 확인해본 결과

ERROR: relation "batch_job_instance" does not exist

라는 에러가 발생한 상황이다.

SELECT JOB_INSTANCE_ID, JOB_NAME
FROM BATCH_JOB_INSTANCE
WHERE JOB_NAME = ?
  AND JOB_KEY = ?

Spring Batch 내부에서 실행된 SQL은 위와 같다.

하지만 실제로 사용중인 테이블은 아래와 같다.

spring_batch_product.BATCH_JOB_INSTANCE

결론이 spring batch가 따로 설정한
schema / table prefix 를 인식하지 못하는 상황인 것으로 파악했다.


3. 왜 기본 테이블을 찾았을까?

Spring Batch는 왜 BATCH_JOB_INSTANCE를 그대로 조회했을까?

Spring Batch는 Job 실행 시 다음 인프라 빈을 사용한다.

  • JobRepository
  • JobExplorer
  • JobLauncher
  • 내부 DAO (JdbcJobInstanceDao 등)

이 DAO들은 메타 테이블을 직접 조회한다.


4. 진짜 원인

@EnableRetry
@EnableScheduling
@EnableFeignClients
@EnableBatchProcessing
@SpringBootApplication
public class ProductApplication {
	public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class, args);
    }
}

@EnableBatchProcessing을 붙이면?

  • Spring Batch 인프라 빈을 자동 등록
  • 내부적으로 다음 객체들을 기본 설정으로 생성
    • JobRepository
    • JobExplorer
    • JobLauncher
    • JdbcJobInstanceDao

이때 생성되는 DAO들은 기본 테이블 이름을 하드코딩된 값으로 사용된다.

즉, 우리가 설정한
커스텀 DataSource, schema 분리, table prefix 전략이 전부 무시된 상태이다.


5. 배운점

이번 경험을 통해
Spring Batch는 단순히 Job/Step만 작성하는 프레임워크가 아니라, 메타 테이블과 인프라 설계가 핵심인 기술이라는 점을 다시 체감했다.

Spring Boot의 Auto Configuration은
항상 ‘편의’를 제공하지만, 모든 상황에 안전한 것은 아니다.

특히 MSA 환경에서는 명시적인 인프라 설정이 버그를 줄이고 운영 안정성을 높인다.




0개의 댓글