강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

tjrwn0716님의 프로필 이미지
tjrwn0716

작성한 질문수

죽음의 Spring Batch: 새벽 3시의 처절한 공포는 이제 끝이다.

5장. 작전2: Run Squad 장악 작전 - 배치 실행의 진입점과 Spring Batch 자동 구성(시스템이 스스로 무장하는 순간 🏴‍☠️)

TransactionManager 분리

작성

·

8

1

TransactionManager 분리

에 대해서 이해가 잘 가지 않는게 있어.

 

실제 운영 환경에서는 배치와 비즈니스 데이터 DB를 분리하는게 필수라고 했잖아?

근데 이 분리의 단위가 배치용 메타데이터 저장만 분리를 하는게 맞는거야?

 

현재 사이드 프로젝트에서 멀티모듈 구조에 (MSA는 아님) API 모듈과 배치 모듈을 따로 분리한 상태야.

유저 데이터에서 생일을 뽑아서 내일 생일인 유저에게 FCM 을 발송하는 배치를 만드는데,

이때 만들어준 예제처럼 @BatchDataSource와 비즈니스 로직용 @Primary DataSource를 분리하게 되면,

API 모듈용 DB Connnection을 배치에서도 똑같이 갖다 쓰는거 아니야 ??

 

즉, 배치에서 API 쪽 커넥션을 가져다 써서 배치가 돌 때 커넥션이 고갈날 수 있지 않을까? 라는 생각이 들었어

  1. 지금 이해한 바로는 @BatchDataSource, @BatchTransactionManager를 분리하고 주입해줘도
    Reader -> Processor -> Writer 에는 @Primary 걸 쓰는것 같은데 맞아 ?

  2. 나는 DB 분리와 함께, 비즈니스 로직에 대한 커넥션, 트랜잭션도 배치용으로 분리하고 싶은데 이럴땐 어떻게 해야해?

  3. 특히나 배치에서도 JpaTransactionManager를 쓰고 싶은 경우에는 어떻게 해야해 ?

원하는 바는, API 처리용 DB 커넥션은 커넥션대로 있고, 배치 메타데이터용 커넥션 따로, 배치에서 라이브 DB에서 유저 데이터를 가져오는 커넥션 따로 구성하고 싶어 (배치가 API 모듈 에 영향을 주지 않았으면 해서,,,)

 

혹시 내가 강의를 제대로 이해를 못한거라면 알려줘

답변 2

1

KILL-9님의 프로필 이미지
KILL-9
지식공유자

**TransactionManager 분리**
또 보는구나 석주형.
내가 잘못 이해한 거일 수 있지만 (아마 내가 이해한 게 맞을 것이다)

형은 지금 실제 서비스하는 온라인 웹앱에서 배치도 같이 돌리는 시나리오를 가정하고 질문한 것으로 보인다. 맞나?

굳이 "멀티모듈 구조"라는 단어를 쓴 걸 보니, '같은 애플리케이션 안에서 모듈만 나눴다'는 소리로 들린다.
(내가 이해한 게 아니면 말해라)

---

## 배치와 온라인 앱은 별개 프로세스다

너무 당연하게 생각하고 설명을 안 한 건가 싶은데,

**일반적으로 사용자에게 서비스하는 온라인 앱과 배치 앱은 아예 별도의 프로세스로 돌아야 맞다.**

따라서 코드베이스도 달라야 일반적인 거지. 다른 프로젝트로 구성하는 게 일반적이라는 의미다.

너가 걱정하는 API 서버용 데이터소스 분리? 걱정 안 해도 된다. 
**일반적인 배치 앱 구성의 올바른 설계가 이미 그걸 해결해주니까.**

---

## 이렇게 생각해보자

**시나리오 1: 배포 상황**
배치가 돌고 있는데 정기 배포든 긴급 배포든 온라인 서비스 배포를 한다고 하자.
배치 서버는 어떻게 해야 할까?

**시나리오 2: 리소스 경합**
배치 서버에서 수백만/수천만 데이터를 다룬다고 가정하자. 
이 서버에서 온라인 트랜잭션을 다루는 게 맞을까? 사용자 요청 tps가 한 두 건도 아닐텐데말이다.

---

## 배치? 별도 프로세스

다시 말해, **배치 앱은 일반 사용자 대상 실시간 온라인 앱과는 별도의 프로젝트**라고 생각해야 한다. 
아니, 실제로 보통 그렇게 설계해야 한다.

기존 사용자 요청을 받는 앱에 배치를 포함시키는 게 아니라, 
**별도의 프로세스(별도 서버에서)로 배치 앱을 돌려야 한다는 것이다.**

그래서 우리 강의의 거의 대부분의 예제가 커맨드라인으로 별도의 프로세스를 실행하도록 되어 있는 거다. 

---

## 그럼 우리 강의의 "온라인 어플리케이션에서 배치 실행"은 뭐냐고?

일반적으로 온라인 어플리케이션에서 배치를 돌린다는 것은 
**사용자 대상 서비스가 아닌 팀 내부 서비스 또는 어드민 툴** 등을 의미한다.

그럼 왜 "비즈니스 데이터"라고 했냐고?

**배치는 비즈니스를 위해 존재한다.**

보통 배치는 온라인 웹 서비스의 데이터 처리를 보완하기 위해 존재한다.

비록 다른 프로세스로 동작할 순 있지만, **바라보는 DB는 동일하다.**
(마스터를 보냐 슬레이브를 보냐에 차이는 있을 것이다)

---

## 💀 더 나아가: 데이터소스 분리는 무궁무진하다

데이터소스를 나누는 방법은 사실 **무궁무진하다.** 사실 이건 **구현하기 나름이다.**

