이전글




표현 언어(EL)에서의 연산자 종류
표현언어(Expression Language)에서는 값 그자체를 출력하거나 특정 변수나 객체의 속성값을 표현할수도 있지만 특정 연산자를 통한 연산 결과 또한 출력할 수 있습니다. 다음 표는 표현언어 EL에서 사용 가능한 연산자를 표기한것입니다. 표를 보면 알 수 있지만 일부 연산은 평소에 사용하는 연산자 이외에 lt, gt 같은 키워드를 통한 연산이 가능합니다.
연산자 구분
연산자
설명
산술 연산자
+
덧셈
-
뺄셈
*
곱셈
/ or div
나눗셈
% or mod
나머지 연산
ex) 8 % 3 = 2
비교 연산자
== or eq
앞의 값이 뒤의 값과 같으면 true.
!= or ne
앞의 값이 뒤의 값과 다르면 true.
< or lt
앞의 값이 뒤의 값보다 작으면 true
> or gt
앞의 값이 뒤의 값보다 크면 true
<= or le
앞의 값이 뒤의 값과 같거나 작으면 true
>= or ge
앞의 값이 뒤의 값과 같거나 크면 true
논리 연산자
&& or and
논리곱(and) 연산
|| or or
논리합(or) 연산
! or not
부정(not) 연산
empty 연산자
empty <대상>
<대상>null 이거나 빈 문자열 또는 길이가 0배열이나 List 비어있는 MapCollection 객체인 경우 true를 리턴함.
비교 선택
연산자
<수식> ? <값1> : <값2>
앞의 <수식>true인 경우 <값1>false인 경우 <값2>를 리턴함.




EL 연산자 통합 테스트 예제
위의 연산자 표를 바탕으로 실제 EL 구문에서 어떤식으로 값들이 연산되는지 실습예제를 진행해보도록 하겠습니다. 코드는 아래와 같으며 전체 코드가 궁금하신분은 다음 GIT 주소를 참고 바랍니다.
<h1>산술연산자</h1>
\${1 + 2} : ${1 + 2} <br>
\${"1" + 2} : ${"1" + 2} <br>
\${"1" + "2"} : ${"1" + "2"} <br>
\${null + 2} : ${null + 2} <br>
<%-- \${"one" + 2} : ${"one" + 2}--%>
\${1 - 2} : ${1 - 2} <br>
\${10 * 3} : ${10 * 3} <br>
 
\${10 / 3} : ${10 / 3} <br>
\${10 div 3} : ${10 div 3} <br>
\${10 % 3} : ${10 % 3} <br>
\${10 mod 3} : ${10 mod 3} <br><br><br>
 
 
<h1>비교 연산자</h1>
\${10 == 10} : ${10 == 10} <br>
\${10 eq 10} : ${10 eq 10} <br>
\${'dololak' == 'dololak'} : ${'dololak' == 'dololak'} <br>
\${'dololak' eq 'dololak'} : ${'dololak' eq 'dololak'} <br>
 
\${10 != 9} : ${10 != 9} <br>
\${10 ne 9} : ${10 ne 9} <br>
 
\${'dololak' != 'dololak1'} : ${'dololak' != 'dololak1'} <br>
\${'dololak' ne 'dololak1'} : ${'dololak' ne 'dololak1'} <br>
 
\${3 < 10} : ${3 < 10} <br>
\${3 lt 10} : ${3 lt 10} <br>
 
\${10 > 3} : ${10 > 3} <br>
\${10 gt 3} : ${10 gt 3} <br>
 
\${3 <10} : ${3 <10} <br>
\${3 le 10} : ${3 le 10}<br>
 
\${10 >= 3} : ${10 >= 3} <br>
\${10 ge 3} : ${10 ge 3} <br><br><br>
 
 
<h1>논리 연산자</h1>
\${1==1 && "dololak"=="dololak"} : ${1==1 &&  "dololak"=="dololak"} <br>
\${1==1 and "dololak"=="dololak"} : ${1==1 and  "dololak"=="dololak"} <br>
 
\${1==1 || 1!=1} : ${1==1 || 1!=1} <br>
\${1==1 or 1!=1} : ${1==1 or 1!=1} <br>
 
\${!true } : ${!true } <br>
\${not false } : ${not false } <br><br><br>
 
 
<h1>empty 연산자</h1>
<%
    String emptyValue = null;
    String emptyStr = "";
    Object[] emptyArr = new Object[0];
    List<String> emptyList = new ArrayList();
    Map<String, Object> emptyMap = new HashMap();
%>
\${empty emptyValue} : ${empty emptyValue} <br>
\${empty emptyStr} : ${empty emptyStr} <br>
\${empty emptyArr} : ${empty emptyArr} <br>
\${empty emptyList} : ${empty emptyList} <br>
\${empty emptyMap} : ${empty emptyMap} <br><br><br>
 
<h1>비교 선택 연산</h1>
\${10 == 10 ? 2000 : 3000 } : ${10 == 10 ? 2000: 3000 }
cs










