@WebMvcTest와 Spring Security 이슈

iqpizza6349·2023년 11월 25일
1

Spring

목록 보기
6/6
post-thumbnail

본 문제는 Springboot 2.7(Spring 5.7) 이상 버전으로 Spring Security를 적용한 @WebMvcTest를 할 때 발생할 수 있는 이슈를 담고 있습니다.
필자 역시 이와 동일한 문제를 `또` 겪었기에 기왕 이렇게된 김에 블로그로 포스트하여 더 이상 시간 낭비를 하지 않기 위해 기록하고자 한다.

문제가 발생한 시점

@WebMvcTest를 사용하여 슬라이스 테스트를 하는 도중 예상치 못하게 에러가 많이 보이고, Forbidden과 Unauthorized 에러를 봤다. 분명히 Springboot 2.7+ 이상에서 WebSecurityConfigurerAdapterdeprecated되면서 직접 빈으로 등록하라고 했기에 SecurityFilterChain으로 등록을 해주었는 데, 등록되지 않았다.

문제가 발생한 이유

문제가 발생한 이유를 찾는 것은 그리 어렵지 않았다.
@WebMvcTest가 테스트 컨텍스트에 어떤 빈들을 등록하는 지를 알면 이유를 쉽게 알 수 있었다.
다음은 자동으로 컨텍스트에 등록하는 빈들이다.

  • @Controller
  • @ControllerAdvice
  • @JsonComponent
  • Converter
  • GenericConverter
  • Filter
  • WebMvcConfigure
  • WebSecurityConfigurerAdapter
  • HandlerMethodArgumentResolver

그 어디에도 @EnableWebSecurity 혹은 SecurityFilterChain는 등록되지 않는다.
(@EnableWebSecurity을 언급하는 이유는 그 안에 GlobalSecurity 어노테이션이 포함되어 있기에 언급했다.)
그렇기에 스프링 개발(지원)팀에서 언급한 새로운 방법으로는 지원해주지 않고 있기 때문에 이러한 문제가 발생하고 있는 것이다.

스프링 개발팀에서 지원해주지 않는 이유

사실 스프링 개발(지원)팀에서도 이미 이러한 문제를 파악하고 있다. (이 글을 작성하고 있는 시점에서는) 스프링 공식 깃허브 이슈를 자주 찾아보는 개발자분들이라면 알고 계시지만, 이미 이러한 문제를 파악하고 이슈로 올라가있다. (물론 Closed 되어 있다.)
(이슈가 궁금하다면 링크를 참고 바란다.)

이슈에서 언급된 말을 빌리자면, 굳이 @WebMvcTest에서 Security까지 신경쓸 필요는 없다고 한다. (정확히는 사용자 어플리케이션이 아닌 Spring Security에서 제공되고 있는 것이기 제공하지 않는 다고 한다.) 또한, 일부 사용자들이 원치않을 경우도 고려해야하는 입장이기에 원할 경우 직접 설정하라고 한다.

추가적으로 필자가 생각했을 때에도 사용자가 임의로 정의(수정)한 SecurityFilterChain 빈 선언을 100% 신뢰하기 어려울 수 있기 때문이라는 생각도 들었다.
(사용자는 항상 고양이 같이 뭘 어떻게 건드릴지 모르는 일이니 말이다.)

해결 방법

해결방법은 이슈 링크에도 언급되어 있듯이 @ImportAutoConfiguration 혹은 @Import를 사용하여 필요한 클래스를 등록하라고 한다.

이게 해결방법이 맞긴 하나요?

공식적으로는 해결 방법 중 하나이다. 그 외에도 방법은 여러가지이니, 무엇을 테스트할지에 따라 달라진다.

필자의 경우

필자는 2가지 방법으로 문제를 해결했다.
한 가지는 공식적인 방법을 사용했고, 다른 한 가지는 FIRST따윈 개나 줘버린 방법이다.

공식적인 방법

@TestConfiguration으로 직접 SecurityFilterChain을 빈으로 등록하는 클래스를 정의하고선, 이를 테스트 클래스에서 @Import하여 사용했다.

그리고 권한이 필요한 부분은 @WithAnonymousUser, @WithMockUser, @WithUserDetails, @WithSecurityContext 어노테이션을 사용했다.

FIRST 방법을 버린 방법

단순히 @SpringBootTest를 사용하는 방법이다. 모든 빈들을 등록하는 단순하고 무식한 방법이지만, 문제는 해결된다. 대신 FIRST는 개나 줘버리기 때문에 문제가 발생하거나 속도가 느릴 수 있다는 사실은 잊어선 안된다.

끝으로...

스프링에서 왜 지원해주지 않는 지 어느 정도 알게 되었다. 추가적으로 의외로 이와 관련된 포스트가 많이 없는 것처럼 보이는 것은 필자의 기분 탓이었음 한다.
(이미 필자처럼 찾아서 공식 방법으로 사용하고 있기를 희망한다.. @SpringBootTest는 정말 사용하지 않았으면 한다. (의존성이 박살난 것이 아니라면 말이다.))

여담이지만, 1년 전까지만 해도 이 문제를 해결하지 못해서 그냥 단순 무식하게 @SpringBootTest를 사용해서 문제를 해결했다.

profile
coffee.drinkUntilEmpty();

0개의 댓글