* El이란?
- Expression language의 약자이며 jsp 2.0 스펙에 추가된 개념
- JSP 스크립트의 표현식을 대신하여 속성 값을 쉽게 출력하도록 고안된 언어
- 출력, 반복처리를 태그기반으로 제공
- 기존 Expression Tag(<%= %>) 대체 하여 값을 꺼낼 때 ${}로 표기한다.
4가지의 특성을 가지고 있다 .
값을 꺼내 쓰기에 앞서 아래의 4가지 범위가 있다.
Application scope > Session scope > Request scope > Page scope
위의 범위는 영역이 큰 순부터 작은 순으로 이루어져있다.

동일한 변수명의 다른 값을 가진 변수가 있고, 동일한 스코프의 범위 안에 존재할 때 더 좁은 범위에 있는 값을 가져올 수 있다는 특징이 있다.
예시로 page와 request 스코프 둘 다에 만족하는 어떠한 값이 존재할 때 , 더 좁은 범위인 page 스코프에 있는 값을 가져온다 .
아래의 예시
1) jsp 화면
//el. jsp 화면 최상단
<%
// 페이지에서만 사용하는 변수는 지역변수이고 스코프 취급을 하지 않음
String data1="페이지 데이터입니다.";
// 따라서 pageContext를 통해서 스코프에 추가를 해야함
pageContext.setAttribute("data1", data1); // 페이지 영역에 데이터 추가
%>
// el.jsp 화면을 나타내는 부분
<h3>el scope attribute 다루기 </h3>
- el은 문자열이지만 숫자 형식이라면 자동으로 형변환을 하여 연산을 한다. <br>
${requestScope.data1}10<br> <!-- 스코프를 생략하면 무조건 좁은 범위의 스코프가 선택이 된다. -->
${data1}<br> <!-- 스코프를 생략하면 무조건 좁은 범위의 스코프가 선택이 된다. -->
${pageScope.data1}<br> <!-- 스코프를 생략하면 무조건 좁은 범위의 스코프가 선택이 된다. -->
${data2}<br>
${vo.title}<br>
위에서 , ${data1}의 결과는 requestScope와 pageScope중 더 좁은 범위인 pageScope 에 해당하는 문자열인 "페이지 데이터입니다" 가 출력이 됨.
위의 코드를 통해 스코프의 범위에 따라 값이 어떻게 나오는지 화면을 통해 알 수 있다 .
2) 컨트롤러
package edu.springMVC.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import edu.springMVC.vo.BoardVO;
@Controller
public class ElJSTLController {
@RequestMapping(value="/el.do")
public String el(Model model) {
model.addAttribute("data1","10");
model.addAttribute("data2",10);
BoardVO vo = new BoardVO();
vo.setTitle("제목입니다.");
model.addAttribute("vo",vo);
BoardVO vo2 = new BoardVO();
vo2.setTitle("안녕하세요. 반갑습니다..");
vo2.setPassword("1234");
vo2.setWriteDate("2024-11-19");
vo2.setWriter("홍길동");
vo2.setContent("첫 번재 게시글을 작성해요 하하하 ");
// request.setAttribute("details", vo2)와 같음
model.addAttribute("details", vo2);
// 위 details 안에 들어있는 객체의 데이터를 el.jsp 맨 아래 전부 각 필드값을 출력하세요
return "el";
}
}
3) controller에서 details객체의 값을 가져오는 화면
<hr />
${details.title}<br>
${details.password}<br>
${details.writer}<br>
${details.writeDate}<br>
${details.content}<br>
기존 jsp와는 다르게 el에서는 스크립틀릿 <%=%>을 사용하지 않고 ${}를 통해서 해당 키의 값을 바로 찍어낼 수 있는 것을 알 수 있다.
또한 controller에 담아놓은 키를 이용해서 , el태그를 사용하면
해당 객체의 값을 가져올 수 있다.

위의 el 리터럭 식을 보면 null 은 el 사용시 null로 표시되는게 아니라 빈 문자열로 표시가 되는 것을 알 수 있다 .
* JSTL이란?
- 반드시 라이브러리가 있어야함
- pom.xml에 jstl 라이브러리가 있어야 사용이 가능함
- 스프링 프레임워크에서는 JSTL 라이브러리를 제공함
- jstl을 사용하려면 태그립이 필요함
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
위의 코드는 접두어를 나타내는 태그립 ( c로 시작한다는 의미 )
이때 접두어를 나타내는 태그립은 prefix의 값을 바꿀 수 있지만 잘 바꾸지 않음
*jstl을 사용하여 영역별 속성(attribute) 선언하기
jstl에서 키를 지정하는 속성은 var , 값을 지정하는 속성은 value이다.
<h2> jstl을 배워보자 </h2>
<h2> jstl을 사용하여 영역별 속성(attribute) 선언하기</h2>
<!-- 키를 지정하는 속성 > var , 값을 지정하는 속성 value -->
<!-- pageContext.setAttribute("name","홍길동")과 같다고 볼 수 있음 -->
<c:set var="name" value="홍길동"/>
${name}<br>
해당 코드를 통해 <c: set을 선언 후
var로 지정된 키인 name을 el 태그 ( ${} )를 이용해서 키의 값인 홍길동이 출력되는 걸 볼 수 있다.

