Spring & Java
Spring Security Context와 인증구조 및 실습 본문

Spring Security 가장 핵심이 되는 SecurityContext 개념과 인증 실습을 해보겠습니다.
SecurityContextHolder
SecurityContextHolder는 현재 쓰레드에서 인증된 사용자 ( Authentication 객체 )를
저장/조회 하는 Spring Security 핵심 저장소 입니다.
즉, 지금 로그인한 사용자가 누구인지를 저장하는 곳입니다.
인증 정보 저장 위치
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
커스텀 필터나 컨트롤러, 서비스 어디서든 SecurityContextHolder를 통해 인증 정보에 접근 가능
수동 저장 예시 (JWT 사용 시 )
SecurityContextHolder.getContext().setAuthentication(authentication);

위 컴포넌트를 가지고 jwt를 가지고 인증까지 해봅시다!
Spring Security ( + 인증까지 ) 실습
솔직히 어렵다고 말하진 않지만 지금까지 해보면서 느낀거는 인증/인가 같은 절차가 꽤나 복잡한건 사실인 것 같고 .. 제가 지금부터 하는 실습 연습은 현업에서 사용하는 필수적인 코드라고 생각이 들어서 꼭 절차를 기록하고 어떤 방식으로 코딩 했었는지 효율적이게 관리 하고, 학습 하기로 했습니다. 이질감이 들더라도 학습 내용에는 꼭 필요한 내용만 꽂아 넣었으니 참고 하시면 되겠습니다.

implementation 'org.springframework.boot:spring-boot-starter-security'
자 시작하겠습니다 우선 위 경로에 security 코드를 넣고 POSTMAN 호출을 해보도록 하겠습니다.

지금 포스트맨 호출 결과 401 에러가 나타났습니다 이 에러는 무슨 에러였는지 혹시 기억 하시나요 ? 401 에러는 인증이죠? 인증 절차에서 거부 당한것을 두눈으로 확인할 수 있었습니다.
우리는 로그인 정보를 SecurityContextHolder에 담기로 했습니다. 근데 지금은 아무런 로그인 정보가 안들어 있어서 이런 에러가 발생했다고 생각하면 아주 편하겠습니다.
그럼 이제 가장먼저 뭘 해야 될까요 ? SecurityFilterChain을 직접 등록 하면 됩니다.

config 셋팅 패키지를 만들고 거기에 저는 SecurityConfig 클래스를 만들었습니다. 기본 셋팅으로 Bean을 추가 해줘야 되는데 어떻게 하냐면

어노테이션 기봇 셋팅 값이라고 생각하면 아주 편합니다. 이것들이 있어야 Security가 정상 작동 하도록 하니까 꼭 참고해서 추가하시길 바랍니다.
이제부터 SecurityConfig를 설정 해볼까 합니다.
@Configuration
@RequiredArgsConstructor
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {
private final JwtFilter jwtFilter;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean // 자세하고 구체적이게 커스텀 필터 체인을 만들겁니다.
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable) // .csrf().disable() 방식은 더 이상 사용 안함.
.httpBasic(AbstractHttpConfigurer::disable) // BasicAuthenticationFilter 비활성화
.formLogin(AbstractHttpConfigurer::disable) // UsernamePasswordAuthenticationFilter, DefaultLoginPageGeneratingFilter 비활성화
.addFilterBefore(jwtFilter, SecurityContextHolderAwareRequestFilter.class)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/user/login").permitAll()
)
.build();
}
}
우선 코드는 이렇게 되어 있습니다. 조금 복잡해 보이긴 하는데 조금만 단순하게 생각하면 또 단순해지니까 너무 어렵게 생각할 필요 없습니다 결국 저희가 쓰는 코드는
.addFilterBefore(jwtFilter, SecurityContextHolderAwareRequestFilter.class)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/user/login").permitAll()
)
.build();
이정도 뿐이라고 생각하면 아주 간단하겠죠 ?
자 이렇게 값을 지정 했으니까 다음으로 어떻게 할 것인가 ?

User user = new User를 통해서 객체를 생성 할건데 아래 이미지를 꼭 보세요 User는 어떤 User를 쓰는게 맞는지 말이죠 User 객체는 Spring Security에서 제공하는 User 객체 입니다 제가 만든게 아니에요 꼭 참고하세요!
( 윈도우 기준 : 컨트롤 + b )

그럼 이렇게 나옵니다. 들어가 볼까요 ?

User에 접근 하니까 권한도 필요하고 뭐 필요하다는 말이 줄줄 있습니다. 저는 JWT 토큰을 쓰고 있죠 ? 그래서
비밀번호는 사용하지 않을거니까 지금은 username만 쓰도록 하겠죠 ? 권한은 그리고 아직 만들지 않아서 일단 넣지 않고 진행 할 겁니다.

