스프링 시큐리티(Spring Security)는 스프링 기반의 애플리케이션 보안(인증, 인가, 권한)을 담당하는 스프링 하위 프레임워크이다.
스프링 시큐리티에서는 주로 서블릿 필터(filter)와 이들로 구성된 필터체인으로의 구성된 위임 모델을 사용한다.
스프링 시큐리티의 동작 구조는 공식문서에 따르면 다음과 같다.
스프링 시큐리티는 서블릿 필터기반으로 동작한다.
서블릿 필터는 서블릿 실행에 대한 전처리 및 후처리를 실행하는 역할이다.

클라이언트가 요청을 보내면, WAS는 이 요청을 웹 컨테이너를 통해 처리한다.
웹 컨테이너는 요청 URI를 기반으로 어떤 서블릿이 처리할지 결정하고,
그 서블릿과 관련된 FilterChain(Filter 목록 + 서블릿)을 생성한다.
이 FilterChain은 먼저 여러 Filter들을 실행하며 요청을 가공하거나 보안을 적용한 뒤,최종적으로 서블릿(예: DispatcherServlet)을 실행해 초기화된 서블릿으로 처리를 넘긴다.

하지만 서블릿 컨테이너는 Spring에서 정의한 Bean을 인식하지 못한다.
이를 해결하기 위해 Spring은 DelegatingFilterProxy라는 Filter구현체를 제공한다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
Filter delegate = getFilterBean(someBeanName); //1
delegate.doFilter(request, response); //2
}
이렇게 DelegatingFilterProxy는 서블릿 Filter의의 기능을 Bean Filter로 위임하여 실행할 수 있도록 해준다. 즉, DelegatingFilterProxy는 Bean Filter를 Filter로 위임하는 중간 다리 역할을 해준다.

FilterChainProxy는 스프링 시큐리티(Spring Security)가 제공하는 특수한 Filter 구현체로 SecurityFilterChain를 통해 여러개의 SecurityFilterChain을 위임할 수 있게 해준다.
FilterChainProxy도 Spring에서 제공하는 Bean이므로 서블릿 컨테이너에 직접 등록되지 않고DelegatingFilterProxy 로 매핑된다.

SecurityFilterChain은 FilterChainProxy가 현재 요청에 대해 어떤 Security Filter를 호출해야 할지 결정하는데 사용된다.
Security Filtersms Bean이지만 DelegatingFilterProxy대신에 FilterChainProxy에 등록된다.
그러므로 FilterChainProxy는 스프링 시큐리티(Spring Sicurity)의 시작점 역할을 한다.
FilterChainProxy는 SecurityFilterChain을 통해 여러 Filter 인스턴스로 위임하여 실행할수 있다.

또한 여러 개의 SecurityFilterChain을 설정해두고,
FilterChainProxy를 통해 요청 URL에 따라 각각의 SecurityFilterChain을 매핑하여 적용할 수 있다.
특정 요청에 대해 스프링 시큐리티가 무시하려면, SecurityFilterChain에 보안 Filter를 0개 설정하면 된다.
그럼 인증(Authentication)된 객체가 어떻게 저장될까?

Spring Security에서는 인증(Authentication) 정보를 SecurityContextHolder를 통해 전역적으로 관리한다.
실제로는 인증에 성공한 사용자의 Authentication 객체가 SecurityContextHolder가 보유한 SecurityContext 내부에 저장된다.
이 SecurityContext는 일반적으로 ThreadLocal기반으로 동작하여,
각 요청 스레드마다 독립된 인증 정보를 안전하게 분리하여 관리할 수 있도록 한다.
null로 설정되는 경우가 많다.GrantedAuthority의 리스트로 구성된다.
1. Http Request
사용자가 /login 요청을 보냄 (아이디/비밀번호 포함)
사용자가 입력한 아이디/비밀번호를 가지고 UsernamePasswordAuthenticationToken 객체 생성
AuthenticationManager로 토큰 전달
AuthenticationFilter는 AuthenticationManager에게 위에서 만든 토큰을 넘김
AuthenticationManager는 실제 인증을 AuthenticationProvider에 위임
일반적으로 사용되는 구현체는 ProviderManager임
AuthenticationProvider → UserDetailsService 사용
인증을 처리하기 위해 UserDetailsService의 loadUserByUsername() 호출
UserDetailsService가 DB에서 User 정보 조회
아이디로 사용자를 찾고, 비밀번호, 권한 정보 등을 포함한 UserDetails 객체를 리턴
UserDetails를 기반으로 Authentication 객체 생성
AuthenticationProvider는 아이디/비밀번호가 일치하면,
인증 완료 상태의 Authentication 객체를 생성하고 반환
AuthenticationManager → 인증 성공 결과 반환
최종적으로 인증된 Authentication 객체를 AuthenticationManager가 AuthenticationFilter에 반환
AuthenticationFilter가 인증 성공 시 SecurityContext에 저장
SecurityContextHolder.getContext().setAuthentication(...) 호출
SecurityContextHolder에 인증 정보 저장 완료
이후부터는 이 정보(Authentication)를 통해
사용자 정보, 권한 등을 어디서든 사용할 수 있음 (예: @AuthenticationPrincipal 등)