기록하며 성장한다 - 개발, 회고

개발 회고록

[ 개발 회고록 ] 테스트 코드 작성 시, @Transactional 어노테이션을 사용하는 것에 대한 짧은 생각

전대홍 2024. 1. 10. 21:13

 

 

현재 필자가 진행하고 있는 배달 토이프로젝트가 있다. ( 프로젝트 링크 << )

해당 프로젝트를 개발 하는 도중, 테스트 코드에 @Transactional 을 쓰면서 직접 DB에 데이터가 담기는 지까지 테스트를 하는 것이 맞을까 라는 생각이 들었다.

그래서 @Transactional 을 테스트 코드에 써도 되는지 공부를 해보았고, 공부한 글과 함께 내 생각을 간단히 포스팅 해보려고 한다.

오늘은 짧은 글이다.

 

 


1. Transactional 어노테이션을 테스트 코드에서 사용하면 안될까?

결론부터 이야기하면, 사용하면 안되는건 아니다.

위 코드는 Spring Data Jpa 팀의 테스트 코드이다. ( 깃허브에서 확인하였다. )

보면 @Transactional 어노테이션을 통해 테스트로 들어온 데이터를 RollBack 시킨다.

즉, 쓴다고 해서 잘못 된 방식은 아니라는 것이다.

그러나 이렇게 Transactional 을 사용했을 경우 생길 수 있는 문제점을 잘 알고 있는 것은 중요하다.

그래서 테스트 도중에 생긴 다른 문제에 대응할 수 있기 때문이다.

 

 

2. 어떤 문제가 있을 수 있을까?

2.1. 우선 테스트 도중에, Transactional 로 인한 오류를 체크할 수 없다.

예를 들어, 실제 Service 로직에는 실수로 @Transactional 어노테이션을 붙이지 않았지만, 테스트 코드에만 @Transactional 이 붙어있는 상태로 테스트를 진행한다고 가정해보자.

Transactional 전파 레벨 덕분에, 문제 없이 테스트를 통과 하였을 것이다.

그러나, 실제 서비스를 운영하는 런타임 시에 예기치 못한 오류가 발생하였고, 롤백이 되지 않는 문제가 발생 할 수 있다.

 

2.2. 두 번째는 전파 속성으로 인한 테스트 롤백 실패가 있을 수 있다.

Transactional 전파 레벨 중에는 프로퍼게이션이 Requires_New 인 것이 있다.

내가 테스트하고자 하는 로직이 Requires_New 전파 레벨이어서, 별개의 물리적 트랜잭션을 형성하게 된다면, 테스트 코드에서는 롤백을 시도하지만, 실제 서비스의 메서드로 인해 발생한 내용은 롤백이 되지 않을 수 있다.

 

2.3. 비동기로 메서드 테스트 시 롤백이 되지 않을 수 있다.

2번과 비슷하게 테스트가 끝나고 초기화 되지 않은 데이터로 인해, 다른 테스트가 영향을 받아 테스트에 예기치 못한 문제가 발생할 수 있다.

 

* 참고로 이러한 전파레벨로 인한 트랜잭션 문제 점이 발생하는 이유는 트랜잭션이 프록시 객체로 실행되기 때문인데, 이에 대해서는 필자의 TIL 블로그에 잘 정리해두었다.

클릭 ==>>> 필자 TIL 블로그 ( 트랜잭션 )

 


3. 결론

 

@Tranasactional 어노테이션을 테스트 코드에서 무조건 쓰지 말라는 것이 아니다.

필요한 부분에서는 충분히 사용할 수 있다.

그러나, 위와 같은 문제점이 발생할 수 있다는 것을 알아야 테스트에서 발생하는 여러 문제들을 사전에 막을 수 있고, 발생하여도 대처할 수 있다.

그래서 특히, @Transactional 이 붙은 실제 서비스 메서드를 테스트 할 때는 더욱 주의해야 한다.

마지막으로 적어도 팀 내에서는 @Transactional 을 테스트 코드에서 사용할 지 말지를 통일 하는 것이 좋다고 생각한다.

@Transactional 을 사용하지 않을 거라면, 명시적으로 데이터를 초기화 하는 메서드를 선언하여 @BeforeEach 나 @AfterEach 를 활용하여 초기화를 해주면 좋다.

* 참고로 같은 이유로 @DataJpaTest 어노테이션도 조심하여야 한다. 해당 어노테이션은 내부적으로 @Transactional 어노테이션을 포함하고 있기 때문이다.