Spring 응용프로그램 개발에 TDD를 적용하는 과정에서 테스트 실행 속도와 관련된 질문이 자주 제기된다. 특히, @SpringBootTest를 사용한 테스트의 실행 성능과 관련한 고민을 많이 듣는다. 이와 관련된 인프런 Spring Boot TDD 강의의 질문이 올라와서 응용프로그램 컨텍스트(Spring application context)를 사용하는 테스트의 실행 성능에 대한 경험으로 답변했고 이 글에서 한 번 더 정리한다.

우선 인프런 Spring Boot TDD 강의 실습은 120개 이상의 테스트가 모두 @SpringBootTest를 사용해 작성되었다. 그렇게 작성한 이유는 강의의 목적이 Spring Boot 앱을 TDD로 개발하는 기본 역량을 단단히 다지는 것이기 때문이다. 실습 마지막에 테스트 실행 성능을 개선하는데, 거의 모든 테스트가 HTTP 요청으로 동작하고 일부 테스트는 복잡하고 긴 시나리오에 기반함에도 테스트를 모두 실행하는데 걸리는 시간은 대략 6초 정도로 감소된다. 이 정도면 작업 흐름이 끊기는 일은 거의 없을 것이다.

여기서 @SpringBootTest를 사용하지만 테스트 실행 시간에 많은 시간이 소비되지 않는 가장 큰 이유는 테스트 수가 100개 이상이지만 만들어지는 응용프로그램 컨텍스트가 2개 밖에 되지 않기 때문이다. 강의 실습의 경우 응용프로그램 컨텍스트 하나가 준비되는 데 400~700 밀리초 정도 소요된다. 그런데 응용프로그램 컨텍스트 수가 테스트 수가 늘어나도 유지되고 재사용되기 때문에 테스트가 많아질수록 상대적으로 응용프로그램 컨텍스트 준비 시간이 차지하는 비중이 줄어드는 것이다.

여러 테스트가 하나의 응용프로그램 컨텍스트 공유
Context Bean A Bean B Bean C Test #1 Test #2 Test #3

반면에 실무에서 테스트 클래스마다 필요한 테스트 대역을 준비하기 위해서 응용프로그램 컨텍스트 구성이 계속 달라지는 경우는 새로운 응용프로그램 컨텍스트를 계속 준비하기 때문에 실행 시간이 길어질 수 있다. 과도한 테스트 대역 사용이 일으킬 수 있는 문제 중 하나다. 인프런 강의에서는 H2 인메모리 데이터베이스 외에는 테스트 대역을 사용하지 않는다.

각 테스트가 별도의 응용프로그램 컨텍스트 사용
Context 1 Context 2 Context 3 Test Double A Bean B Bean C Bean A Test Double B Bean C Bean A Bean B Test Double C Test #1 Test #2 Test #3

참고로 나는 그동안 실무에서 Spring Boot 응용프로그램을 개발할 때 @SpringBootTest를 사용한 테스트는 10~20% 정도만 작성하고, 나머지는 Spring 독립적인 순수한 모델 영역의 범위를 크게 만들어서 이 부분을 대상으로 80~90% 정도 테스트를 작성했다. 이렇게 하면 응용프로그램 컨텍스트 준비 시간이 방해가 되는 일이 많지는 않다. 또, 여기서 자세히 설명하지는 않지만 응용프로그램 컨텍스트를 재사용하고 캐싱을 유지하면서 테스트 대역을 사용하는 방법도 있다.

테스트 실행 시간이 짧으면 분명히 장점이 있지만, 제품 요구사항과 밀접한 테스트를 자동화하는 가치가 크기 때문에 각 환경에 따라 응용프로그램 컨텍스를 사용한 테스트에 무조건 거부감을 갖기보다는 실용적인 접근이 필요하다.