본문 바로가기

Spring Security

@PreAuthorize에서 상수(변수) 사용할 수 없는 이유

Spring Security에서 권한 검증을 위해 흔히 사용하는 애노테이션 @PreAuthorize.

보통 아래와 같이 사용한다.

@PreAuthorize("hasRole('ADMIN')")

그런데 이때 "ADMIN" 같은 문자열을 상수로 관리하고 싶어서 이렇게 바꿔보고 싶어진다.

const val ROLE_ADMIN = "ADMIN"
@PreAuthorize("hasRole(ROLE_ADMIN)") // 이렇게 쓰고 싶다!

하지만 이렇게 작성하면 애플리케이션 실행 중 예외가 발생한다.

SpelEvaluationException: EL1008E: Property or field 'ROLE_ADMIN' cannot be found


왜 안 될까?

@PreAuthorize 안에서 사용되는 표현식은 Spring Expression Language(SpEL)로 동작한다.

SpEL은 해당 표현식 안에서 Kotlin이나 Java의 상수, 변수, enum 등을 인식할 수 없다.

즉, 우리가 흔히 쓰는 다음과 같은 것들은 전부 사용할 수 없다.

  • const val로 정의한 문자열 상수
  • enum 값
  • companion object의 변수
  • object 혹은 class의 static 필드

SpEL은 단순한 문자열 표현식만 평가하기 때문에,

Java/Kotlin 코드 영역의 상수를 참조하려고 하면 그런 속성은 존재하지 않는다는 에러가 발생한다.


결론: 무조건 하드코딩해야 한다

// 이렇게만 가능
@PreAuthorize("hasAnyRole('ADMIN', 'CEO')")

아쉽지만 @PreAuthorize나 @PostAuthorize에서 사용할 권한 이름은 반드시 문자열로 직접 하드코딩해야 한다.


그럼 enum이나 const로 권한 이름 못 써?

  • 네. 해당 애노테이션 내부에서는 불가능합니다
  • 외부 로직(예: 서비스, 인증 처리 로직 등)에서는 자유롭게 사용 가능하지만,
  • @PreAuthorize("...") 안에서는 오직 문자열 리터럴만 허용됩니다

📌 요약

  • @PreAuthorize("hasRole(...)") 안에서 변수, 상수, enum 전부 사용할 수 없음
  • SpEL은 Java/Kotlin 상수에 접근할 수 없음
  • 반드시 "ADMIN", "CEO" 등 문자열로 하드코딩해야 함