
개요
Spring Boot 애플리케이션을 개발하다 보면 테스트 작성에서 자주 맞닥뜨리는 고민이 있습니다. "전체 컨텍스트를 띄워서 통합 테스트를 돌려야 할까, 아니면 레이어만 잘라서 빠르게 검증할까?" 이 선택이 CI 파이프라인의 속도와 테스트 품질을 동시에 좌우합니다.
Spring Boot 테스트 전략의 핵심은 @SpringBootTest(전체 컨텍스트 로딩)와 슬라이스 테스트(레이어 단위 격리 테스트)를 상황에 맞게 조합하는 데 있습니다. 이 글에서는 두 방식의 동작 원리와 적합한 사용 시점을 실제 코드와 함께 정리합니다.
@SpringBootTest: 언제, 어떻게 사용하나
@SpringBootTest는 스프링 애플리케이션 컨텍스트 전체를 로딩합니다. @Component, @Service, @Repository, @Controller 등 모든 빈이 등록되고 실제 운영 환경과 가장 유사한 조건에서 테스트가 실행됩니다.
다음은 webEnvironment 속성을 활용해 실제 HTTP 요청까지 검증하는 예시입니다.
// 실제 내장 서버(랜덤 포트)를 띄워 전체 HTTP 흐름을 검증합니다
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class OrderIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private OrderRepository orderRepository;
@Test
void 주문_생성_후_조회_통합_흐름() {
// given
Order saved = orderRepository.save(new Order("item-A", 2));
// when
ResponseEntity<Order> response = restTemplate.getForEntity(
"/api/orders/" + saved.getId(), Order.class);
// then
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody().getItemName()).isEqualTo("item-A");
}
}Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Time elapsed: 4.231 s실행 결과 분석: 단 하나의 테스트임에도 4초 이상 소요됩니다. 컨텍스트 로딩 비용이 크기 때문입니다. 따라서 @SpringBootTest는 서비스 간 연동, DB 트랜잭션 경계, 보안 필터 체인 등 레이어를 관통하는 시나리오에만 한정해서 사용하는 것이 바람직합니다.
슬라이스 테스트로 빠른 피드백 얻기
슬라이스 테스트는 개발자가 각 계층에 구현해 놓은 기능들이 잘 동작하는지 특정 계층만 잘라서(Slice) 테스트하는 것을 말합니다. 슬라이스 테스트는 특정 레이어에 필요한 빈만 선택적으로 로딩합니다. Spring Boot가 기본 제공하는 대표적인 어노테이션은 다음과 같습니다.
| 어노테이션 | 로딩 대상 | 주요 용도 |
|---|---|---|
@WebMvcTest |
MVC 레이어 빈 | Controller, Filter, Argument Resolver |
@DataJpaTest |
JPA 관련 빈 + 인메모리 DB | Repository, 쿼리 검증 |
@JsonTest |
JSON 직렬화 관련 빈 | ObjectMapper 설정 검증 |
@WebFluxTest |
WebFlux 레이어 빈 | Reactive Controller |
@WebMvcTest — 컨트롤러 레이어 격리
서비스 계층은 @MockBean으로 대체하고, HTTP 요청·응답·유효성 검증에만 집중합니다.
// MockMvc를 활용해 컨트롤러 레이어만 빠르게 검증합니다
@WebMvcTest(OrderController.class)
class OrderControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private OrderService orderService; // 실제 빈 대신 Mock 주입
@Test
void 주문_단건_조회_200_응답() throws Exception {
// given
given(orderService.findById(1L))
.willReturn(new OrderResponse(1L, "item-A", 2));
// when & then
mockMvc.perform(get("/api/orders/1")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.itemName").value("item-A"))
.andDo(print());
}
}Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Time elapsed: 0.812 s ← @SpringBootTest 대비 약 5배 빠름
@DataJpaTest — 리포지토리 레이어 격리
@DataJpaTest는 기본적으로 인메모리 H2 데이터베이스를 사용하며, 각 테스트는 트랜잭션 롤백으로 격리됩니다.
// JPA 리포지토리의 쿼리 정확성을 인메모리 DB로 검증합니다
@DataJpaTest
class OrderRepositoryTest {
@Autowired
private OrderRepository orderRepository;
@Test
void 아이템명으로_주문_목록_조회() {
// given
orderRepository.saveAll(List.of(
new Order("item-A", 1),
new Order("item-B", 3),
new Order("item-A", 2)
));
// when
List<Order> result = orderRepository.findByItemName("item-A");
// then
assertThat(result).hasSize(2)
.extracting(Order::getItemName)
.containsOnly("item-A");
}
}Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Time elapsed: 1.104 s실제 프로젝트에서 Querydsl이나 네이티브 쿼리를 사용한다면 @AutoConfigureTestDatabase(replace = NONE)을 추가해 실제 데이터베이스와 연결하는 방식도 고려할 수 있습니다.
테스트 전략 선택 가이드
어떤 테스트를 선택할지는 "무엇을 검증하고 싶은가" 로 결정합니다. 아래 흐름도를 참고하십시오.
- 레이어 하나의 동작을 빠르게 검증 → 슬라이스 테스트(
@WebMvcTest,@DataJpaTest등) - 두 레이어 이상의 협력·연동 검증 →
@SpringBootTest+MOCK또는RANDOM_PORT - 외부 API·메시지 큐 포함 E2E 검증 →
@SpringBootTest+ Testcontainers
컨텍스트 캐싱으로 속도 개선
@SpringBootTest를 여러 테스트 클래스에서 사용할 때는 컨텍스트 캐싱을 적극 활용하십시오. 동일한 컨텍스트 구성이라면 스프링이 캐시에서 재사용하므로, @MockBean 남발을 지양하고 테스트 설정을 최대한 통일하는 것이 빌드 속도를 높이는 핵심입니다.
// 공통 컨텍스트 설정을 부모 클래스에 모아 캐시 히트율을 높입니다
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@ActiveProfiles("test")
abstract class IntegrationTestBase {
// 모든 통합 테스트 클래스가 이 클래스를 상속
}맺음말
Spring Boot 테스트 전략의 핵심은 테스트 목적에 따른 도구 선택입니다.
- 슬라이스 테스트는 특정 레이어의 책임을 빠르고 명확하게 검증합니다. 개발 사이클 중 가장 자주 실행되는 테스트에 적합합니다.
@SpringBootTest는 레이어를 관통하는 시나리오나 인프라 연동을 검증할 때 적합하지만, 남용하면 빌드 시간이 급격히 늘어납니다.
두 방식을 목적에 맞게 조합하면 빠른 피드백과 높은 신뢰도를 동시에 확보할 수 있습니다. 다음 단계로는 Testcontainers를 활용한 실제 DB 통합 테스트나 Spring Security와 테스트 설정 분리 전략을 살펴보시길 권장합니다.
또한 Spring Boot 공식 테스트 문서는 각 슬라이스 어노테이션의 로딩 대상 빈 목록을 상세히 정리하고 있어 설계 기준으로 삼기 좋습니다.
'프로그래밍 PROGRAMMING > 자바 JAVA AND FRAMEWORKS' 카테고리의 다른 글
| OpenTelemetry로 분산 트레이싱 구축하기: Spring Boot 적용 가이드 (1) | 2026.03.12 |
|---|---|
| [JAVA] JVM GC 튜닝으로 자연시간 줄이기 (0) | 2026.03.09 |
| Java HashMap 성능 최적화 초기 용량과 로드 팩터를 제대로 설정하는 법 (0) | 2026.03.07 |
| Java Virtual Threads로 고성능 서버 구현하기 스레드 병목을 해소하는 방법 (0) | 2026.03.06 |
| [JAVA/SPRING] Java Virtual Threads로 고성능 서버 구축하기 스레드 전환 비용 줄이는 방법 (0) | 2026.03.06 |