https://godekdls.github.io/Spring%20Security/testing/
특성 | @WithMockUser | @WithAnonymousUser | @WithUserDetails | @WithSecurityContext |
---|---|---|---|---|
목적 | 간단한 모의 사용자로 테스트 | 익명 사용자로 테스트 | 실제 UserDetailsService 사용 | 완전 커스터마이즈된 SecurityContext |
복잡성 | 낮음 | 매우 낮음 | 중간 | 높음 |
유연성 | 중간 | 낮음 | 높음 | 매우 높음 |
실제 데이터 사용 | 아니오 | 아니오 | 예 | 구현에 따라 다름 |
커스터마이즈 | 사용자명, 비밀번호, 역할, 권한 | 불가능 | 사용자명, UserDetailsService | 완전한 제어 가능 |
사용 편의성 | 쉬움 | 매우 쉬움 | 중간 | 어려움 |
주요 사용 사례 | 기본적인 인증 테스트 | public 리소스, 인증 실패 테스트 | 실제 사용자 데이터로 테스트 | 복잡한 인증 시나리오 |
UserDetailsService 필요 | 아니오 | 아니오 | 예 | 구현에 따라 다름 |
추가 구현 필요 | 아니오 | 아니오 | 아니오 | 예 (Factory 클래스) |
개발자 민수는 온라인 쇼핑몰 프로젝트를 진행 중입니다. 보안 테스트를 시작하려는데, 어떤 방식을 사용해야 할지 고민하고 있습니다.
먼저 민수는 상품 목록 조회 API를 테스트하려 합니다. 이 API는 로그인하지 않은 사용자도 접근 가능해야 합니다.
"이런 경우엔 @WithAnonymousUser를 사용하면 되겠군," 민수는 생각합니다. "이렇게 하면 인증 없이 API를 호출하는 상황을 쉽게 시뮬레이션할 수 있어."
다음으로 민수는 장바구니 추가 기능을 테스트하려 합니다. 이 기능은 로그인한 사용자만 사용할 수 있습니다.
"여기엔 @WithMockUser를 쓰면 되겠다," 민수는 결정합니다. "@WithMockUser(username="user", roles="CUSTOMER")로 설정하면 고객 권한을 가진 사용자로 빠르게 테스트할 수 있겠어."
그러다 민수는 주문 내역 조회 기능을 테스트해야 한다는 것을 깨닫습니다. 이 기능은 실제 사용자의 주문 데이터를 확인해야 합니다.
"이건 좀 더 현실적인 데이터가 필요하겠는걸," 민수는 생각합니다. "@WithUserDetails를 사용해서 실제 데이터베이스에 있는 사용자 정보로 테스트해야겠다. @WithUserDetails("user@example.com")으로 특정 사용자의 주문 내역을 정확히 테스트할 수 있을 거야."
프로젝트가 진행되면서 민수는 관리자 기능을 구현하게 됩니다. 관리자는 특별한 권한을 여러 개 가지고 있어야 합니다.
"이건 좀 복잡한데?" 민수는 고민합니다. "일반적인 방법으론 부족할 것 같아. @WithSecurityContext를 사용해서 커스텀 어노테이션을 만들어야겠다. @WithAdminUser 같은 걸 만들어서 관리자의 모든 권한을 정확히 시뮬레이션할 수 있을 거야."
마지막으로 민수는 소셜 로그인 기능을 구현하고 테스트해야 합니다. 이 기능은 표준 스프링 시큐리티 인증과는 다른 방식으로 작동합니다.
"이건 정말 특별한 경우네," 민수는 생각합니다. "@WithSecurityContext를 사용해 @WithOAuth2User 같은 커스텀 어노테이션을 만들어야겠어. 이렇게 하면 OAuth2 인증을 정확히 시뮬레이션할 수 있을 거야."
이렇게 민수는 다양한 상황에 맞춰 적절한 테스트 방법을 선택했습니다. 간단한 인증이 필요할 때는 @WithMockUser를, 익명 사용자 테스트에는 @WithAnonymousUser를, 실제 사용자 데이터가 필요할 때는 @WithUserDetails를, 그리고 복잡하고 특별한 인증 상황에는 @WithSecurityContext를 사용해 커스텀 어노테이션을 만들어 사용했습니다.
"각 상황에 맞는 도구를 사용하니 테스트가 훨씬 효율적이고 정확해졌어," 민수는 만족스럽게 생각합니다. "스프링 시큐리티 테스트 기능을 잘 활용하면 어떤 복잡한 인증 상황도 테스트할 수 있겠어!"
그림일기 서비스에서 단위 테스트에 @WithSecurityConext를 사용했길래 왜 그런 걸까 궁금했었다.
정리해보니 JWT, OAuth 인증 방식이 표준 스프링 시큐리티 인증과 다른 방식으로 작동하고 있어서 @WithSecurityContext를 써야 하는 거였다!
그래서 @WithSeucirytContextFactory도 같이 구현해줘야 했던 거고