산술 연산자
앞의 예지를 바탕으로 산순 연산자부터 보도록 하겠습니다. 결과는 다음과 같습니다. 덧셈, 뺄셈, 곱셈, 나눗셈 일반 Java의 연산자와 역할이 같으며 다른점은 divmod 키워드를 사용 가능하다는 점입니다.




산술연산에서의 null값
산술연산에서 null이 있는 경우 내부적으로 Long타입 0으로 바꾸어 연산합니다. 따라서 다음값은 2 입니다.
${null + 2}
cs



덧셈에서의 문자열이 있는 경우
일반적으로 Java 문법에서의 문자열 더하기 연산은 문자열이 합쳐지는것이 정상이지만 EL에서는 문자열숫자로 바꾸어 연산합니다. 따라서 다음값은 3입니다.
${"1" + 2}
cs

추가적으로 문자열 더하기 연산시 특정 문자열을 숫자로 변경이 불가능한 경우 NumberFormatException이 발생합니다.
${"one" + 2} //NumberFormatException 발생
cs

다만 EL 3.0부터는 스펙이 변경되어 문자열 연결 연산이 가능합니다. EL 3.0 버전은 Tomcat을 기준으로 Tomcat8부터 지원하므로 테스트 환경이 Tomcat8 이상인 경우 문자열 더하기 연산이 가능합니다.




EL에서 덧셈, 곱셈, 뺄셈 알고리즘
EL에서  ${A + B}, ${A - B}, ${A * B}일때 처리 알고리즘은 다음과 같습니다. 순서상 1번에 해당되지 않으면 2번을 2번에 해당되지 않으면 3번을 수행하는 식입니다.

  1. A와 B가 null인 경우 java.lang.Long타입 0값으로 계산합니다.
  2. A나 B 둘 중 하나가 java.math.BigDecimal이면 다른 하나를 BigDecimal로 변환하여 계산합니다. 덧셈, 뺄셈, 곱셈인 경우 각각 add(), substract(), muliply()를 사용하여 계산합니다.
  3. A나 B 둘 중 하나가 실수인 경우이거나 실수(Float, Double, BigDecimal)에 해당하는 문자열인 경우 다른 하나도 실수로 바꾸로 계산합니다.
    1. 다른 하나가 java.math.BigInteger이면 BigDecimal로 변환한 뒤 계산합니다.
    2. 다른 하나가 BigInteger가 아니면 모두 Double로 변환한 뒤 계산합니다.
  4. A나 B가 BigInteger이면 둘 다 BigInteger로 변환하여 계산합니다.
  5. 1 ~ 4번까지의 조건이 모두 아닌 경우 A와 B를 모두 Long으로 변환한 뒤 계산합니다.
  6. 변환이나 계산이 불가능한 경우 예외가 발생합니다.




EL에서 나눗셈 알고리즘
앞선 결과에서  ${10 / 3}의 결과가 3.333....인것을 볼 수 있습니다. 일반적으로 Java에서 정수끼리의 연산 결과는 정수여야 하지만 EL에서의 나눗셈 연산은 ${A / B} 일때 다음의 규칙적인 순서를 가지고 처리되므로 결과가 다르게 나타납니다.

  1. A나 B가 null인 경우 java.lang.Long타입 0값으로 계산합니다.
  2. A나 B가 Float, Double 또는 실수 형태의 문자열인 경우 A, B 둘 다 Double로 변환하여 계산합니다.
  3. A나 B가 BigInteger이면 둘 다 BigInteger로 변환한 후에 A.remainder(B)를 실행하여 계산합니다.
  4. 1 ~ 3번에 해당 사항이 없다면 A와 B를 Long으로 변환 후 계산합니다.
  5. 변환이나 계산이 불가능한 경우 예외가 발생합니다. 

앞의 결과는 2번에 해당되어 실수로 계산되었습니다.






비교 연산자
비교연산자의 경우 크게 특별한점은 없습니다. 다만 문자열 연산에서 ==eq키워드 !=ne키워드가 사용 가능하다는 점과 내부적으로 String클래스의 compareTo() 메서드를 통해 비교를 수행한다는 점 입니다.



논리연산 결과



비교 연산 결과




empty 연산
앞서 표에서 설명했듯이 empty연산자의 경우 empty <대상>형태로 사용되며 대상이 비어있는 값이면 true를 리턴합니다.



비어있는지의 기준은 다음의 순서를 거쳐 처리됩니다.
  1. <대상>이 null이면 true를 리턴합니다.
  2. <대상>이 빈 문자열 ""이면 true를 리턴합니다.
  3. <대상>이 길이가 0배열이나 List이면 true를 리턴합니다.
  4. <대상>이 빈 Map이면 true를 리턴합니다.
  5. <대상>이 빈 Collection이면 true를 리턴합니다.
  6. 1 ~ 5가 아닌 경우 true를 리턴합니다.



다음글


참고서적
최범균저 - JSP 2.3 웹 프로그래밍 기초부터 중급까지


블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

,