@Transactional private 사용유무
156
작성한 질문수 5
proxy 패턴으로 애플리케이션 서비스에서 반복적인 트랜잭션 처리 적용까지는 이해했습니다.
여기서 만약 애플리케이션 서비스 내부에서 private 로 두개의 트랜잭션은 어떻게 적용해야할까요?
아래는 제가 생각한 흐름입니다.
가령 현재 강의에서는 OrderService 내부에서 주문 정보만 생성하고 있는데 주문 후 결제까지 이뤄진다면?
public class OrderServiceImpl implements OrderService {
private final OrderRepository orderRepository;
private final PaymentRepository paymentRepository;
public OrderServiceImpl(
OrderRepository orderRepository,
PaymentRepository paymentRepository
) {
this.orderRepository = orderRepository;
this.paymentRepository = paymentRepository;
}
@Override
public Order createOrder(Order order) {
// 주문 도메인 생성
// 결제 도메인 생성
}
@Transactional
private void save(Order order, Payment payment) {
// 주문 및 결제 정보 저장
}
}제가 찾아보기로는 @Transactional 경우 Proxy 패턴으로 스프링에서 begin, rollback, commit 을 자동으로 수행해주는데 이를 private 으로 선언 한 경우 스프링에 private 메소드에 접근을 못해서 정상 동작을 안하는걸로 알고 있습니다.
(강의를 듣고서) 제가 추측하기로는 TransactionTemplate 으로 프록시 패턴으로 적용한경우 private 메소드에는 접근을 못하니깐 애노테이션 또한 정상동작을 안하는것으로 생각됩니다.
(제 추측이 틀렸다면 자세한 설명 부탁드립니다.)
그러면 애플리케이션 서비스는 기술 의존적으로 바뀌게 될텐데 private 함수에서 애노테이션이 아닌 TransactionTemplate 을 써야되나?
강의 듣고서는 이정도밖에 생각이 안드는데 어떤식으로 접근하고 private 에서도 트랜잭션을 적용하기위한 원리는 어떤게있는지 답변 주시면 감사하겠습니다!
답변 1
0
말씀하신 대로 private 메소드에는 스프링의 프록시 기반 AOP를 적용할 수 없습니다. 기본적으로 인터페이스 구현 또는 상속을 통한 오버라이딩 기법을 써서 프록시 역할을 하는 코드를 최종 클래스의 메소드를 실행하기 전후에 넣어야 하는데, 그런 코드가 나올 수가 없기 때문이죠.
그러면 TransactionTemplate을 써서 트랜잭션을 만드는 방법 뿐인가라고 생각할 수도 있겠네요.
하지만 좀 더 근본적으로 생각해볼 필요가 있겠네요.
모든 클래스의 private 메소드는 결국 어떤 public 또는 그에 준하는 접근이 가능한 메소드를 타고 실행이 됩니다. 그런다고 하면 트랜잭션의 경계를 굳이 특정 private으로 제한할 필요는 없을 겁니다. 보통 public으로 외부에 공개한 메소드가 결국 이 오브젝트가 제공하는 중요한 기능일테고, 트랜잭션은 그런 기능 단위로 시작하고 종료하는 게 자연스럽습니다. private 메소드는 시간이 지나면서 자주 바뀌거나 변경됩니다. 내부의 디테일한 구현은 리팩터링이나 여러 다른 이유로 변경을 해도 오브젝트를 사용하는 쪽에 영향을 주지 않기 때문에 변경에서 자유롭습니다. 그런데 그 메소드에 트랜잭션을 선언한다는 것은 매우 불안정한 코드와 트랜잭션 기능 적용이 되겠죠.
모든 DB 기능이 사용되는 메소드에서 다시 트랜잭션을 시작할 필요는 없습니다. 진입점에 해당하는 public 메소드에서 트랜잭션을 시작해두면 이후에 호출되는 모든 메소드, 심지어 다른 빈의 메소드까지 트랜잭션에 포함됩니다.
따라서 private 메소드에 트랜잭션을 지정하는 것은 결코 좋은 설계가 아닙니다. 아주 복잡한 AOP 기술을 쓰면 불가능한 것도 아니지만, 그럴만큼 필요할리가 없을 듯하네요. 트랜잭션을 시작해두는 것 때문에 특별히 성능에 영향이 있거나 하지 않습니다. 그래서 public 메소드나 인터페이스의 공개된 메소드에 트랜잭션을 지정하는 것이 좋습니다.
위의 코드라면 createOrder() 메소드에 트랜잭션 설정을 적용하세요.
수업을 잘 듣고 있습니다.
0
103
2
jackson(3.0.2 버전) ObjectMapper.readValue 에러타입
0
108
2
템플릿과 콜백의 역할 경계를 구분하는 기준
0
99
1
테스트를 작성하지않아도 되는 경우
0
86
2
오브젝트 정의 중 배열에 대해서
0
63
2
스프링 레거시를 이용하는 회사에서 일을 하게 될것같은데
0
109
2
JpaTransactionManager에 대해 궁금합니다.
0
81
2
스프링빈과 Clock 클래스 관련
0
44
2
Seprate Interface 패턴에 대한 궁금증
0
46
2
테스트의 기준을 어떤식으로 설정하는 것이 바람직한 테스트일까요 ?
0
51
2
오브젝트와 인스턴스
0
38
1
WebApiExRateProvider 템플릿 콜백 패턴을 적용하면서 테스트 코드를 만들어보았습니다.
0
62
2
템플릿 콜백 패턴 관련하여 궁금한 것이 있습니다!
0
59
2
상태 변경 API 질문
0
120
2
빈에 대한 질문
0
97
1
안녕하세요.
0
145
2
Payment 엔티티에 exRateProvider 주입
0
101
1
JdbcClient 생성 질문
0
190
2
안녕하세요 PaymentConfig 질문드립니다.
0
110
2
[공유] 윈도우 사용자를 위한 http 명령어 오류 해결 방법
0
244
2
생성자 파라미터성자 파라미터
0
237
2
토비님 ! BigDecimal 관련 링크를 못찾겠어요
2
342
2
인터페이스 사용에 관하여 질문드립니다.
0
307
3
Order에서 JPA 메타데이터 분리 - XML 사용
0
257
2





