작성
·
8
1
에 대해서 이해가 잘 가지 않는게 있어.
실제 운영 환경에서는 배치와 비즈니스 데이터 DB를 분리하는게 필수라고 했잖아?
근데 이 분리의 단위가 배치용 메타데이터 저장만 분리를 하는게 맞는거야?
현재 사이드 프로젝트에서 멀티모듈 구조에 (MSA는 아님) API 모듈과 배치 모듈을 따로 분리한 상태야.
유저 데이터에서 생일을 뽑아서 내일 생일인 유저에게 FCM 을 발송하는 배치를 만드는데,
이때 만들어준 예제처럼 @BatchDataSource와 비즈니스 로직용 @Primary DataSource를 분리하게 되면,
API 모듈용 DB Connnection을 배치에서도 똑같이 갖다 쓰는거 아니야 ??
즉, 배치에서 API 쪽 커넥션을 가져다 써서 배치가 돌 때 커넥션이 고갈날 수 있지 않을까? 라는 생각이 들었어
지금 이해한 바로는 @BatchDataSource, @BatchTransactionManager를 분리하고 주입해줘도
Reader -> Processor -> Writer 에는 @Primary 걸 쓰는것 같은데 맞아 ?
나는 DB 분리와 함께, 비즈니스 로직에 대한 커넥션, 트랜잭션도 배치용으로 분리하고 싶은데 이럴땐 어떻게 해야해?
특히나 배치에서도 JpaTransactionManager를 쓰고 싶은 경우에는 어떻게 해야해 ?
원하는 바는, API 처리용 DB 커넥션은 커넥션대로 있고, 배치 메타데이터용 커넥션 따로, 배치에서 라이브 DB에서 유저 데이터를 가져오는 커넥션 따로 구성하고 싶어 (배치가 API 모듈 에 영향을 주지 않았으면 해서,,,)
혹시 내가 강의를 제대로 이해를 못한거라면 알려줘
답변 2
1
**TransactionManager 분리**
또 보는구나 석주형.
내가 잘못 이해한 거일 수 있지만 (아마 내가 이해한 게 맞을 것이다)
형은 지금 실제 서비스하는 온라인 웹앱에서 배치도 같이 돌리는 시나리오를 가정하고 질문한 것으로 보인다. 맞나?
굳이 "멀티모듈 구조"라는 단어를 쓴 걸 보니, '같은 애플리케이션 안에서 모듈만 나눴다'는 소리로 들린다.
(내가 이해한 게 아니면 말해라)
---
## 배치와 온라인 앱은 별개 프로세스다
너무 당연하게 생각하고 설명을 안 한 건가 싶은데,
**일반적으로 사용자에게 서비스하는 온라인 앱과 배치 앱은 아예 별도의 프로세스로 돌아야 맞다.**
따라서 코드베이스도 달라야 일반적인 거지. 다른 프로젝트로 구성하는 게 일반적이라는 의미다.
너가 걱정하는 API 서버용 데이터소스 분리? 걱정 안 해도 된다.
**일반적인 배치 앱 구성의 올바른 설계가 이미 그걸 해결해주니까.**
---
## 이렇게 생각해보자
**시나리오 1: 배포 상황**
배치가 돌고 있는데 정기 배포든 긴급 배포든 온라인 서비스 배포를 한다고 하자.
배치 서버는 어떻게 해야 할까?
**시나리오 2: 리소스 경합**
배치 서버에서 수백만/수천만 데이터를 다룬다고 가정하자.
이 서버에서 온라인 트랜잭션을 다루는 게 맞을까? 사용자 요청 tps가 한 두 건도 아닐텐데말이다.
---
## 배치? 별도 프로세스
다시 말해, **배치 앱은 일반 사용자 대상 실시간 온라인 앱과는 별도의 프로젝트**라고 생각해야 한다.
아니, 실제로 보통 그렇게 설계해야 한다.
기존 사용자 요청을 받는 앱에 배치를 포함시키는 게 아니라,
**별도의 프로세스(별도 서버에서)로 배치 앱을 돌려야 한다는 것이다.**
그래서 우리 강의의 거의 대부분의 예제가 커맨드라인으로 별도의 프로세스를 실행하도록 되어 있는 거다.
---
## 그럼 우리 강의의 "온라인 어플리케이션에서 배치 실행"은 뭐냐고?
일반적으로 온라인 어플리케이션에서 배치를 돌린다는 것은
**사용자 대상 서비스가 아닌 팀 내부 서비스 또는 어드민 툴** 등을 의미한다.
그럼 왜 "비즈니스 데이터"라고 했냐고?
**배치는 비즈니스를 위해 존재한다.**
보통 배치는 온라인 웹 서비스의 데이터 처리를 보완하기 위해 존재한다.
비록 다른 프로세스로 동작할 순 있지만, **바라보는 DB는 동일하다.**
(마스터를 보냐 슬레이브를 보냐에 차이는 있을 것이다)
---
## 💀 더 나아가: 데이터소스 분리는 무궁무진하다
데이터소스를 나누는 방법은 사실 **무궁무진하다.** 사실 이건 **구현하기 나름이다.**
너도 알겠지만, 실제 프로덕션 서비스에서는 (장난감이 아닌 한)
스프링 부트가 자동으로 구성해주는 단일 데이터소스만을 사용하는 것은 **말이 안 된다.**
따라서 별도의 데이터소스들을 직접 정의해주어야 하지.
**스프링 배치도 마찬가지다. 특별할 것 없다. 동일한 스프링 앱이다.**
여러 데이터소스가 필요하면 여러 개를 구성해주면 된다.
일반 스프링 웹앱에서 하던 방식 그대로 분리하면 된다.
강의의 `@Primary` 등의 사용은 **예시에 불과하다.**
주입받을 빈을 어떻게 구성하고 퀄리파잉할지 등의 방법은 **구성하기 나름이다.**
다 이미 알고 있는 내용일 거다. **(스프링 배치도 스프링이다)**
---
## 더 나아가: 샤딩 환경
대용량 트래픽을 다루는 서비스에서는 단순 DB 분리를 넘어
**DB당 (논리 데이터소스 그룹당) 샤드가 수십 개 이상 (또는 그 이상) 관리되기 마련이다.**
이런 경우 추가적인 DataSource 목록 관리 방법이 필요하다.
이 또한 별도의 구성이 필요하며, **배치에서는 웹앱에서 하는 방식 그대로 바라보면 된다. 스프링을 사용하는 조직에서 배치 프레임워크로 스프링 배치를 사용하는 이유이기도하다.**
**정해진 방법이 있는 게 아니다.**
---
## 마무리
내 설명이 다소 어렵다면 다시 댓글을 달아달라. 더 세세하게 이야기해보자.
현재 시간 4:24 AM.
일단 급히 대답 남기고 취침으로 들어간다.
**사소한 것도 이해 안 되면 댓글 ㄱㄱㄱ**
0
안녕하세요, 인프런 AI 인턴입니다. tjrwn0716님께서 질문하신 Spring Batch와 관련된 트랜잭션 매니저 및 데이터 소스 분리에 대해 설명드리겠습니다.
멀티모듈 프로젝트에서 API 모듈과 배치 모듈을 분리하여 사용하고 있으며, 배치 처리를 할 때 API 모듈의 데이터베이스에 영향을 주고 싶지 않다는 상황입니다. 각 모듈에 대해 별도의 데이터 소스와 트랜잭션 매니저를 관리하고 싶다고 하셨습니다.
@BatchDataSource와 @Primary 데이터 소스 분리:
Reader, Processor, Writer의 데이터 소스 설정:
트랜잭션 매니저 설정:
JdbcTransactionManager
를 사용할 수 있습니다.EntityManagerFactory
를 설정하여 배치와 분리된 비즈니스 데이터 트랜잭션을 관리할 수 있습니다.다중 데이터 소스와 트랜잭션 매니저 설정 예시:
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;
}
}
세부 설정 조정:
이와 관련된 유사 질문에 대한 답변을 첨부해 드립니다:
- Spring Boot 멀티모듈에서 데이터베이스 분리 적용하기
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드립니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.