작성
·
289
·
수정됨
0
안녕하세요 강사님
좋은 강의 감사드립니다.
참여했던 실무 프로젝트에서 @Transactional 을 잘 이해하지 못한 채 사용했던 적이 있습니다.
특정 서비스의 한 메소드에서 @Transactional을 선언하고 해당 메소드가 여러 작업을 하기 때문에 다른 메소드를 호출하는 방식이었습니다.
이때 저는 트랜잭션의 특징을 잘 몰라서 두 메소드에 다 @Transactional을 선언했었습니다.
예시)
@Transactional
public void ex1() {
...
// 로직 수행 후 다른 메소드 호출
ex2();
}
@Transactional
public void ex2() {
// 로직 수행
}
테스트를 하는데 로직 수행중 ex1에서 에러가 나든 ex2에서 에러가 나든 트랜잭션 롤백이 안됐었는데 이런 케이스는 무엇이 원인인지 알려주실 수 있나요?
강의에서처럼 ex1이 아예 @Transactional이 선언되어 있지 않았다면 롤백이 안되는게 맞다고 생각이 드는데 저는 두 메소드 다 선언했었거든요,,
확인해주시고 답변 주시면 정말 감사드리겠습니다ㅠ
(혹시나 해서 강의 코드의 externalCall 메소드에 트랜잭션 선언해보고 테스트 돌려봤는데 트랜잭션 적용 되더라고요)
+추가 질문으로 이런 경우에는 ex1 메소드에만 @Transactional을 선언하면 될까요?
답변 2
1
안녕하세요. chaelynjang님
동작하는 코드가 있어야 정확한 상황을 파악할 수 있겠지만 이런 경우는 트랜잭션 AOP 자체가 동작하지 않는 경우들이 있습니다. 지금은 스프링 부트가 트랜잭션 AOP들을 자동으로 등록해주지만 과거에는 직접 이런 부분을 다 관리했는데, 해당 코드가 잘 반영되어 있지 않다면 트랜잭션 자체가 걸리지 않습니다.
추가 질문: 네 ex1()에만 거시면 됩니다.
도움이 되셨길 바래요.
선생님. 저 프록시 내부호출의 문제점에 대해 좋은 예시를 발견한 것 같습니다.
결론적으로 말하자면, 그렇게 되게끔 프록시가 만들어 졌다는 겁니다.
무슨 말이냐 하면, @Test의 @BeforeEach를 예를 들어
@BeforeEach
public void before(){
log.info("before");
}
@Test
void check(){
proxyCheck();
proxyCheck();
}
@Test
void proxyCheck(){
log.info("aop class={}", basicService.getClass());
Assertions.assertThat(AopUtils.isAopProxy(basicService)).isTrue();
}
@BeforeEach는 각 @Test를 실행하면 꼭 한번 씩 실행이 되잖아요?
근데 check에서 @Test가 붙은 proxyCheck()를 두번이나 호출하여, @BeforeEach가 총 3번 호출되어야 하지만 1번만 호출 됩니다.
이런 것 처럼, 프록시도 "외부에서 처음 들어온 메소드 호출에서 한번만" 으로 동작되도록 설계가 된 것 같습니다.
좀 다르긴 할 것 같습니다.
물어보니까 @Test는 프록시가 아니라고 하고, @Test의 기능은 클래스 전체를 실행했을 때 @Test인 것을 실행토록 하는 거니..
좀 다르지만, 좋은 예시 같습니다.
1
안녕하세요, 인프런 AI 인턴입니다.
처음에 ex1 메소드에만 @Transactional을 선언하셨을 때 롤백이 되지 않았다는 것은 롤백이 필요한 상황이 발생하지 않았거나 롤백이 제대로 처리되지 않은 것일 수 있습니다. 두 메소드 중 하나에서 예외가 발생하면 트랜잭션은 롤백되어야 합니다. 다만, 예외가 발생하지 않는 경우에는 롤백이 되지 않습니다.
이 경우가 왜 발생했는지 정확한 원인 파악은 어려우나, @Transactional 어노테이션을 두 메소드에 모두 선언했다는 것은 두 메소드가 독립적으로 트랜잭션을 처리한다는 것을 의미합니다. 따라서 ex1에서 예외가 발생한다고 해도 ex2는 이미 별도의 트랜잭션으로 처리가 완료되어 롤백되지 않은 것입니다.
해결책으로는 ex2 메소드에서는 @Transactional 어노테이션을 제거하고, ex1 메소드에서만 @Transactional 어노테이션을 유지하는 것이 좋습니다. 이렇게 하면 ex1에서 예외가 발생하면 전체 메소드 수행이 롤백되므로 문제가 발생할 가능성이 줄어듭니다.
답변이 도움이 되셨길 바랍니다. 감사합니다.
감사합니다 강사님
저도 코드가 정확하게 잘 기억나지는 않지만
강의에서 말씀하신 것처럼 두 메소드 중 하나가 public 메소드가 아니었거나 체크예외가 발생해서 커밋되었을 수도 있었던 것 같아요
나머지 강의를 계속 듣다보면 트랜잭션이 제대로 롤백되지 않은 여러 이유를 찾을 수 있을 것 같습니다 :-)
항상 좋은 강의 감사드려요 정말 많이 배우고 있습니다.
감사합니다.