이번 게시글에서는 동시성 문제를 테스트하기 위해 테스트 코드를 작성하던 중 발생했던 @Transactional 문제를 기록하려 한다.
테스트 코드다. @Transactional 이 붙어있고 리뷰를 저장하고 reviewService.deleteReview() 메서드를 호출해서 리뷰를 삭제하는 간단한 코드다.
reviewService.deleteReview() 내부 코드인데 (@Async 어노테이션을 주목하자) validateReview() 메서드를 호출해서 해당 리뷰가 존재하는 리뷰인지 확인한다.
그리고 validateReview() 내에서는 리포지토리를 통해 실제 DB(or 1차 캐시) 에 접근한다.
테스트 코드를 실행해보면 위와 같은 오류가 발생하게 된다. 리포지토리를 통해 리뷰를 조회했는데 찾을 수 없다는 오류다. 이거 때문에 몇 시간을 삽질한건지 모르겠다.
일단 일반적인 로직대로라면 @Transactional 어노테이션이 붙어있기 때문에 리뷰를 저장하는 로직 부분에서 영속성 컨텍스트의 1차 캐시에 내용을 저장하게 된다. 그리고 validateReview() 부분에서 영속성 컨텍스트를 통해서 1차 캐시의 값을 조회하게 될텐데, 호출하는 메서드의 @Async 가 붙은 경우는 이렇게 동작하지 않는다.
왜냐하면 @Async 어노테이션이 붙은 메서드를 호출하게되면 새로운 쓰레드를 만들고 이를 비동기로 처리하기 때문이다. 그리고 새로 만들어진 쓰레드는 당연히 트랜잭션 전파가 되지 않는다.테스트 코드의 @Transactional 이 붙어있기 때문에 실제 DB 에는 값이 반영되지 않았을테고 이는 당연히 오류로 이어질 수 밖에 없었던 것이다.
참고 자료
'기타 > 문제 해결' 카테고리의 다른 글
QueryDSL 과 Spring Cloud 의존성 충돌 문제 (0) | 2024.06.13 |
---|---|
스프링 SQL 초기 데이터 삽입 시 나타나는 문제 (1) | 2024.06.07 |
자바 Jackson 라이브러리 LocalDateTime 직렬화 문제 (0) | 2024.06.01 |
낙관적 락을 사용해 동시성 문제 해결 (0) | 2024.05.31 |
nGrinder 테스트 되지 않는 문제 해결 (Connection is not completed or cached files digest weren't received until 10 sec) (0) | 2024.05.22 |