본문 바로가기
Spring

[Spring Boot/JPA] JPA와 MongoDB 병행 시 @Transactional 설정 주의점 (멀티 트랜잭션 매니저)

by noddu 2026. 1. 9.
728x90
반응형
문제

프로젝트에서 MySQL(JPA)과 MongoDB를 함께 사용하는데

MongoDB를 사용한 테스트 중 테스트는 잘 되지만 롤백이 안되는 현상을 겪었다

 

@Configuration
public class MongoConfig {
    @Bean
    MongoTransactionManager mongoTransactionManager(MongoDatabaseFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }
}

그래서 찾아보니 MongoDB의 롤백을 위해 MongoTransactionManager를 빈으로 등록해서

MongoDB도 트랜잭션을 사용하니 테스트시 롤백이 잘 되었다

그런데, 이번엔 잘 돌아가던 JPA 기반의 회원 테스트들이 줄줄이 실패하는 현상이 발생했다

 

728x90

 

원인: 트랜잭션 매니저의 중복

Spring은 @Transactional 어노테이션을 만나면 빈 컨테이너에서 PlatformTransactionManager 타입의 빈을 찾는다

  • JPA만 쓸 때: 스프링 부트가 JpaTransactionManager를 자동으로 등록하고 이를 기본으로 사용
  • MongoDB 매니저 추가 후: 컨테이너에 JpaTransactionManager와 MongoTransactionManager 두 개가 공존하게 됨

이때 별도의 설정을 하지 않으면 스프링은 어떤 매니저를 기본으로 써야 할지 몰라 엉뚱한 매니저를 선택하거나 에러를 발생시킨다

JPA 로직에 MongoDB용 매니저가 투입되면 당연히 MySQL 롤백은 실패

 

반응형

 

해결 방법: 명확한 이름 부여와 @Primary 설정

어떤 녀석이 기본인지 정해주고, 특수한 상황(MongoDB)에서만 이름을 불러주는 것

1. TransactionConfig 설정

@Configuration
public class TransactionConfig {

    // JPA 트랜잭션 매니저를 '기본'으로 설정
    @Primary
    @Bean(name = "transactionManager")
    public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    // MongoDB용 트랜잭션 매니저는 별도의 이름을 부여
    @Bean(name = "mongoTransactionManager")
    public MongoTransactionManager mongoTransactionManager(MongoDatabaseFactory dbFactory) {
        return new MongoTransactionManager(dbFactory);
    }
}

MongoTransactionManager에 이름을 부여하고, 기존 JPA 매니저를 @Primary로 설정

 

2. 서비스 코드에서 구분해서 사용

이제 @Transactional만 쓰면 JPA 매니저가 작동하고, 몽고디비용은 이름을 명시

  • JPA 서비스 (회원 가입 등):
    @Transactional // @Primary인 jpaTransactionManager가 자동으로 선택됨
    public void registerMember() { ... }
    

     

  • MongoDB 서비스 (로그, 프롬프트 저장 등):
    @Transactional(value = "mongoTransactionManager") // 명시적으로 지정
    public void savePrompt() { ... }
    

     

3. 테스트 코드 작성 시 주의사항

// 1. JPA 테스트 (MySQL 롤백 필요 시)
@SpringBootTest
@Transactional 
class MemberServiceTest { ... }

// 2. MongoDB 테스트 (Atlas 롤백 확인 시)
@SpringBootTest
@Transactional("mongoTransactionManager")
class PromptServiceTest { ... }

 

테스트 환경에서도 적용

 

참고: MongoDB 트랜잭션을 테스트하려면 사용 중인 MongoDB가 반드시 Replica Set(복제셋) 모드로 돌아가고 있어야 합니다. (MongoDB Atlas는 기본적으로 복제셋입니다.)

 

 

반응형