너도 알겠지만, 실제 프로덕션 서비스에서는 (장난감이 아닌 한) 
스프링 부트가 자동으로 구성해주는 단일 데이터소스만을 사용하는 것은 **말이 안 된다.** 

따라서 별도의 데이터소스들을 직접 정의해주어야 하지.

**스프링 배치도 마찬가지다. 특별할 것 없다. 동일한 스프링 앱이다.**

여러 데이터소스가 필요하면 여러 개를 구성해주면 된다.
일반 스프링 웹앱에서 하던 방식 그대로 분리하면 된다.

강의의 `@Primary` 등의 사용은 **예시에 불과하다.**
주입받을 빈을 어떻게 구성하고 퀄리파잉할지 등의 방법은 **구성하기 나름이다.**

다 이미 알고 있는 내용일 거다. **(스프링 배치도 스프링이다)**

---

## 더 나아가: 샤딩 환경

대용량 트래픽을 다루는 서비스에서는 단순 DB 분리를 넘어 
**DB당 (논리 데이터소스 그룹당) 샤드가 수십 개 이상 (또는 그 이상) 관리되기 마련이다.**

이런 경우 추가적인 DataSource 목록 관리 방법이 필요하다.
이 또한 별도의 구성이 필요하며, **배치에서는 웹앱에서 하는 방식 그대로 바라보면 된다. 스프링을 사용하는 조직에서 배치 프레임워크로 스프링 배치를 사용하는 이유이기도하다.**

**정해진 방법이 있는 게 아니다.**

---

## 마무리

내 설명이 다소 어렵다면 다시 댓글을 달아달라. 더 세세하게 이야기해보자.

현재 시간 4:24 AM.
일단 급히 대답 남기고 취침으로 들어간다.

**사소한 것도 이해 안 되면 댓글 ㄱㄱㄱ**

0

안녕하세요, 인프런 AI 인턴입니다. tjrwn0716님께서 질문하신 Spring Batch와 관련된 트랜잭션 매니저 및 데이터 소스 분리에 대해 설명드리겠습니다.

문제 요약

멀티모듈 프로젝트에서 API 모듈과 배치 모듈을 분리하여 사용하고 있으며, 배치 처리를 할 때 API 모듈의 데이터베이스에 영향을 주고 싶지 않다는 상황입니다. 각 모듈에 대해 별도의 데이터 소스와 트랜잭션 매니저를 관리하고 싶다고 하셨습니다.

적용 방안

  1. @BatchDataSource와 @Primary 데이터 소스 분리:

    • @BatchDataSource: 배치 관련 메타데이터를 저장하는 별도의 데이터 소스를 설정합니다. 이를 통해 배치의 상태 관리, 이력 등이 이 데이터 소스를 통해 관리될 수 있습니다.
    • @Primary: 비즈니스 로직을 수행하는 주 데이터 소스입니다. 일반적인 API 처리에서 사용하는 데이터 소스를 지정합니다.
  2. Reader, Processor, Writer의 데이터 소스 설정:

    • 기본적으로 API 모듈의 비즈니스 로직 데이터 소스를 활용하여 비즈니스 데이터를 가져오고 처리합니다.
    • 배치 작업에서 비즈니스 데이터를 읽어올 때 API와 동일한 원본 데이터 소스를 사용하지만, 별도의 커넥션 풀을 사용할 수 있도록 설정하여 각 프로세스가 서로에게 영향을 주지 않도록 관리할 수 있습니다.
  3. 트랜잭션 매니저 설정:

    • @BatchTransactionManager: 배치 메타데이터 저장소의 트랜잭션을 처리합니다. 일반적으로 JdbcTransactionManager를 사용할 수 있습니다.
    • JpaTransactionManager를 사용하고자 할 경우: 추가로 별도의 EntityManagerFactory를 설정하여 배치와 분리된 비즈니스 데이터 트랜잭션을 관리할 수 있습니다.
  4. 다중 데이터 소스와 트랜잭션 매니저 설정 예시:

    • application.yml을 활용하여 다중 데이터 소스 설정:

      spring:
      datasource:
       primary:
         url: jdbc:mysql://localhost:3306/business_db
         username: user
         password: pass
       batch:
         url: jdbc:mysql://localhost:3306/batch_meta_db
         username: batch_user
         password: batch_pass
      
    • Configuration 클래스 내 Bean 설정:

      @Configuration
      public class DataSourceConfig {
       @Primary
       @Bean(name = "primaryDataSource")
       @ConfigurationProperties(prefix = "spring.datasource.primary")
       public DataSource primaryDataSource() {
           return DataSourceBuilder.create().build();
       }
      
      
       @Bean(name = "batchDataSource")
       @ConfigurationProperties(prefix = "spring.datasource.batch")
       public DataSource batchDataSource() {
           return DataSourceBuilder.create().build();
       }
      
      
       @Primary
       @Bean
       public PlatformTransactionManager transactionManager(
               @Qualifier("primaryDataSource") DataSource dataSource) {
           return new JpaTransactionManager(entityManagerFactory().getObject());
       }
      
      
       @Bean
       public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
           LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
           em.setDataSource(primaryDataSource());
           // 설정 추가
           return em;
       }
      }
      
  5. 세부 설정 조정:

    • 배치 모듈에서 사용하는 데이터 소스와 트랜잭션 매니저는 API 모듈과 독립적으로 설정할 수 있습니다. 이는 배치 작업이 API 작업에 영향을 주지 않도록 하여 시스템의 안정성을 높입니다.

이와 관련된 유사 질문에 대한 답변을 첨부해 드립니다:
- Spring Boot 멀티모듈에서 데이터베이스 분리 적용하기

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드립니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

tjrwn0716님의 프로필 이미지
tjrwn0716

작성한 질문수

질문하기