우당탕탕
Spring Security 6 권한 설정, 이 부분부터 꼭 체크하세요 본문
Spring Security 6으로 마이그레이션하면서 권한 설정 부분에서 생각보다 삽질을 많이 했어요. 기존 버전과 달라진 점이 꽤 많아서, 그냥 대충 넘어가면 인증은 통과하는데 권한 체크가 엉망인 상황이 벌어지더라고요.
그래서 이번 글에서는 제가 직접 부딪히고 해결한 경험을 바탕으로, Spring Security 6에서 권한 설정할 때 꼭 확인해야 할 부분들을 ✅ 체크리스트로 정리해 드릴게요. 사실 이 글 하나만 잘 봐도 권한 관련 이슈는 거의 다 해결될 거예요.
개발 환경 / 버전 정보
이번 작업에 사용한 주요 버전은 Java 17, Spring Boot 3.1.2, 그리고 그에 맞춘 Spring Security 6.1.2입니다. 최신 릴리즈 정책에 맞춰서 보안 정책들도 강화된 상태라, 기존 방식으로 설정하면 막히는 부분이 많아요.
권한 설정, 이렇게 하면 됩니다
먼저 가장 기본적으로 많이 사용하는 HttpSecurity 설정 부분부터 살펴볼게요. Spring Security 6부터는 authorizeHttpRequests()가 기본인데, 중요한 건 권한 체크 메소드가 requestMatchers()를 반드시 먼저 써야 한다는 점이에요.
// Spring Security 6 권한 설정 예시
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
.formLogin(withDefaults())
.httpBasic(withDefaults());
return http.build();
}
위처럼 requestMatchers() 순서를 꼭 지켜야 하는데, 만약 anyRequest()를 먼저 쓰면 나머지 매칭이 무시되는 경우가 많아요. 그리고 권한 이름도 "ROLE_" 접두어를 안 붙여도 되고, 대신 내부적으로 붙여 처리해줘요. 그래서 hasRole("ADMIN")처럼 쓰면 됩니다.
권한 이름과 Prefix, 여기서 많이 틀립니다
이전 버전에서 직접 ROLE_ 접두어를 붙여서 권한을 관리했다면, Spring Security 6에서는 굳이 그렇게 하지 않아도 되죠. 그런데 혼동해서 권한 이름을 중복으로 붙이는 경우가 많더라고요.
예를 들어, hasRole("ROLE_ADMIN") 이렇게 쓰면 실제 역할은 ROLE_ROLE_ADMIN로 인식돼서 막히는 경우가 많아요. 그래서 저는 무조건 hasRole("ADMIN")처럼 쓰는 것을 권장합니다.
권한 검사 커스텀할 때도 꼭 확인할 점
그런데 여기서 끝이 아니에요. 저는 커스텀 권한 검사 메소드를 만들 때도 헷갈렸거든요. 예를 들어, 메소드 시큐리티에서 @PreAuthorize 쓰면 hasAuthority()나 hasRole() 안에 입력하는 권한 이름 체계가 다를 수 있어요.
Spring Security 6부터는 권한 검사도 일관되게 ROLE_ 접두어 없이 사용하는 게 좋고, 커스텀 권한 클래스를 만들면 반드시 GrantedAuthority를 올바르게 구현해야 해요.
커스텀 권한 리졸버 샘플 코드
public class CustomAuthority implements GrantedAuthority {
private final String authority;
public CustomAuthority(String authority) {
this.authority = authority;
}
@Override
public String getAuthority() {
// "ROLE_" 접두어 없이 권한명 리턴
return authority;
}
}
이렇게 하면 권한 체크 시 hasRole("ADMIN") 같은 형태로 쓸 때 충돌 없이 동작해요.
✅ 꼭 체크해야 할 권한 설정 체크리스트
- requestMatchers 순서: 가장 구체적인 매칭을 앞에 두고
anyRequest()는 제일 마지막에 써야 합니다. - hasRole 권한명 작성법: "ROLE_" 접두어 빼고 권한명만 넣기(예:
hasRole("USER")) - 커스텀 권한 클래스:
GrantedAuthority인터페이스를 구현할 때 반드시 권한명에 접두어를 안 붙여야 합니다. - 메소드 시큐리티 어노테이션:
@PreAuthorize등에서 권한 체크 시에도 동일한 권한명 규칙 지키기 - 테스트 시 권한 부여 확인: 권한 이름 매칭이 안 맞으면 인증 성공해도 권한 거부되니 꼭 로그 확인하기
여기서 삽질했던 부분들
실제로 제가 겪은 문제 중 하나가, requestMatchers()에서 anyRequest()를 먼저 써서 나머지 요청들이 무조건 인증 실패 처리됐던 거였어요. 로그를 봐도 이유를 못 찾아 한참 헤맸죠.
// 잘못된 예시
http.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
.requestMatchers("/admin/**").hasRole("ADMIN")
);
이렇게 하면 사실상 anyRequest()가 모든 요청을 차단하는 역할을 해버려서, 그 뒤에 있는 requestMatchers()는 무시되는 겁니다.
또 하나는 권한명을 "ROLE_" 붙여서 쓰면서 내부적으로 또 붙여서 중복되는 문제도 있었고요. 이런 작은 부분이 겹치니까 권한이 제대로 인식이 안 되더라고요.
심화: 이렇게 하면 권한 설정 더 편해집니다
추가로 권한 설정이 복잡한 프로젝트라면, 권한을 enum이나 상수 클래스로 관리하는 게 좋아요. 저도 이렇게 권한명을 직접 하드코딩하는 대신 enum으로 관리해서 오타 위험을 줄였거든요.
public enum UserRole {
ADMIN, USER, GUEST;
public String getRoleName() {
return name(); // ROLE_ 접두어는 붙이지 않음
}
}
그리고 권한 검사 시에는 hasRole(UserRole.ADMIN.getRoleName()) 처럼 사용하면, 오타를 걱정할 필요가 없어요.
자주 물어보시는 것들
Q. 기존에 "ROLE_" 붙여서 권한을 넣었는데, 이제 어떻게 바꾸는 게 좋을까요?
A. Spring Security 6에서는 내부적으로 hasRole("ADMIN")을 호출하면 "ROLE_ADMIN"으로 자동 변환해줘요. 그래서 사용자 권한 저장소(DB)에도 ROLE_를 붙인 상태로 유지하셔도 되지만, 권한 비교 시에는 hasRole에 접두어 없이 넣는 게 좋습니다.
Q. requestMatchers() 외에 권한 검사 방법이 있나요?
A. 네, 메소드 시큐리티(@PreAuthorize, @Secured 등)를 쓰면 URL이 아니라 메소드 단위로 권한을 관리할 수 있어요. 다만 이때도 권한명 체계는 일관되게 맞춰줘야 합니다.
Spring Security 6 권한 설정은 작은 문법 차이와 규칙 하나를 놓쳐도 서비스 중 권한 오류가 생길 수 있기 때문에, 제가 정리한 체크리스트대로 꼭 검증해보세요. 이렇게 하면 저처럼 한참 헤맬 일은 없을 겁니다. 관련해서 OAuth2, JWT 권한 처리도 비슷한 흐름이라 다음 글에서 다뤄볼게요.
'Tech > Spring' 카테고리의 다른 글
| Spring Boot Validation 커스텀 어노테이션 숫자 비교하며 만들어본 후기 (0) | 2026.06.18 |
|---|---|
| Spring Batch 처음 써보면서 비용 비교와 숫자 처리에서 막혔던 점들 (0) | 2026.06.18 |
| Spring Cloud Gateway 도입하면서 겪은 라우팅 문제와 해결 체크리스트 (0) | 2026.06.09 |
| Spring Boot에서 Querydsl 도입, 직접 해보고 정리한 절차와 팁 (0) | 2026.06.03 |
| Spring WebFlux 적용하다 헷갈렸던 개념들, 저랑 다르네요 (0) | 2026.06.01 |
