문제 상황
Spring Security + JWT가 적용된 프로젝트에서 @WebMvcTest로 컨트롤러 테스트 시 JWTFilter 및 SecurityConfig도 제외하면 정상적으로 테스트가 성공할 줄 알았지만 401 Unauthorized 에러가 발생했다
@WebMvcTest(
controllers = RankController.class,
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JWTFilter.class),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
}
)
class MockRankControllerTest {
...
}
문제 해결 방안
은 엄청 간단하다
@AutoConfigureMockMvc(addFilters = false)를 추가하면 된다
@WebMvcTest(
controllers = RankController.class,
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = JWTFilter.class),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
}
)
@AutoConfigureMockMvc(addFilters = false)
class MockRankControllerTest {
...
}
@AutoConfigureMockMvc(addFilters = false) 와 @WebMvcTest의 excludeFilters 차이점
간단하게 JWTFilter와 SecurityConfig는 다음과 같이 구현되어 있다
@Configuration
@EnableWebSecurity
public class SecurityConfig {
}
@Component
public class JWTFilter extends OncePerRequestFilter {
}
mockMvc를 디버깅해보면 filters 부분에 springSecurityFilterChain, JWTFilter가 있는 걸 볼 수 있다

- springSecurityFilterChain 는 기본적으로 spring-security 의존성을 추가했을 때 자동으로 생성된다
- JWTFilter는 Filter를 상속받아 구현하여서 생성된다
@WebMvcTest의 excludeFilters
excludeFilters는 Component Scan 할 때 특정 클래스를 제외하는 필터이다
문제 상황에서 mockMvc를 다시 디버깅해보면 springSecurityFilterChain 유지, JWTFilter는 없어진 걸 볼 수 있다

excludeFilters로 SecurityConfig를 제외해도, Spring Security 자체는 여전히 활성화되어 있어 springSecurityFilterChain 유지가 된다
왜냐하면 SecurityConfig는 Filter가 아니라 설정 클래스이기 때문에 단지 SecurityConfig로 구현한 부분이 springSecurityFilterChain에 등록이 된다
동작 방식
| 1. Spring Context 로딩 시작 2. Component Scan 실행 ├─ excludeFilters 확인 └─ SecurityConfig.class 제외 └─ JWTFilter.class 제외 3. Bean 등록 └─ RankController -> Bean 등록 4. Auto-configuration 실행 └─ springSecurityFilterChain (SecurityConfig가 없어도 기본 설정 적용) 5. MockMvc 생성 └─ addFilters = true (기본값) └─ Spring Context에서 모든 Filter Bean 수집 └─ springSecurityFilterChain 포함 6. MockMvc 최종 구조 mockMvc { filters = [springSecurityFilterChain] } 7. 테스트 실행 요청 → springSecurityFilterChain → 인증 체크 → 401 에러 발생 !! |
@AutoConfigureMockMvc(addFilters = false)
MockMvc 생성 시, 모든 Servlet Filter를 비활성화하는 옵션으로 모든 filters가 제외되어 인증 없이 컨트롤러 테스트만 가능하다!
mockMvc 디버깅 결과: Filter 배열이 0이다

동작 방식
| 1. Spring Context 로딩 시작 2. Component Scan 실행 3. Bean 등록 ├─ SecurityConfig -> Bean 등록 ├─ JWTFilter -> Bean 등록 └─ RankController -> Bean 등록 4. Auto-configuration 실행 └─ springSecurityFilterChain -> Bean 생성 5. MockMvc 생성 └─ @AutoConfigureMockMvc 확인 └─ addFilters = false 발견 -> 모든 필터 제거! 6. MockMvc 최종 구조 mockMvc { filters = [] } 7. 테스트 실행 요청 → (필터 없음) → DispatcherServlet → Controller 테스트 성공 |
결론
- excludeFilters: Bean 로딩만 제어 → Auto-configuration은 막을 수 없다
- addFilters = false: 필터 실행 자체를 차단 → Security 완전 비활성화한다
따라서, 컨트롤러 단위 테스트에는 @AutoConfigureMockMvc(addFilters = false) 사용하면 필터 관련 문제를 해결할 수 있다
'Spring' 카테고리의 다른 글
| [Spring] Bean이란? (0) | 2026.01.24 |
|---|---|
| [Spring] DI(Dependency Injection) (0) | 2026.01.12 |
| [Spring] IoC(Inversion of Control) (0) | 2025.12.31 |
| [Spring] 스프링의 3계층 구조 : Controller, Service, Repository (1) | 2025.12.11 |
| [Spring] Spring과 SpringBoot의 차이 (1) | 2025.10.26 |