전용 저장소 처음 말한거야!
SecurityContextHolder.getContext().setAuthentication
(new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()));
전용 저장소에다가 내가 토큰에서 뽑아온 값을 SecurityContextHolder에 넣어 주면 되는 겁니다.
권한도 추후에 넣어주고 다음 필터로 이동 하게 되면
.addFilterBefore(jwtFilter, SecurityContextHolderAwareRequestFilter.class)
방금 우리가 넣어줬던 정보를 SecurityContextHolderAwareRequestFilter 정보를 토대로 " 인가 " 처리를 해줄 예정입니다.
지금까지가 SecurityContextHolder에 관련된 인증 구조였습니다.
이제 실습을 한번 해볼까요 ? 지금 열려 있는곳이 아래 이미지니까 이대로 한번 테스트 해보고 마무리 하겠습니다.


와우 ! 토큰 값을 변경 시키지 않아도 괜찮았습니다 401 에러가 해결 됐거든요. 처음에 401 에러 떳던거 기억나시죠? 지금은 문제 없이 코드가 작동 하는 것을 확인할 수 있었습니다.
아! 참고로 하나 더 설명 드릴게 있습니다.
예를들어 우리가 다른 메서드로 접근을 한번 해볼까요 ?

어? 이놈은 왜 안뜨는걸까요? 403에러가 발생 했습니다. 이거 굉장히 쉽게 말씀 드릴게요.

여기 이미지에서 보시면 login만 허락이 된 상태인거에요 다른 url을 넣어 권한을 열어 넣으면 되겠죠 ?
살짝 쿵 맛보기로 하나 추가 해볼까요 그럼 ?

똑 같은 코드에 url만 바꿔 넣었어요 이러면 포스트맨은 과연 정상 작동을 할까요 ?

짜잔 토큰만 최신화로 바꿔주면 우리는 이제부터 인증 된 값만 호출 하도록 바꿀수 있게 됐습니다 어렵다면 어렵고 쉽다면 쉬운 인증이였는데 따라오기 편하도록 하나하나 상세하게 만들어 봤습니다.
Spring Security 에서 사용하는 SecurityContextHolder 값을 넣어주면서 전용 User 객체를 생성해서 User를 넣어준겁니다.
이제 어떤 사용자가 로그인 했는지 그 값만 있다면 알아서 처리 해줄겁니다.
오늘의 TIL
📌 날짜 : 2026 01 22
📌 주제 : SecurityContextHolder로 JWT 인증 흐름 만들기
✅ 학습한 내용
Spring Security에서 가장 핵심이 되는 SecurityContext 개념과, JWT를 이용해 인증을 직접 실습했습니다. 특히 Contorller/Service 단에서 인증을 처리하는 방식이 아니라, HTTP 요청이 Controller에 도달하기 전 (Filter단계)에서 JWT 토큰을 검증하고 인증 정보를 SecurityContextHolder에 저장하는 구조를 이해했습니다.
하지만, 완벽하게 숙달한 것이 아닌 이론을 파악하고 어떤 원리 구조로 작동 하는 것이 맞는지 그 흐름을 이해하는데 중점을 두고 실습을 했습니다.
🔍 핵심 개념 정리
SecurityContextHolder란?
SecurityContextHolder는 현재 쓰레드(Thread)에서 인증된 사용자 정보를 저장/조회하는 Spring Security의 핵심 저장소입니다. 즉,
“지금 로그인한 사용자가 누구인지”를 저장하는 공간.
실습 진행 내용 (Spring Security + JWT 인증)
1) Spring Security 의존성 추가 후 변화
implementation 'org.springframework.boot:spring-boot-starter-security'
추가하고 Postman 호출을 해보니 401 에러가 발생했다.
- 401은 인증(Authentication) 실패
- 즉, Security는 “로그인한 사용자 정보가 없으니 접근 불가”로 판단한 것이다.
2) 해결 방향: SecurityFilterChain 직접 등록하기
인증 흐름을 우리가 원하는 방식(JWT 기반)으로 만들기 위해
SecurityFilterChain을 직접 등록해야 했다.
그래서 config 패키지를 만들고 SecurityConfig를 생성했다.
3) SecurityConfig 구성 요소 이해
- Security가 정상 동작하기 위한 기본 설정 어노테이션을 추가했다.
- PasswordEncoder도 Bean으로 등록했다.
🔍 SecurityFilterChain 설정 코드
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.formLogin(AbstractHttpConfigurer::disable)
.addFilterBefore(jwtFilter, SecurityContextHolderAwareRequestFilter.class)
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/user/login").permitAll()
)
.build();
}
'심화 Spring > Spring Security' 카테고리의 다른 글
| Spring Security 개념 및 구조 (0) | 2026.01.22 |
|---|---|
| 인증 & 인가 개념 정리 (0) | 2026.01.22 |