티스토리 뷰
Spring Boot 테스트 슬라이스 완전 정리: @WebMvcTest, @DataJpaTest 동작 원리와 Mockito의 역할
ebson 2026. 2. 26. 07:44Spring Boot로 애플리케이션을 개발하다 보면 테스트 전략은 자연스럽게 복잡해집니다. 단위 테스트를 작성하다가 어느 순간 @SpringBootTest를 사용하게 되고, 또 어느 순간 @WebMvcTest나 @DataJpaTest와 같은 테스트 슬라이스 어노테이션을 접하게 됩니다. 표면적으로는 모두 “테스트”이지만, 실제로는 로딩되는 Bean의 범위와 컨텍스트 구성 전략이 다릅니다.
이 글에서는 Spring Boot 공식 문서와 Spring TestContext Framework의 동작 방식을 기반으로, 테스트 슬라이스가 실제로 무엇을 로딩하는지, 그리고 그 안에서 Mockito가 어떤 역할을 수행하는지 정리해 보겠습니다. 단순히 단위 테스트와 통합 테스트를 비교하는 차원을 넘어, Spring Boot 테스트 아키텍처를 입체적으로 이해하는 데 초점을 맞추겠습니다.
테스트 슬라이스가 등장한 배경
Spring Boot는 자동 설정(Auto Configuration)을 통해 애플리케이션 컨텍스트를 구성합니다. @SpringBootTest는 이 전체 컨텍스트를 로딩합니다. 즉, 애플리케이션이 실제 구동될 때와 거의 동일한 환경을 구성합니다.
하지만 모든 테스트에서 전체 컨텍스트를 로딩하는 것은 비용이 큽니다. Spring TestContext Framework는 컨텍스트 캐싱을 지원하지만, 테스트 설정이 달라지면 새로운 컨텍스트를 생성해야 합니다. 이로 인해 테스트 수가 많아질수록 실행 시간이 증가합니다.
이 문제를 해결하기 위해 Spring Boot는 “테스트 슬라이스”라는 개념을 도입했습니다. 특정 계층만 로딩하여 테스트 목적에 맞는 최소한의 컨텍스트만 구성하는 전략입니다.
@WebMvcTest는 실제로 어떤 Bean을 로딩하는가
Spring Boot 공식 문서에 따르면 @WebMvcTest는 MVC 구성 요소만을 로딩하도록 설계되어 있습니다. 기본적으로 다음과 같은 구성 요소들이 포함됩니다.
- @Controller
- @ControllerAdvice
- @JsonComponent
- Converter, GenericConverter
- Filter
- Spring MVC 관련 설정
반면, @Service, @Repository, @Component와 같은 일반적인 Bean은 자동으로 로딩되지 않습니다. 이는 @WebMvcTest가 전체 컴포넌트 스캔을 수행하는 대신, MVC 계층에 필요한 구성 요소만 제한적으로 로딩하도록 Auto Configuration을 필터링하기 때문입니다.
결과적으로 @WebMvcTest는 웹 계층의 요청-응답 흐름을 검증하기에 적합한 환경을 구성합니다. DispatcherServlet은 구성되지만, 비즈니스 로직 계층은 기본적으로 포함되지 않습니다.
이 설계는 테스트 범위를 명확히 제한합니다. Controller의 요청 매핑, Validation, JSON 직렬화/역직렬화 등을 검증하는 데 초점을 맞춥니다.
@DataJpaTest는 어떤 Auto Configuration을 포함하는가
@DataJpaTest는 JPA 관련 구성 요소만을 로딩하는 테스트 슬라이스입니다. Spring Boot 문서에 따르면 다음과 같은 구성들이 포함됩니다.
- JPA 관련 Auto Configuration
- DataSource 설정
- Hibernate 설정
- EntityManagerFactory
- Spring Data JPA Repository
기본적으로는 Embedded Database를 자동으로 구성합니다. 명시적으로 설정하지 않으면 H2, HSQL, Derby 등 내장 데이터베이스가 사용됩니다.
또한 @DataJpaTest는 기본적으로 각 테스트 메서드 실행 후 트랜잭션을 롤백합니다. 이는 테스트 간 상태 오염을 방지하기 위한 전략입니다. Spring TestContext Framework가 트랜잭션 경계를 관리하며, 테스트 실행 후 자동 롤백을 수행합니다.
이 구조는 Repository 계층의 동작을 검증하기에 적합합니다. 실제 JPA 동작, 쿼리 생성, 매핑 오류 등을 확인할 수 있습니다.
슬라이스 테스트에서 @MockBean이 필요한 이유
@WebMvcTest는 Service Bean을 자동으로 로딩하지 않습니다. 따라서 Controller가 의존하는 Service를 그대로 두면 Bean 주입 오류가 발생합니다.
이때 사용하는 것이 @MockBean입니다. @MockBean은 Spring Boot 테스트 지원 기능으로, ApplicationContext에 Mockito 기반 mock 객체를 등록합니다. 기존 Bean이 존재하면 해당 Bean을 교체합니다.
즉, @MockBean은 단순히 Mockito mock을 생성하는 것이 아니라, Spring 컨텍스트 내부에 해당 mock을 Bean으로 등록합니다. 이 차이 때문에 슬라이스 테스트에서 중요한 역할을 합니다.
Controller는 실제 Service 대신 mock Service를 주입받습니다. 이를 통해 웹 계층만을 격리하여 테스트할 수 있습니다.
Mockito의 @Mock과 Spring의 @MockBean의 차이
Mockito의 @Mock은 순수 Mockito 차원에서 mock 객체를 생성합니다. 이는 Spring 컨텍스트와 무관합니다. 테스트 클래스 내부에서만 사용됩니다.
반면 @MockBean은 Spring Boot 테스트 환경에서 동작하며, ApplicationContext에 mock을 등록합니다. 이로 인해 의존성 주입 과정에 영향을 줍니다.
정리해 보면 다음과 같은 구조적 차이가 있습니다.
- @Mock은 Mockito Extension이 관리합니다.
- @MockBean은 Spring TestContext Framework가 관리합니다.
- @Mock은 컨텍스트 외부 객체입니다.
- @MockBean은 컨텍스트 내부 Bean입니다.
이 차이로 인해 테스트 범위와 격리 수준이 달라집니다.
컨텍스트 캐싱 전략과 테스트 실행 속도의 관계
Spring TestContext Framework는 동일한 설정의 ApplicationContext를 캐싱합니다. 캐시 키는 설정 클래스, 활성 프로파일, ContextLoader, PropertySource 등 여러 요소에 의해 결정됩니다.
테스트 클래스마다 설정이 달라지면 새로운 컨텍스트가 생성됩니다. @MockBean을 사용하는 경우, 해당 Bean 정의가 컨텍스트 구성에 포함되므로 캐시 키에 영향을 줄 수 있습니다.
또한 @DirtiesContext를 사용하면 캐시된 컨텍스트가 폐기됩니다. 이는 테스트 안정성을 높일 수 있지만, 실행 속도에는 영향을 줍니다.
슬라이스 테스트는 전체 컨텍스트가 아니라 일부만 로딩하기 때문에, 기본적으로 @SpringBootTest보다 빠르게 실행되는 경향이 있습니다. 다만, 슬라이스 종류가 다양해질수록 캐시 분산이 발생할 수 있습니다.
슬라이스 테스트는 단위 테스트인가 통합 테스트인가
이 질문은 자주 등장하지만, 명확하게 둘 중 하나로 단정하기는 어렵습니다.
슬라이스 테스트는 단위 테스트처럼 전체 애플리케이션을 로딩하지 않습니다. 하지만 순수 단위 테스트와 달리 Spring 컨텍스트를 로딩합니다. 실제 DispatcherServlet이나 JPA 환경이 구성됩니다.
따라서 슬라이스 테스트는 특정 계층 범위 내에서의 “부분 통합 테스트”에 가깝다고 정리할 수 있습니다. Controller와 MVC 인프라의 통합, Repository와 JPA 인프라의 통합을 검증합니다.
이는 테스트 피라미드에서 중간 계층에 해당합니다. 순수 단위 테스트와 전체 통합 테스트 사이의 균형 지점에 위치합니다.
단위 vs 통합을 넘어선 테스트 아키텍처 관점
Spring Boot 테스트 전략은 단순히 “단위 테스트를 많이 작성하자” 혹은 “통합 테스트가 더 안전하다”라는 이분법으로 설명되기 어렵습니다.
- 순수 Mockito 단위 테스트는 가장 빠르고 격리된 테스트입니다.
- 슬라이스 테스트는 계층 단위의 통합을 검증합니다.
- @SpringBootTest는 전체 애플리케이션의 통합을 검증합니다.
이 세 가지는 경쟁 관계라기보다, 서로 다른 위험을 줄이기 위한 전략입니다.
Mockito는 이 중에서 단위 테스트뿐 아니라 슬라이스 테스트에서도 핵심 역할을 합니다. @MockBean을 통해 계층 간 경계를 제어하는 도구로 사용됩니다.
마무리하며
테스트 슬라이스는 단위 테스트도 아니고, 완전한 통합 테스트도 아닙니다. Spring Boot가 제공하는 계층적 테스트 전략의 일부라고 보는 것이 더 적절해 보입니다.
Mockito 역시 단순한 mocking 도구를 넘어, 테스트 경계를 설정하는 역할을 수행합니다. 중요한 것은 도구 자체보다 테스트 범위를 어떻게 정의할 것인가입니다.
저 역시 테스트 코드를 작성하면서, 속도와 안정성 사이의 균형을 고민하게 되었습니다. 슬라이스 테스트는 그 균형을 맞추기 위한 실용적인 선택지라고 느끼고 있습니다. 단정적인 정답이 있다기보다는, 애플리케이션의 구조와 팀의 품질 목표에 따라 적절한 조합을 설계하는 것이 더 중요하다고 생각합니다.
Spring Boot 테스트 아키텍처를 입체적으로 이해하는 과정은, 결국 애플리케이션 구조를 더 깊이 이해하는 과정과도 연결된다고 생각합니다.
'STUDY' 카테고리의 다른 글
| 테스트 피라미드와 Spring Boot 테스트 전략: Mockito 단위 테스트부터 @SpringBootTest까지의 균형 (0) | 2026.02.26 |
|---|---|
| Mockito 내부 동작 원리 완전 정리: Bytecode 조작과 Mock Maker, 그리고 테스트 설계 철학 (0) | 2026.02.26 |
| Spring Boot에서 Mockito 단위 테스트와 @SpringBootTest의 차이 정리: 언제 무엇을 사용해야 할까 (0) | 2026.02.26 |
| Spring Batch chunk size 선택 기준: 디스크 IO와 네트워크 비용 모델 비교 (0) | 2026.02.25 |
| RDBMS 트랜잭션 격리수준 심화 이해: MySQL·PostgreSQL·MSSQL 기본값과 Phantom Read 원리 (0) | 2026.02.24 |
- Total
- Today
- Yesterday
- Java Performance
- Enum 기반 싱글톤
- 캐시 장애
- Cache Aside
- Cache Penetration
- InterruptedException
- 트래픽 처리
- 백엔드 성능
- Hot Key 문제
- Spring Batch
- Eager Initialization
- 동시성처리
- Redis 캐시 전략
- 캐시 성능 비교
- 캐시와 인덱스
- mybatis
- 스레드 생명주기
- Double-Checked Locking
- Redis vs DB
- spring batch 5
- Redis 성능 개선
- DB 트랜잭션
- 백엔드 성능 설계
- 트랜잭션 관리
- TTL 설계
- 백엔드 성능 튜닝
- Cache Avalanche
- DB 인덱스 성능
- 백엔드 아키텍처
- Initialization-on-Demand Holder Idiom
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |

