본문으로 건너뛰기
개발 머꼬
개발 노트Spring
hohyeon.dev27

테스트 200개에 @SpringBootTest를 붙였다가 CI가 20분이 된 이유

  • #Engineering Note
  • #Spring
  • #Testing

문제 발생

테스트를 늘릴수록 CI가 느려졌습니다. 컨트롤러 매핑 하나를 확인하는 테스트도 DB와 메시지 브로커까지 올리고 있었습니다.

@SpringBootTest
class PostControllerTest { ... }

게다가 클래스마다 @MockBean이나 프로퍼티가 조금씩 달라서, 컨텍스트가 계속 새로 만들어졌습니다.

원인 분석

@SpringBootTest는 전체를 띄웁니다. Spring Boot 문서 설명대로 이 애노테이션은 SpringApplication을 통해 전체 애플리케이션 컨텍스트를 로드합니다. 컨트롤러 하나를 보려는 테스트에는 과합니다.

문서는 이 상황을 위해 슬라이스를 제공합니다 — 예를 들어 @WebMvcTest는 스캔 범위를 @Controller, @ControllerAdvice, Converter, Filter 등으로 제한하고 일반 @Component@ConfigurationProperties 빈은 제외하며 MockMvc를 자동 구성합니다. 문서가 드는 동기도 정확히 우리 상황입니다 — Spring MVC 컨트롤러가 URL을 올바르게 매핑하는지 테스트하고 싶지만 그 테스트에 데이터베이스 호출을 끌어들이고 싶지는 않은 경우.

느려진 두 번째 이유는 캐싱입니다. 문서 설명대로 Spring의 테스트 프레임워크는 테스트 사이에 애플리케이션 컨텍스트를 캐시하므로, 테스트들이 같은 설정을 공유하는 한 컨텍스트 로딩은 한 번만 일어납니다. 뒤집으면 설정이 조금이라도 다르면 컨텍스트가 새로 만들어집니다@MockBean 조합이 다르면 그것도 다른 설정입니다.

해결 방안

  1. 계층에 맞는 슬라이스를 씁니다.
@WebMvcTest(PostController.class)   // 웹 계층만
@DataJpaTest                        // JPA 계층만
@JsonTest                           // 직렬화만
  1. 설정 변형을 줄입니다. 공통 목 구성을 부모 클래스나 @TestConfiguration으로 모아 컨텍스트 종류를 손에 꼽을 수 있게 만듭니다. 캐시 적중률이 곧 CI 시간입니다.

  2. 슬라이스를 겹쳐 쓰지 않습니다. 문서가 명시합니다 — 여러 @…Test 애노테이션을 한 테스트에 함께 쓰는 것은 지원되지 않습니다. 필요하면 @SpringBootTest에 개별 @AutoConfigure…를 조합합니다.

  3. webEnvironment를 의식해서 고릅니다. 기본값 MOCK은 서버를 띄우지 않습니다. RANDOM_PORT는 실제 서버가 필요할 때만 씁니다 — 비용이 다릅니다.

  4. 통합 테스트는 소수만 남깁니다. 전체 컨텍스트가 필요한 시나리오(인증 흐름, 트랜잭션 경계)는 분명히 있습니다. 그것만 @SpringBootTest로 두고 나머지는 슬라이스나 순수 단위 테스트로 내립니다.

  5. 컨텍스트가 몇 번 만들어지는지 확인합니다. 로그의 컨텍스트 시작 횟수를 세보면 캐시가 실제로 듣고 있는지 바로 드러납니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.