포스트

Spring Security 요청 처리 흐름과 DispatcherServlet

Spring Security 요청 처리 흐름과 DispatcherServlet

요청이 필터를 거쳐 인증과 인가를 수행하고 DispatcherServlet을 통해 컨트롤러로 전달되는 흐름 정리

오늘은 Spring Security를 단순히 “권한 설정을 적는 도구”로 보는 것이 아니라,
실제 요청이 들어왔을 때 내부에서 어떤 순서로 동작하는지 흐름 중심으로 정리했다.

1. 인증과 인가의 역할 구분

먼저 가장 중요한 전제는 인증(Authentication)인가(Authorization) 는 다르다는 점이다.

  • 인증: 사용자가 누구인지 확인하는 과정
  • 인가: 인증된 사용자가 무엇을 할 수 있는지 확인하는 과정

쉽게 말하면 인증은 “로그인 확인”, 인가는 “권한 확인”이다.
그리고 순서는 항상 인증이 먼저, 인가가 나중이다.
누구인지 확인되지 않은 상태에서는 권한 판단도 할 수 없기 때문이다.


2. 요청이 들어오면 바로 컨트롤러로 가지 않는다

Spring Boot 애플리케이션에서 요청이 들어오면,
바로 컨트롤러로 진입하는 것이 아니라 먼저 Security Filter 들을 거친다.

이 부분이 중요했다.
나는 처음에 컨트롤러가 먼저 실행되고 그 안에서 권한을 검사하는 줄 알았는데,
실제로는 그 전에 Spring Security가 요청을 가로채서 먼저 확인한다.

즉, 전체 흐름은 대략 다음과 같다.

요청 → 필터 → 인증 정보 확인 → SecurityContext 저장 → 인가 처리 → 컨트롤러 진입

이 순서를 이해하니 왜 Security 설정이 애플리케이션 전반에 영향을 주는지도 더 명확해졌다.


3. JWT 기반 인증에서는 무엇을 확인할까

JWT 방식을 사용할 때는 서버가 세션처럼 로그인 상태를 저장하지 않는다.
대신 클라이언트가 요청마다 JWT를 함께 보내고,
서버는 그 토큰이 유효한지 검사해서 사용자를 식별한다.

여기서 핵심은 다음과 같다.

  • 사용자가 로그인하면 서버가 JWT를 발급한다.
  • 클라이언트는 이후 요청마다 JWT를 함께 보낸다.
  • 서버는 요청이 들어올 때 JWT를 검증한다.
  • 검증이 성공하면, 이 사용자가 누구인지에 대한 인증 정보를 만든다.

즉, JWT 자체가 인증을 “완료”하는 것이 아니라,
JWT를 검증한 결과를 바탕으로 Spring Security가 인증 객체를 생성하는 것이 핵심이다.


4. Authentication 객체는 왜 필요한가

JWT를 검증했다고 해서 끝나는 것이 아니라,
Spring Security는 그 결과를 바탕으로 Authentication 객체를 만든다.

이 객체에는 보통 다음과 같은 의미가 담긴다.

  • 현재 사용자가 누구인지
  • 인증이 완료된 사용자인지
  • 어떤 권한이나 역할을 가지고 있는지

즉, Authentication은
“이 요청의 사용자 정보를 Spring Security가 이해할 수 있는 형태로 정리한 결과물”이라고 볼 수 있다.

비유하면,
JWT는 사용자가 들고 온 출입증 원본이고,
Authentication은 보안 시스템이 그 출입증을 확인한 뒤 내부 기록에 등록한 출입 정보라고 이해할 수 있다.


5. SecurityContext는 인증 정보를 보관하는 공간이다

Authentication 객체가 만들어지면,
그 다음에는 이 정보를 SecurityContext 에 저장한다.

이 저장 과정이 중요한 이유는,
이후의 권한 검사나 컨트롤러 처리 과정에서
“현재 요청 사용자가 누구인지” 계속 참조해야 하기 때문이다.

즉, SecurityContext는 현재 요청에서 사용할 인증 정보를 담아두는 공간이다.

정리하면:

  • JWT 검증
  • Authentication 생성
  • SecurityContext 저장

이 흐름이 완료되어야 이후 인가 처리가 가능하다.


6. 인가는 어디서 일어날까

