해결된 질문
작성
·
162
·
수정됨
1
보통 실무에서는
controller ->service(interface) -> repository -> dao
^
|
serviceImpl (service Interface 구현체)
이렇게 많이 사용합니다.
제가 개발자로 실무를 하지 않아서 정확하지는 않지만
@Configuratiain 을 이용한 클래스에서 구성을 잡고 포인트컷으로 지정된 패키지와 그 하위 *Impl 메서드에 모든 @Transaction 어노테이션이 적용되도록 설정을 했던 것 같습니다.
그리고 serviceImpl에서 @Transactional 어노테이션을 사용하지 말라고 가이드가 내려 옵니다.
코딩은
public class serviceImpl {
public int createMember(MemberVO member) {
deleteMember(member);
insertMember(member);
updateMember(member);
}
public int deleteMember(MemberVO member) {
//비지니스 로직 수행
String id = member.getId(); //null 체크 되어 있다고 가정
repository.delete(id);
}
public int insertMember(MemberVO member) {
//비지니스 로직 수행
repository.insert(member);
}
public int updateMember(MemberVO member) {
//비지니스 로직 수행
repository.update(member);
}
}
그런데 한번도 아키텍처나 업무 공통 단에서 내부 호출에 대한 가이드가 없었습니다.
그리고 실제로 내부 호출을 해도 Transaction 처리에 문제가 있지는 않았습니다.
그렇다고 AspectJ 의 컴파일러를 이용하는 것 같지도 않고
ObjectProvider를 사용하는 것 같지도 않는데 말입니다.
고급편에서도 궁금했지만 DB2편을 다 수강하고 나서 질문을 드립니다
아키텍처 쪽에서 내부 호출에 대한 문제를 모르진 않았을것 같은데
통상적으로 어떻게 @Transactional 처리를 하기에 개발자들은 내부 호출 문제에 신경 쓰지 않을까요?
답변 2
1
안녕하세요. gaabi1204님
@Transaction을 클래스 레벨에 걸거나, 또는 말씀하신 것 처럼 걸게되면 외부에서 서비스를 호출하는 시점에 바로 트랜잭션이 걸리게 됩니다.
따라서 외부 클래스에서 createMember를 호출할 때도 트랜잭션이 걸리고, 따라서 외부 클래스에서 deleteMember를 호출할 때도 트랜잭션이 걸리게 됩니다.
예를 들어서 createMember를 호출하고 그 안에서 내부 메서드를 호출해도 createMember에서 이미 트랜잭션이 걸렸기 때문에 문제가 되지 않습니다.
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다.
gaabi1204님, 프록시 내부 호출 문제와 관련해 질문해주셨네요. 먼저, 스프링의 @Transactional
어노테이션이 제대로 작동하려면 스프링이 해당 클래스의 프록시(Proxy)를 생성하여 관리해야 합니다. 이 때문에 @Transactional
어노테이션을 클래스 내부 메서드에서 직접 호출(내부 호출)하는 경우, 스프링 프록시를 거치지 않고 직접 메서드를 호출하기 때문에 트랜잭션 처리가 정상적으로 이루어지지 않을 수 있습니다.
이러한 내부 호출 문제를 해결하기 위한 방법 중 하나는, 자기 자신의 빈(Bean)을 주입받아 사용하는 것입니다. 스프링에서는 ApplicationContext
를 활용하거나, @Lazy
와 함께 자기 자신을 주입받아 이 문제를 해결할 수 있습니다. 예를 들어, @Autowired
와 @Lazy
를 이용하여 자기 자신의 빈을 주입받는 것을 통해 메서드 호출 시 스프링 컨테이너를 통해 프록시 객체를 경유하도록 할 수 있습니다.
또 다른 방법으로는 비즈니스 로직을 분리하여 별도의 클래스에 위치시키고, 이 클래스를 통해 트랜잭션을 관리하는 방법도 있습니다. 즉, 내부에서 직접 호출하는 것이 아니라 외부에서 호출할 수 있도록 구조를 변경하여, 스프링 프록시를 통해 @Transactional
이 적용된 메서드를 호출하도록 하는 것입니다.
이와 같은 문제는 실무에서도 종종 발생할 수 있는 문제로, 개발자들은 이런 상황을 인지하고 적절한 방법을 선택하여 문제를 해결해야 합니다. 구체적인 구현 방법은 프로젝트의 구조나 개발 팀의 선호도에 따라 달라질 수 있습니다.
이 내용은 깊은 이해를 필요로 하며, 프로젝트의 구체적인 상황에 따라 최적의 방법이 달라지기 때문에 팀 내에서 충분한 논의가 필요할 수 있습니다.
안녕하세요. gaabi1204님
이 경우 mainMethod()를 호출하는 순간에 이미 트랜잭션이 적용됩니다 🙂
트랜잭션의 범위가 mainMethod()를 호출하는 순간부터 mainMethod()가 끝나서 반환 할 때 까지 적용됩니다.
따라서 mainMethod()가 호출하는 deleteMethod() 메서드 내부에서는 이미 트랜잭션이 적용된 상태로 호출되기 때문에 deleteMethod()도 같은 트랜잭션의 범위 안에 포함이 됩니다.
감사합니다.