Spring Expression Language(SpEL) 에 대해

2 분 소요

스프링 프레임워크에서 사용되는 SpEL 표현법에 대해 알아보고 사용 예제에 대해 정리해보았다.


SpEL : Spring Expression Language

개요

SpEL (Spring Expression Language) 는 런타임에서 객체에 대한 쿼리와 조작(querying and manipulating)을 지원하는 강력한 표현 언어이다.

타입 연산자
산술 +, -, *, /, %, ^, div, mod
관계 <, >, ==, !=, <=, >=, lt, gt, eq, ne, le, ge
논리 and, or, not, &&, ||, !
조건 ?:
정규식 matches

연산자

SpEL 표현식은 # 기호로 시작하며 중괄호로 묶어서 표현한다. #{표현식}

속성 값을 참조할 때는 $ 기호와 중괄호로 묶어서 표현한다. ${property.name}

아래와 같이 속성 값 참조는 표현식 안에서 사용이 가능하다.

#{${someProperty} + 2}

산술 연산자

앞서 표에 나와있는 기본적인 산술 연산자들을 지원한다.

@Value("#{19 + 1}") // 20
private double add;

@Value("#{2 ^ 10}") // 1024
private double powerOf;

@Value("#{(2 + 2) * 2 + 9}") // 17
private double brackets;

관계 및 논리 연산자

기본적인 관계, 논리 연산자 또한 지원한다.

@Value("#{1 == 1}") // true
private boolean equal;

@Value("#{!true}") // false
private boolean notTrue;

조건부(삼항) 연산자

조건에 따라 값을 주입할 때 사용하는 조건부 연산자를 지원한다.

또한, 삼항 연산자 구문을 단축하는 Elvis 연산자와 동일한 방법을 사용할 수 있다.

@Value("#{some.property != null ? some.perperty : 'default'}")
private String ternary;

@Value("#{some.property != null ?: 'default'}") // 위와 동일하게 null인 경우 default 주입
private String elvis;

정규식(Regex) 표현법

matches 를 이용하여 문자열에 정규식을 사용할 수 있다.

@Value("#{'100' matches '\\d+'}") // true
private boolean validNumericStringResult;

@Value("#{'100asdf' matches '\\d+'}") // false
private boolean invalidNumericStringResult;

List, Map 객체 참조

스프링 빈으로 생성된 객체의 List, Map 프로퍼티에 대해서도 표현식을 통해 참조가 가능하다.

@Component("membersHolder")
public class MembersHolder {
    private List<String> members = new ArrayList<>();
    private Map<String, Integer> membersAge = new HashMap<>();

    public MembersHolder() {
        members.add("devwithpug");
        members.add("John");

        membersAge.put("devwithpug", 24);
        membersAge.put("John", 30);
    }

    // Getter & Setter 생략
}

위와 같이 임의의 스프링 빈 객체를 생성하면 간단하게 참조할 수 있다.

@Value("#{membersHolder.members.size()}") // 2
private Integer numberOfMembers;

@Value("#{membersHolder.membersAge['devwithpug']}") // 24
private Integer age;

사용 예제

SpEL 이 강력한 표현 언어인 이유는 스프링과 호환되는 다양한 프레임워크에서 사용이 가능하기 때문이다.

간단한 사용 예제들을 정리해보았다.

SpEL in Thymeleaf

객체 프로퍼티 참조

<p th:text="${member.name}">name</p>

Enum 클래스 참조

아래와 같은 Enum 클래스를 Thymeleaf에서 참조해야 하는 경우

package test.my.enumclass

public enum Role {
    USER, MANAGER, ADMIN
}

SpEL을 통해서 Enum 클래스의 경로(패키지 포함)를 명시하면 Thymeleaf 에서 Enum 타입 연산이 가능하다.

<div th:if="${member.role == T(test.my.enumclass.Role).ADMIN}"></div>

변수, 텍스트 혼용

<태그 속성값=|표현식|>

속성 값을 주입할 때, 일반 텍스트와 서버에서 받아온 변수를 함께 사용하여 값을 정의할 수 있다.

<button type="button" 
        th:onclick="|location.href='@{/somepage/{id}(id=${member.id})}'|">somepage</button>

SpEL in Spring security

@Pre, @Post 어노테이션

@PreAuthorize, @PostAuthorize 어노테이션을 사용하여 메소드에 인가 정책을 적용하는 경우 SpEL 표현식으로 인가 정책을 정의한다.

@Controller
public class MyController {

    @GetMapping("/preAuthorize")
    @PreAuthorize("hasRole('ROLE_USER') AND principal.username == #account.username")
    public String preAuthorize(AccountDto account, Principal principal) {

        return "mypage";

    }

}

한가지 다른 점은 html에서 클라이언트를 통해 받아오는 객체 값# 기호를 통해 참조하며 기존 스프링 빈 객체 프로퍼티에 참조 할 때는 기호를 사용하지 않는다.

References

댓글남기기