*jstl에서 scope을 지정하기
다음은 해당하는 키가 applicationScope, sessionScope,requireScope,pageScope 4개의 영역에서 어디에 존재하는지
확인 하는 코드이다.
<%@ taglib url="http://java.sum.com/jsp/jstl/core" prefix="c" %> <!-- 태그립 선언-->
<!-- request.setAttribute("id","honghong") -->
<c:set var="id" value="honghong" scope="request"/> <!-- scope > 영역을 지정 -->
${id}<br>
${requestScope.id}<br> <!-- requestScope영역에 존재하는 걸 알 수 있음 -->
위에서 마찬가지로 속성을 선언할 때 <c:set을 사용하고 해당하는 var(키)와 value(값)을 선언하는걸 알 수 있다.
*jstl에서 el태그 사용하기
<c:set var="sum" value="10+20"/>
${sum } <br> <!-- 더하는 값이 아닌 문자열 형태로 출력 -->
위의 코드에서 value를 "10+20"으로 선언 후 el태그를 활용해 ${sum}을 출력하게 되면 30이 아닌 문자열 10+20이 출력된다.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!-- 태그립 선언 -->
<!-- value 속성에 el을 사용하게 되면 연산의 결과 값을 대입할 수 있다. -->
<c:set var="sum" value="${10+20}"/>
${sum } <br> <!-- 더하는 값이 아닌 문자열 형태로 출력 -->
따라서 문자열이 계산한 값을 갖고 오고 싶은경우 value에 el 태그를 사용한 value="${10 +20}"의 형태로 작성을 하면 값은
10+20이 아닌 30을 화면에 보여주게 된다.

이처럼 <c: set var ="sum" value="${계산식}" />의 형태로 작성 후 el 태그로 ${sum}을 출력하면 계산식의 결과가 나오는 걸 알 수 있다.
*jstl에서 attribute 제거하기
<h3> attribute 제거하기 </h3>
<!-- 특정 스코프를 지정하지 않으면, 모든 영역의 sum을 제거함 -->
<c:remove var="sum"/>
${sum }<br>
위의 코드는 sum이 존재하는 스코프의 영역을 지정하지 않고 삭제한 경우에 var이 sum인 객체를 모두 삭제하는 코드이다.

위와 같은 경우 특정 scope에 존재하는 키 var를 삭제하지 않고 전체를 삭제하게 되는데
아래의 코드처럼 scope를 지정하게 된다면 특정 scope를 지정하여 삭제할 수 있다.
<!-- scope 지정시 해당 영역에서 일치하는 attribute 제거함 -->
<c:remove var="id" scope="page"/>
id : ${id}<br>
여기서 sum은 pageScope에 존재하지만, 이미 위에서 삭제를 했기 때문에 화면에는 아무것도 나오지 않는다.
*attribute 출력하기
여기서 attribue를 출력하는 코드가 있다.

46번째 라인의 html키에 value값을 작성후 el태그로 html을 출력하면 화면에 아래의 이미지처럼 나오는 걸 볼 수 있다.

위의 이미지에서 value 부분에는 html 태그가 먹히는 걸 볼 수 있다.
이때 누군가 악의적인 스크립트를 value 부분에 작성하면 스크립트가 작동이 된다는 보안적인 문제가 있기 때문에
<c: out value="${html}"/>을 작성하여 html 및 스크립트를 무력화 시킬 수 있다.

