⭐ SpEL(Spring Expression Language)이란?
Spring Expression Language(SpEL)은 Spring 프레임워크에서 제공하는 강력한 표현식 언어로, 객체의 값을 동적으로 평가하거나 조작할 수 있는 기능을 제공합니다.
즉, 코드 실행 중에 객체 내부의 값이나 속성에 접근하거나, 그 값을 변경할 수 있습니다.
이 기능은 프로그램이 실행되는 동안에 필요한 값을 실시간으로 계산하거나, 조건에 맞게 값을 업데이트할 수 있게 해줍니다. 이를 통해 코드에서 미리 정해진 값을 사용하는 것이 아니라, 상황에 맞게 값을 유연하게 조작할 수 있는 것입니다.
사실 SpEL이 없더라도 자바 코드만으로도 동적인 값 계산이나 조작이 가능하지만, SpEL의 장점은 표현식을 문자열로 작성해 동적인 평가를 할 수 있고, 이를 Spring 설정(XML, 애노테이션 등)이나 런타임 환경에서 쉽게 사용할 수 있다는 점입니다.
특히 Spring 같은 대규모 프레임워크에서 SpEL을 사용하면, 복잡한 로직을 간결하게 표현하고 관리할 수 있습니다.
이에 대해 더 알아가보록 하겠습니다!
⭐ SpEL의 필요성
SpEL(Spring Expression Language)의 필요성은 주로 Spring 프레임워크와의 통합 및 동적 표현식 처리를 통해 코드의 유연성을 높여주고, 간결성을 확보할 수 있다는 데 있습니다. SpEL이 필요한 이유를 좀 더 구체적으로 설명하면 아래와 같습니다.
✅ 설정 파일이나 애노테이션에서 동적 값 설정
자바 코드는 컴파일 후 정적으로 실행됩니다. 즉, 프로그램 실행 전에 모든 값이나 로직이 고정되어 있습니다. 하지만 SpEL은 런타임에 표현식을 평가할 수 있어, 실행 중에도 동적으로 값이나 로직을 결정할 수 있습니다.
@Value("#{systemProperties['user.name'] ?: 'Guest'}")
private String userName;
이 코드는 시스템 속성에서 user.name 값을 가져오고, 값이 없으면 'Guest'라는 기본값을 설정합니다.
SpEL을 사용하면 설정 파일이나 애노테이션에서 코드 없이 이런 값을 동적으로 결정할 수 있어 매우 유연합니다.
SpEL을 사용하지 않고 애노테이션에서 값을 설정하는 일반적인 방식으로 @RequestMapping에서 경로 설정하는 걸 예로 들 수 있을 거 같습니다.
@RequestMapping("/users")
public String getUsers() {
return "users";
}
이 예시는 "/users" 경로에 대한 요청을 처리하는 메서드를 정의한 것입니다. 이 경로는 고정된 문자열로, 동적으로 변경되지 않습니다.
애노테이션은 주로 컴파일 타임에 처리되는 메타데이터입니다. 그래서 런타임에 동적으로 값을 계산하거나 설정하는 작업은 기본적으로 할 수 없습니다.
이러한 애노테이션의 정적 특성 때문에 SpEL 없이 애노테이션에서 동적으로 값을 처리하는데에 어려움이 존재합니다.
반면, SpEL을 사용하면, 위의 시스템 속성에서 user.name를 가져오는 코드에서 볼 수 있듯이 런타임에 값을 계산하거나 외부 값을 참조하는 등 동적인 처리가 가능해져서 Spring 애플리케이션의 유연성을 크게 높일 수 있습니다.
✅ Spring의 여러 기능과 통합 가능
Spring은 거대한 생태계를 가지고 있습니다. SpEL은 다양한 Spring 모듈과의 원활한 통합을 제공하여, 복잡한 로직을 더 간단하게 처리할 수 있게 합니다.
예시 1️⃣ Spring Security에서의 SpEL
Spring Security에서 SpEL을 사용하여 보안 규칙을 유연하게 정의할 수 있습니다.
@PreAuthorize("hasRole('ADMIN') and #user.name == authentication.name")
public void secureMethod(User user) {
// 관리자이면서, 사용자 이름이 현재 인증된 사용자와 동일할 때만 접근 가능
}
이 코드는 SpEL을 통해 사용자의 권한과 이름을 확인한 후에 메서드에 접근할 수 있는지 결정합니다.
코드 작성 없이 표현식을 통해 보안 로직을 정의할 수 있어 간결하고 유연합니다.
예시 2️⃣ Spring Data에서의 SpEL
Spring Data JPA에서는 쿼리 메서드에서 동적으로 쿼리를 생성할 때 SpEL을 활용할 수 있습니다.
@Query("SELECT u FROM User u WHERE u.age > :#{#minAge}")
List<User> findUsersOlderThan(@Param("minAge") int minAge);
이 코드는 쿼리에서 minAge 파라미터를 SpEL을 사용해 동적으로 처리합니다
SpEL이 없으면 Spring의 유연한 기능을 충분히 활용하기 어려워집니다.
✅ 코드와 설정의 분리
SpEL은 코드에서 직접 로직을 처리하지 않고, 설정 파일이나 애노테이션에 표현식을 작성하여 로직을 처리할 수 있습니다. 이로 인해 코드와 설정이 분리되어 코드가 더 깔끔해지고 유지보수하기 쉬워집니다.
<bean id="person" class="com.example.Person">
<property name="age" value="#{20 + 5}"/>
</bean>
XML 설정 파일에서 나이에 20 + 5를 계산하는 표현식을 넣어 실행 시 계산되도록 할 수 있습니다. 코드 없이 설정 파일에서만 값을 조작할 수 있으므로 코드가 더 깔끔해지고 유지보수가 쉬워집니다.
✅ 복잡한 로직을 간결하게 표현
SpEL은 표현식을 사용해 복잡한 로직을 간단하고 직관적으로 표현할 수 있습니다. 이를 통해 코드의 가독성이 높아지고, 유지보수가 쉬워집니다.
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("10 > 5 ? '맞습니다' : '아닙니다'");
String result = (String) exp.getValue();
System.out.println(result); // 출력: 맞습니다
이처럼 SpEL의 필요성은 Spring 프레임워크에서 유연한 설정과 동적 로직 처리를 가능하게 하여, 코드와 설정의 분리와 복잡한 로직의 간결한 표현을 돕는 데 있습니다. 이를 통해 Spring 애플리케이션은 더 유연하고 유지보수하기 쉬운 구조를 가질 수 있습니다.
⭐ SpEL 문법
SpEL(Spring Expression Language)은 표현식(Expression)을 사용해 객체의 값에 접근하거나 계산하는 문법을 제공합니다. SpEL을 사용한 코드는 보통 "#{...}" 형태로 작성되며, 이 안에 표현식을 정의합니다. SpEL 문법은 기본적으로 자바의 연산자와 유사하지만, 런타임에 동적 평가가 가능하다는 점이 차별점입니다.
@Value("#{10 + 20}") // 숫자 연산 (10 + 20)
private int sum; // 30
@Value("#{person.name}") // person 객체의 name 속성에 접근
private String name;
@Value("#{systemProperties['user.name'] ?: 'Guest'}") // 시스템 속성에서 user.name 값 가져오기
private String userName;
위 코드와 같이 리터럴 값(숫자, 문자열, 불리언 등의 기본 데이터)를 다룰 수도 있고,
객체의 메서드도 호출할 수 있고,
삼항 연산자와 같이 다양한 연산자를 지원합니다.
이외에도 다른 기능은 아래 주요 기능에서 바로 확인할 수 있습니다.
⭐ SpEL의 주요 기능
✅ 속성 접근
SpEL을 통해 객체의 필드나 메서드에 쉽게 접근할 수 있습니다.
public class Person {
private String name = "John";
public String getName() {
return name;
}
}
ExpressionParser parser = new SpelExpressionParser();
Person person = new Person();
Expression exp = parser.parseExpression("name");
String name = (String) exp.getValue(person);
System.out.println(name); // 출력: John
이 예제에서, Person 클래스의 name 필드에 SpEL을 사용해 접근하고 있습니다. Expression 객체에서 getValue() 메서드를 호출하여 객체의 속성 값을 가져올 수 있습니다.
✅ 리터럴 표현식
문자열, 숫자, 불리언 등의 값을 표현할 수 있습니다.
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello, SpEL!'");
String message = (String) exp.getValue();
System.out.println(message); // 출력: Hello, SpEL!
SpelExpressionParser를 통해 "Hello, SpEL!"이라는 문자열을 표현식으로 파싱하고, 이를 출력합니다.
✅ 연산자 사용
논리 연산, 산술 연산 등을 지원합니다.
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("10 + 20");
Integer result = (Integer) exp.getValue();
System.out.println(result); // 출력: 30
단순한 덧셈 연산을 표현식으로 파싱하여 계산 결과를 얻습니다.
✅ 메서드 호출
SpEL을 사용하면 객체의 메서드를 호출할 수도 있습니다.
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello, world!'.toUpperCase()");
String message = (String) exp.getValue();
System.out.println(message); // 출력: HELLO, WORLD!
문자열 객체의 toUpperCase() 메서드를 SpEL로 호출하는 예시입니다.
✅ 조건문
삼항 연산자 및 if-else와 같은 논리 조건문 지원합니다.
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("10 > 5 ? '맞습니다' : '아닙니다'");
String result = (String) exp.getValue();
System.out.println(result); // 출력: 맞습니다
✅ 컬렉션 처리
SpEL을 사용하면 배열, 리스트, 맵과 같은 컬렉션에 접근하거나 필터링할 수 있습니다.
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class SpelArrayExample {
public static void main(String[] args) {
ExpressionParser parser = new SpelExpressionParser();
// 배열 생성 및 접근
int[] numbers = {1, 2, 3, 4, 5};
Expression exp = parser.parseExpression("new int[]{1, 2, 3, 4, 5}[2]");
Integer value = (Integer) exp.getValue();
System.out.println("세 번째 요소: " + value); // 출력: 세 번째 요소: 3
}
}
위 코드는 SpEL을 사용해 배열 요소에 접근하는 방법입니다.
⭐ 실전에서 SpEL의 활용
SpEL은 단순히 표현식을 처리하는 기능뿐만 아니라, Spring 프레임워크 내에서 다양한 곳에서 활용됩니다.
1) Spring EL을 사용한 Bean 설정
XML 설정에서 SpEL을 사용하여 값을 동적으로 설정할 수 있습니다.
<bean id="bean1" class="com.example.MyBean">
<property name="value" value="#{10 + 20}"/>
</bean>
위 설정에서는 SpEL을 이용해 value 속성에 30이 할당됩니다.
2) @Value 애노테이션에서 SpEL 사용
Spring의 @Value 애노테이션에서 SpEL을 사용하여 속성 값을 주입할 수 있습니다.
@Value("#{systemProperties['user.name']}")
private String userName;
이 코드는 시스템 속성 중 user.name 값을 userName 필드에 주입하는 예시입니다
3) 메서드 보안 처리
Spring Security에서는 메서드 권한 검사에 SpEL을 활용할 수 있습니다.
@PreAuthorize("hasRole('ADMIN') and #user.name == authentication.name")
public void secureMethod(User user) {
// 관리자이면서, 사용자 이름이 현재 인증된 사용자와 동일할 때만 접근 가능
}
🚩 결론
SpEL은 Spring 프레임워크 내에서 매우 유용하게 사용되는 표현식 언어로, 코드와 설정에서 복잡한 로직을 간결하게 표현할 수 있는 강력한 도구입니다.
초보자도 SpEL의 기본적인 사용법을 익히면, Spring의 다양한 기능을 더욱 효율적으로 활용할 수 있습니다.
저 또한, 앞으로 SpEL의 다양한 가능성을 실제 프로젝트에 적용하면서, 더 효율적이고 유연한 Spring 애플리케이션을 만들어보고 싶습니다! Spring Security에서의 권한 처리나 Spring Data JPA와의 통합 같은 고급 기능에서도 SpEL을 적극적으로 사용해 보고 싶습니다.
실습을 통해 익히다 보면 Spring의 다양한 구성 요소와의 통합을 자연스럽게 경험할 수 있을 것입니다. 앞으로 SpEL을 더욱 깊이 탐구하고, 그 잠재력을 최대한 활용할 계획입니다~!
📌 참고
'기술 지식 쌓아가기 📚 > Backend 🍔' 카테고리의 다른 글
[Spring] 스프링 MVC: 웹 개발의 기본, 쉽게 이해하기 🍃 (5) | 2024.09.22 |
---|---|
[Spring] 서블릿(Servlet)에 대해 알려드리겠송! 😼🍃 (3) | 2024.09.18 |
[Spring] 스프링 컨테이너란? 의존성 주입의 마법 🍃 (0) | 2024.09.15 |
[Spring] 스프링 빈(Bean)이란? 초보 개발자를 위한 쉬운 설명 🍃 (2) | 2024.09.13 |
[Spring] 제어의 역전(IoC)과 의존성 주입(DI) 완벽 이해하기 🍃 (4) | 2024.09.12 |