인증 정보가 준비되면 이제 Spring Security는
이 사용자가 해당 요청에 접근할 수 있는지 판단한다.
이 단계가 바로 인가다.

인가 방식은 크게 두 가지로 이해할 수 있었다.

6-1. URL 권한 설정

URL 자체를 기준으로 접근 가능 여부를 판단한다.

예를 들어,

  • 누구나 접근 가능한 경로
  • 관리자만 접근 가능한 경로

처럼 경로 단위로 제어하는 방식이다.

이 방식은 애플리케이션 입구에서 1차로 막아주는 느낌이라서
1차 방어선처럼 이해할 수 있었다.

6-2. 메서드 권한 설정

컨트롤러나 서비스 내부의 특정 기능 실행 시점에 권한을 검사한다.

이 방식은 같은 URL 흐름 안에서도
실행되는 기능 단위로 더 세밀하게 제어할 수 있다.

그래서 메서드 권한 설정은
2차 방어선, 혹은 더 정밀한 권한 제어라고 볼 수 있다.

즉,

  • URL 권한 설정: “이 주소로 들어와도 되는가?”
  • 메서드 권한 설정: “들어온 뒤 이 기능까지 수행해도 되는가?”

라는 차이로 이해했다.


7. permitAll 과 hasRole 차이

권한 설정을 볼 때 자주 나오는 표현도 함께 정리했다.

permitAll

  • 인증이 없어도 접근 가능
  • 누구나 접근할 수 있는 공개 자원에 사용

예: 공지사항, 로그인 페이지, 회원가입 페이지

hasRole

  • 특정 역할을 가진 사용자만 접근 가능
  • 인증뿐 아니라 권한까지 확인해야 함

예: 관리자 페이지, 운영 기능

처음에는 둘 다 “접근 설정”이라는 점에서 비슷하게 느껴졌지만,
핵심 차이는 허용 범위였다.

  • permitAll = 공개
  • hasRole = 역할 제한

즉, permitAll은 인증이 없어도 통과할 수 있지만,
hasRole은 인증된 사용자 중에서도 특정 역할을 가진 경우에만 통과할 수 있다.


8. 전체 흐름을 한 번에 정리하면

오늘 학습한 내용을 한 줄 흐름으로 정리하면 다음과 같다.

  1. 클라이언트가 요청을 보낸다.
  2. 요청은 먼저 Spring Security 필터를 지난다.
  3. JWT가 있으면 서버가 토큰을 검증한다.
  4. 검증 결과로 Authentication 객체를 만든다.
  5. 인증 정보를 SecurityContext에 저장한다.
  6. 저장된 인증 정보를 바탕으로 인가를 수행한다.
  7. 권한이 맞으면 컨트롤러로 진입한다.
  8. 권한이 없으면 접근이 거부된다.

이 흐름을 이해하고 나니,
Spring Security는 단순히 로그인 기능을 붙이는 것이 아니라
요청의 입구에서 사용자 신원과 권한을 검증하는 보안 체계라는 점이 더 명확해졌다.


9. 오늘의 핵심 정리

  • 인증은 누구인지 확인하는 과정이다.
  • 인가는 무엇을 할 수 있는지 확인하는 과정이다.
  • 요청은 바로 컨트롤러로 가지 않고, 먼저 Security Filter를 거친다.
  • JWT 검증 결과로 Authentication 객체가 생성된다.
  • Authentication은 SecurityContext에 저장된다.
  • 이후 Spring Security는 이 정보를 바탕으로 인가를 수행한다.
  • URL 권한 설정은 경로 단위의 1차 방어선이다.
  • 메서드 권한 설정은 기능 실행 단위의 2차 방어선이다.
  • permitAll은 공개, hasRole은 역할 제한이다.

10. 느낀 점

이전에는 JWT 인증을 “토큰만 검사하면 끝나는 것”처럼 단순하게 생각했는데,
실제로는 그 이후에 Authentication 생성, SecurityContext 저장, 인가 처리까지 이어지는
하나의 보안 흐름으로 이해해야 한다는 점이 중요했다.

특히 “요청 → 필터 → 인증 정보 생성 → 저장 → 권한 확인 → 컨트롤러 진입”
이 순서를 머릿속에 넣어두면,
앞으로 Security 설정을 볼 때도 왜 이런 설정이 필요한지 훨씬 잘 이해할 수 있을 것 같다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.