일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- +9:00
- apatch poi
- mysql not equal null
- Protecle
- 운동해서 광명찾자
- pooled-lo
- https
- @CreateDate
- 1*1000
- MYSQL
- sendFractionalSeconds
- 오블완
- NamedEntityGraph
- @EntityListeners
- mysql =
- spring boot
- createEntityGraph
- MSSQL
- getDateCellValue
- getEntityGraph
- 티스토리챌린지
- EmbeddedId
- 버전 문자열 비교
- yml
- mysql equal null
- RootGraph
- deserializer
- load order
- fractional seconds
- AuditingEntityListener
- Today
- Total
Hello
Spring에서 트랜잭션을 관리하는 세 가지 방법 본문
비즈니스 코드를 작성하다 보면 다른 트랜잭션의 메소드를 호출해야 할 때가 있습니다. 이 글에서는 Spring에서 트랜잭션을 관리하는 세 가지 방법을 비교하고, 각 방법의 장단점을 설명합니다. 상황에 맞는 최적의 트랜잭션 관리 방법을 선택할 수 있습니다.
1. Self-Injection
Spring Bean이 자신을 의존성으로 주입받아 사용하는 방식입니다. 사용 방법이 간단하며, 메소드 간의 트랜잭션 경계를 명확하게 나눌 수 있습니다.
장점
- 단순성: 코드가 비교적 단순하고 이해하기 쉽습니다.
- 명확한 트랜잭션 경계: 메소드 간의 트랜잭션 경계를 명확하게 정의할 수 있습니다.
- 간단한 설정: 설정이 비교적 간단하여 빠르게 적용할 수 있습니다.
- 유연성: 특정 메소드에만 트랜잭션을 적용할 수 있어 유연하게 트랜잭션을 관리할 수 있습니다.
단점
- 순환 의존성: 잘못 사용하면 순환 의존성 문제가 발생할 수 있습니다.
- 테스트 어려움: self-injection을 사용하는 코드는 테스트하기 어려울 수 있습니다.
- 유지보수: 코드가 복잡해지면 유지보수가 어려울 수 있습니다.
- 의존성 주입: 자기 참조를 주입받아야 하므로, 의존성 주입 설정이 필요합니다.
@Service
public class SomeService {
private SomeService self;
@Autowired
public void setSelf(SomeService self) {
this.self = self;
}
// 트랜잭션이 없는 비즈니스 로직
public void someFacadeBusiness() {
self.txMethodA(); // 트랜잭션A 메소드 호출
}
// 트랜잭션B가 적용된 비즈니스 로직 에서 트랜잭션A가 메소드 호출
@Transactional("transactionManagerB")
public void txMethodB() {
//트랜잭션 B를 사용하는 로직
//...
self.txMethodA(); // 트랜잭션A 메소드 호출
}
@Transactional("transactionManagerA")
public void txMethodA() {
// 트랜잭션A가 적용된 비즈니스 로직
}
}
2. 서비스 클래스를 두 개로 분리
말 그대로 서비스를 분리해 트랜잭션을 각각 관리할 수 있도록 합니다. 각 서비스의 역활이 명확해지며 코드가 모듈화 되어 유지보수 및 테스트 편의성이 용이합니다.
장점
- 역할 분리: 각 서비스 클래스가 명확한 역할을 가지며, 서로 다른 트랜잭션을 관리할 수 있습니다.
- 모듈화: 코드가 모듈화되어 유지보수와 테스트가 용이합니다.
- 가독성: 코드의 가독성이 향상되어 이해하기 쉽습니다.
- 테스트 용이성: 각 클래스가 독립적으로 동작하므로 단위 테스트가 용이합니다.
- 순환 의존성 해결: 순환 의존성 문제를 피할 수 있습니다.
단점
- 복잡성 증가: 클래스가 많아지면 관리가 복잡해질 수 있습니다.
- 의존성 관리: 클래스 간의 의존성을 잘 관리해야 합니다.
- 코드 분리: 코드가 여러 클래스에 분리되어 있어, 전체 흐름을 파악하기 어려울 수 있습니다.
- 설정 필요: 각 클래스에 대한 별도의 트랜잭션 설정이 필요할 수 있습니다.
@Service
public class ServiceA {
@Autowired
public ServiceB serviceB;
@Transactional("transactionManagerA")
public void someFacadeBusiness() {
// 트랜잭션 A가 적용된 비즈니스 로직
serviceB.txMethod();// ServiceB의 메소드 호출
}
@Transactional("transactionManagerA")
public void txMethod() {
// 트랜잭션 A가 적용된 비즈니스 로직
}
}
@Service
public class ServiceB {
@Transactional("transactionManagerB")
public void txMethod() {
// 트랜잭션 B가 적용된 비즈니스 로직
}
}
@Service
public class BusinessService {
@Autowired
private ServiceA serviceA;
@Autowired
private final ServiceB serviceB;
public void executeBusinessLogic1() {
serviceA.someFacadeBusiness();
}
public void executeBusinessLogic2() {
serviceA.txMethod();
serviceB.txMethod();
}
}
3. ChainedTransactionManager [ deprecated ]
여러 트랜잭션 매니저를 체인으로 연결하여 복잡한 트랜잭션 시나리오를 처리할 수 있게 합니다. 아래 예시는 2개의 트랜잭션만 연결했지만 n개의 트랜잭션을 연결할 수 있습니다.
ChainedTransactionManager는 Spring Data Core 2.5 버전부터 deprecated되었습니다. 이 클래스는 여러 트랜잭션 매니저를 체인으로 연결하여 트랜잭션을 관리하는 기능을 제공했지만, 일관된 트랜잭션 처리를 보장하기 어렵다는 이유로 더 이상 권장되지 않습니다.
장점
- 다중 트랜잭션 매니저: 여러 트랜잭션 매니저를 체인으로 연결하여 사용합니다.
- 중앙 집중식 관리: 트랜잭션 매니저를 중앙에서 관리하여 트랜잭션 경계를 명확하게 정의할 수 있습니다.
- 복잡한 트랜잭션 시나리오: 복잡한 트랜잭션 시나리오를 처리할 때 유용합니다.
- 일관성: 여러 데이터 소스에 걸쳐 일관된 트랜잭션 처리가 가능합니다.
- 확장성: 새로운 트랜잭션 매니저를 쉽게 추가할 수 있습니다.
단점
- 설정 복잡성: 설정이 복잡할 수 있으며, 잘못된 설정으로 인해 예상치 못한 동작이 발생할 수 있습니다.
- 유지보수 어려움: 여러 트랜잭션 매니저를 관리해야 하므로 유지보수가 어려울 수 있습니다.
- 성능: 여러 트랜잭션 매니저를 사용하면 성능에 영향을 미칠 수 있습니다.
- 의존성: 트랜잭션 매니저 간의 의존성을 잘 관리해야 합니다.
@Configuration
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManagerA(EntityManagerFactory entityManagerFactoryA) {
return new JpaTransactionManager(entityManagerFactoryA);
}
@Bean
public PlatformTransactionManager transactionManagerB(EntityManagerFactory entityManagerFactoryB) {
return new JpaTransactionManager(entityManagerFactoryB);
}
@Bean
public ChainedTransactionManager chainedTransactionManager(
PlatformTransactionManager transactionManagerA,
PlatformTransactionManager transactionManagerB) {
return new ChainedTransactionManager(transactionManagerA, transactionManagerB);
}
}
@Service
public class SomeService {
@Transactional("chainedTransactionManager")
public void someFacadeBusiness() {
// 트랜잭션 A와 B가 모두 적용된 비즈니스 로직 작성 또는 호출
txMethodA();
txMethodB();
}
@Transactional("transactionManagerA")
public void txMethodA() {
// 트랜잭션 A가 적용된 비즈니스 로직
}
@Transactional("transactionManagerB")
public void txMethodB() {
// 트랜잭션 B가 적용된 비즈니스 로직
}
}
Spring에서 트랜잭션을 관리하는 방법은 다양하며, 각 방법은 특정 상황에 맞는 장단점을 가지고 있습니다. Self-Injection은 코드가 단순하고 이해하기 쉬우며, 메소드 간의 트랜잭션 경계를 명확하게 정의할 수 있는 장점이 있습니다. 서비스 클래스를 분리하는 방법은 코드의 가독성과 유지보수성을 높이고, 테스트 용이성을 향상시키는 데 매우 유용합니다.
참고 : https://docs.spring.io/spring-framework/reference/data-access/transaction/motivation.html
Dependency Injection :: Spring Framework
'spring' 카테고리의 다른 글
[Spring HATEOAS] 프록시 서버 및 로드 밸런서 사용 시 http 링크 문제 (0) | 2024.06.17 |
---|---|
[Spring HATEOAS] 유저 정보 관리에 적용해본 내용 정리 (0) | 2024.05.13 |
[Spring] RequestParam Enum으로 매핑 (0) | 2024.04.18 |
[spring] 같은 bean에서 Propagation.REQUIRES_NEW 동작하지 않음 (0) | 2024.01.29 |
Spring Data JPA @Modifying (0) | 2023.12.18 |