* if문 작성하기
아래의 코드를 보았을 때 , <c:if test="true"/> , <c:if test="false"/>를 모르고 얼핏 보면 true와 false가 둘 다 출력된다고 생각할 수 있다.
<h3> if문 작성하기</h3>
<c:if test="true">
true
</c:if>
<br>
<c:if test="false">
false
</c:if>
하지만 자바의 if문과 동일하다고 생각한다면 보다 보기 쉽다.
자바의 if 문에서는 조건문이 true일 때 실행문이 실행이 된다.
그처럼 위의 코드도 <c:if test="true" />일 때만 true가 실행이 된다.
또한 test="true" 대신 el식을 넣어서 표현 할 수 있다.
<!-- 로그인 x -->
<%-- <c:if test="${loginUser == null}" > --%>
<c:if test="${empty loginUser}" >
<a href="<%=request.getContextPath() %>/login.do">로그인 </a>
</c:if>
<!-- 로그인 o -->
<%-- <c:if test="${loginUser != null}"> --%>
<c:if test="${not empty loginUser}" >
<a href="<%=request.getContextPath() %>/mypage.do">마이페이지</a>
</c:if>
위의 코드는 test="true"부분에 el 태그를 이용해서 식을 대입한 내용이다.
empty loginUser 는 loginUser 객체가 비어있을 때 true를 반환하고 , loginUser == null 또한 loginUser가 참조할 수 있는게 없기 때문에, 둘 다 해당 객체에 아무것도 없다는 이야기가 되므로
여기서 loginUser == null과 empty loginUser는 같은 의미이다.
*switch-case문 작성하기
아래는 jstl의 switch-case 문이다.
<h3> switch문 사용하기 </h3>
- jstl에서는 else if 문법은 없으므로, switch문을 사용하여 표현한다.<br>
- choose 태그 안 when의 test 속성이 최초 true인 태그 안의 실행문이 실행된다.<br>
- when이 모두 false인 경우는 otherwise 태그 안의 실행문이 실행된다.<br>
<!--
switch(변수 or 식){
case 값 : ...
}
-->
<!-- true와 false의 연산을 위해 test안에 el 태그를 사용할 수 있다. -->
<c:choose>
<c:when test="true">
true1
</c:when>
<c:when test="true">
true2
</c:when>
</c:choose>
<br>
<c:choose>
<c:when test="${loginUser != null}">
<a href="<%=request.getContextPath() %>/mypage.do">마이페이지</a>
</c:when>
<c:otherwise>
<a href="<%=request.getContextPath() %>/login.do">로그인 </a>
</c:otherwise>
</c:choose>
위의 코드를 실행하면

위의 이미처럼 true1을 반환하는 것을 알 수 있다 .
<c:choose>
<c:when test="true">
true1
</c:when>
<c:when test="true">
true2
</c:when>
</c:choose>
의 결과는 true1과 true2가 모두 출력될 수 있다고 생각하지만 일 수 있다고 생각 할 수 있다.
하지만
JSTL <c:choose> 태그의 동작 원리는
if-else if-else 구조와 유사하며, 첫 번째로 조건이 true인 <c:when> 블록만 실행된다.
즉, <c:choose> 내에서는 단 한 개의 <c:when> 블록만 실행되도록 설계되어 있기 때문에, true1만 나오게 된다.
또한 <c:when>블록과 일치하는 경우가 없는경우 <c:otherwise>가 실행이 된다(switch-case문의 default 느낌).
* 반복문 사용하기
<h3>반복문 사용하기</h3>
-forEach 태그 사용하여 반복문 실행 <br>
<!-- begin 시작 end 끝 step 증감연산자 역활 -->
<c:forEach begin="1" end="10" step="2" var="count">
반복${count} <br>
</c:forEach>
jstl에서 반복문을 사용하는 코드는 <c forEact begin="시작값' end="끝 값" step="건너뛰는 숫자 " var="x번째 반복을 알려주는 값"
따라서 위의 코드를 보고 알 수 있는 내용은
반복을 줄바꿈하여 1부터 10번 화면에 찍을 내용인데 이때 , var을 통해 count의 값을 알려준다 .

// 객체를 이용한 반복문 작성해야함 (미완성)
controller에서 map의 형태로 "members" : members를 받았다고 가정했을 때 , 클라이언트에서 해당 객체의 정보를 반복문을 통해 가져올 수 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib url="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!-- 태그립 선언 -->
<html>
<head>
</head>
<body>
<!--여러 사용자를 담은 컬렉션 (users)인 경우 -->
<!-- <c:forEach를 사용할 경우에는 반복할 컬렉션인 items와
각 요소를 저장할 변수 이름인 var 속성이 필요함 -->
<c:forEach var= user items="${users}" >
이름 : ${user.name) <br/>
아이디 : ${user.id) <br/>
나이 : ${user.age) <br/>
</c:forEach>
<!-- 단일 사용자를 담은 단일 객체인 경우 -->
<c:if test="${loginUser != null}" >
이름 : ${loginUser.name} <br/>
아이디 : ${loginUser.id}<br/>
나이 : ${ginUser.age}<br/>
</c:if>
</body>
</html>
'스프링' 카테고리의 다른 글
| [Spring] file 업로드 시에 발생하는 오류 (0) | 2025.02.16 |
|---|---|
| [Spring] Logger 오류 시도 (0) | 2025.02.16 |
| [Spring] Spring MVC 프로젝트 생성 시 발생하는 오류 (0) | 2025.02.12 |
| [Spring] @RestController , @RequestBody, @ResponseBody (0) | 2025.02.06 |
| [Spring] ResponseEntity (0) | 2025.02.06 |