EL(Expression Language)이란?
Expression Language(표현 언어)는 값을 표현하는 데 사용되는 스크립트 언어로, JSP의 기본 문법을 보완하는 역할을 한다.
JSP에는 Java 코드와 markup 요소들이 섞여있다. 그러다보니 프론트엔드 개발자, 디자이너들도 쉽게 볼 수 있는 코드에 대한 needs가 있었고, 프론트엔드와 백엔드 사이에 어떻게 하면 효율적으로 일들을 나눌 수 있을 것인가라는 고민이 있었다.
이를 위해 Java 코드보다 더 간단하고 직관적으로 사용할 수 있는 형태로 나온 것이 EL이다.
EL이 제공하는 기능들은 다음과 같다.
- JSP의 스코프(scope)에 맞는 속성 사용
각 scope의 변수들을 손쉽게 사용할 수 있다.
- (Framework에서 제공하는)집합 객체에 대한 접근 방법 제공
EL의 표현방법
사용하는 방법은, ${ expr } 과 같이 쓰면 된다.
<jsp:include page="/module/${skin.id}/header.jsp" flush="true" />
<b>${sessionScope.member.id}</b>님 환영합니다.
이런 식이다.
${ } 안의 있는 것들이 그대로 출력된다. JSP의 표현식과 같다고 생각하면 된다.
EL의 기본 객체(Implicit Object)
EL의 기본 객체들은 다음과 같다.
EL의 기본 객체 사용 예시
EL의 데이터 타입
EL에서도 다양한 데이터 타입들을 다룰 수 있다.
- 불리언 타입 - true와 false
- 정수타입 - 0~9로 이루어진 정수 값 음수의 경우 '-'가 붙음
- 실수타입 - 0~9로 이루어져 있으며, 소수점('.')을 사용할 수 있고, 3.24e3과 같이 지수형으로 표현 가능하다.
- 문자열 타입 - 따옴표( ' 또는" )로 둘러싼 문자열. 만약 작은 따옴표(')를 사용해서 표현할 경우 값에 포함된 작은 따옴표는 \' 와 같이 \ 기호와 함께 사용해야 한다.
- \ 기호 자체는 \\ 로 표시한다.
- 널 타입 - null
객체 접근 규칙
- 표현 1이나 표현 2가 null이면 null을 반환한다.
- 표현1이 Map일 경우 표현2를 key로한 값을 반환한다.
- 표현1이 List나 배열이면 표현2가 정수일 경우 해당 정수 번째 index에 해당하는 값을 반환한다.
만약 정수가 아닐 경우에는 오류가 발생한다. - 표현1이 객체일 경우는 표현2에 해당하는 getter메소드에 해당하는 메소드를 호출한 결과를 반환한다.
EL의 연산자
수치 연산자
+ : 덧셈
- : 뺄셈
* : 곱셈
/ 또는 div : 나눗셈
% 또는 mod : 나머지
숫자가 아닌 객체와 수치 연산자를 사용할 경우 객체를 숫자 값으로 변환 후 연산자를 수행 : ${"10"+1} → ${10+1}
숫자로 변환할 수 없는 객체와 수치 연산자를 함께 사용하면 에러를 발생 : ${"열"+1} → 에러
수치 연산자에서 사용되는 객체가 null이면 0으로 처리 : ${null + 1} → ${0+1}
비교 연산자
== 또는 eq
!= 또는 ne
< 또는 lt
> 또는 gt
<= 또는 le
>= 또는 ge
문자열 비교: ${str == '값'} str.compareTo("값") == 0 과 동일
논리 연산자
&& 또는 and
|| 또는 or
! 또는 not
empty 연산자, 비교선택 연산자
연산자 우선순위
- [] .
- ()
- - (단일) not ! empty
- * / div % mod
- + -
- < > <= >= lt gt le ge
- == != eq ne
- && and
- || or
- ? :
EL을 비활성화(무시)하도록 JSP 안에 옵션을 줄 수도 있다.
<%@ page isELIgnored = "true" %>
또한 Servlet의 버전에 따라 EL의 지원 여부가 달라지니 확인해야 한다. (2.5부터는 기본적으로 지원)
https://docs.oracle.com/cd/E19316-01/819-3669/bnaic/index.html 참조
EL을 활용한 간단한 예제를 살펴보자.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%
pageContext.setAttribute("p1", "page scope value");
request.setAttribute("r1", "request scope value");
session.setAttribute("s1", "session scope value");
application.setAttribute("a1", "application scope value");
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
pageContext.getAttribute("p1") : <%=pageContext.getAttribute("p1") %><br>
pageContext.getAttribute("p1") : ${pageScope.p1 }<br>
request.getAttribute("r1") : ${requestScope.r1 }<br>
session.getAttribute("s1") : ${sessionScope.s1 }<br>
application.getAttribute("a1") : ${applicationScope.a1 }<br>
pageContext.getAttribute("p1") : ${p1 }<br>
request.getAttribute("r1") : ${r1 }<br>
session.getAttribute("s1") : ${s1 }<br>
application.getAttribute("a1") : ${a1 }
</body>
</html>
상단의 scriptlet에서 각 scope의 객체를 set하고, body 태그 안에서 attribute를 얻어와서 출력하고 있다.
주목할 것은 EL 안에서 각각의 scope를 지정해서 출력해도 되고, "p1", "r1"과 같이 그냥 이름만으로 출력해도 여기서는 결과가 똑같다. 하지만 코드를 명확하게 나타내기 위해서, scope를 확실하게 명시해주는 것이 더 좋다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%-- isELIgnored를 true로 지정하면 EL로 인식하지 않고 ${ } 그대로 출력 --%>
<%@ page isELIgnored="false" %>
<%
request.setAttribute("k", 10);
request.setAttribute("m", true);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
k : ${k }<br><br>
k + 5 : ${k + 5 }<br>
k - 5 : ${k - 5 }<br>
k * 5 : ${k * 5 }<br>
k / 5 : ${k div 5 }<br>
k : ${k }<br>
m : ${m }<br><br>
k > 5 : ${k > 5 } <br>
k < 5 : ${k < 5 } <br>
k <= 10 : ${k <= 10 } <br>
k >= 10 : ${k >= 10 } <br>
m : ${m } <br>
!m : ${!m } <br>
</body>
</html>
이 코드는 EL의 각종 연산자를 사용한 결과를 출력한다.
JSTL이란?
JSP 파일 안에 HTML 문법과 Java 문법이 섞여 있는 상태에서는, 태그에 익숙한 프론트 개발자들은 코드를 읽기가 불편하다는 문제점이 있었다. 이를 해결하기 위해 등장한 것이 JSTL(JSP Standard Tag Library)이다. 어차피 Servlet에서 로직과 관련된 부분을 수행하고, JSP는 결과를 출력만 하면 되기 때문에, JSP 파일 내에서 Java 코드로 수행되는 부분(조건문, 반복문 등)을 HTML 태그 형태로 사용할 수 있다면 어쩌면 그것이 더 적절한 선택일 수 있겠다.
JSTL을 사용하려면,
http://tomcat.apache.org/download-taglibs.cgi로 이동해서, 다음과 같이 3개의 파일을 WEB-INF > lib 폴더 내에 넣어줘야 한다.
단, 탐색기가 아닌 Eclipse 내에서 붙여넣기 해야 인식한다.
JSTL에서 제공하는 태그들의 종류에는 다음이 있다.
지금은 일단 코어 태그 중심으로 알아보도록 한다.
1) set, remove
set을 이용해 변수를 생성하고, remove로 제거할 수 있다. set 태그 내에서 var 속성으로 변수를 지정하고, scope 속성, value(값) 속성도 직접 정할 수 있다.
이제 set과 remove을 활용한 아주 간단한 예제를 살펴 보자.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="value1" scope="request" value="Kim"></c:set>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
성: ${value1 }<br>
<c:remove var="value1" scope="request"/>
성: ${value1 }<br>
</body>
</html>
<c:set>으로 request scope 안에 변수를 만들고, 출력에 사용한뒤 <c:remove>로 제거까지 해보았다.
2) set(변수 지원 태그), if(흐름 제어 태그)
if 태그는 프로그래밍 언어의 if문과 유사하지만, else 역할을 하는 기능은 없다.
아래는 if를 활용한 예제 코드이다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%-- <%
request.setAttribute("n", 10);
%> --%>
<c:set var="n" scope="request" value="10"></c:set>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:if test="${n == 0 }">
n과 0은 같습니다.
</c:if>
<c:if test="${n == 10 }">
n과 10은 같습니다.
</c:if>
</body>
</html>
"n과 10은 같습니다."가 출력된다.
3) choose, when, otherwise
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
request.setAttribute("score", 90);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:choose>
<c:when test="${score >= 90 }">
A학점입니다.
</c:when>
<c:when test="${score >= 80 }">
B학점입니다.
</c:when>
<c:when test="${score >= 70 }">
C학점입니다.
</c:when>
<c:when test="${score >= 60 }">
D학점입니다.
</c:when>
<c:otherwise>
F학점입니다.
</c:otherwise>
</c:choose>
</body>
</html>
if-else의 기능을 수행한다고 보면 된다.
4) forEach
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
List<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
list.add("!!!!");
request.setAttribute("list", list);
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:forEach items="${list }" var="item" begin="1">
${item }
</c:forEach>
</body>
</html>
먼저 스크립트릿에서 List를 만들고, request에 저장해둔다. 그런 다음 forEach를 사용해 하나하나씩 출력하게 된다. 만약 begin 속성을 생략하면 "hello world !!!!"가 출력되고, begin을 1로 주면 "world !!!!"가 출력될 것이다.
5) import
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Hello Kim
먼저 jstlValue.jsp라는 파일 안에는 간단한 텍스트를 넣었다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:import url="http://localhost:8080/firstweb/jstlValue.jsp" var="urlValue" scope="request"/>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
${urlValue }
</body>
</html>
이제 jstl05.jsp에서 import 태그를 사용해 jstlValue.jsp를 읽어오게 된다. 만약 url 속성 안에 다른 웹페이지, 만약 "https://www.google.com"을 넣었다면, 구글 페이지가 나타난다.
만약 url에 넣을 parameter 값이 존재한다면, param 태그를 추가로 사용하면 된다.
6) redirect
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:redirect url="http://localhost:8080/firstweb/jstl05.jsp"/>
...
redirect 태그의 url 속성을 jstl05.jsp로 넣었다. 따라서 jstl05.jsp로 redirect된다. JSP 파일 생성시 기본적으로 딸려오는 하단의 코드들은 어차피 수행되지 않으므로, 없어도 상관없다.
7) out
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:set var="t" value="<script type='text/javascript'>alert(1);</script>" />
<c:out value="${t }" escapeXml="false"/>
</body>
</html>
set 태그 안에 t라는 변수의 value를 지정했다. JavaScript로 alert을 띄워주는 코드다.
out 태그에서 escapeXml 속성을 true(default값)로 두면, t의 value가 그대로 텍스트로 페이지에 출력된다. false로 해야만 alert 창이 뜨게 된다.
참고자료
Expression Language (EL) in JSP
JSTL Quick Reference
댓글