본문 바로가기

JSP

[JSP]JSP의 스크립트 요소

스크립트 요소

  • JSP 프로그래밍에서 사용되는 문법 표현 형태로 총 4가지가 존재한다.
  • 선언문(Declaration) - <%! ...%>
  • 스크립트릿(Scriptlet) - <% ... %>
  • 표현식(Expression)2 - <%= ... %>
  • 주석(Comment) - <%-- ... --%>, <-- ... --> <% //... %>

선언문(Declaration) - <%! ... %>

  • <%! 멤버변수 및 메서드를 선언하는 영역>
  • JSP페이지에서 사용될 변수나 메서드를 선언할 수 있는 영역의 요소
  • JSP 페이지 어느 곳에서든지 참조하여 사용이 가능하다.
  • JAVA형식으로 선언된 변수나 메서드를 이용해 동적인 HTML 코드를 생성하는데 사용된다.
  • 멤버변수나 메서드의 선언은 JAVA의 클래스와 똑같다. 멤버변수를 선언과 동시에 초기화를 하지 않는다면 각 자료형의 기본값으로 초기화가 된다. 단 메서드의 경우에 반드시 리턴 타입이 존재해야한다.
  •  JSP페이지에서 선언된 메서드는 자신의 페이지에서만 반복적으로 사용될 수 있기 때문에 반복적으로 사용할 기능의 메서드가 필요하다면 자바 파일로 만들어서 모든 JSP 페이지에서 참조하여 사용하는것이 코드의 중복을 제거할 수 있고, 작성하기 편하기 때문에 잘 사용되지 않는다.

예제1

  • 같은 선언문 내의 firstName과 lastName은 선언되기 이전에 같은 선언문 내에서는 참조가 불가능하나
  • 스크립트릿내에서는 선언문의 위치와는 관계없이 참조가 가능하다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Declaration Example</title>
</head>
<body>

<%-- <%! String name = firstName + lastName;%> --%>
<% String name = firstName + lastName;%>
<%! String firstName = "hong"; %>
<%! String lastName = "mugae"; %>
<%!
	public String getName() {
		//return name;
		return firstName + lastName;
	}

	String tempStr;
	int tempInt;
%>
	<div>Declaration의 멤버변수 표현식 결과 : <%= name %></div>
	<div>Declaration의 메서드 표현식 결과 : <%= getName() %></div>
	<div>초기화 되지 않은 String : <%= tempStr %></div>
	<div>초기화 되지 않은 int : <%= tempInt %></div>

</body>
</html>

실행결과

 

스크립트릿(Scriptlet) - <% ... %>

  • <% 지역변수 및 제어문등의 자바코드가 위치한다. %>
  • JSP페이지가 서블릿으로 변환되고 요청될 때 _.jspService(Tomcat기준) 메서드 안에 선언이 되는 요소이다.
  • 선언문과 달리 선언된 변수는 지역 변수로 선언이 되고 당연하게도 메소드 선언은 할 수 없다.(Java의 메서드 안에 메서드를 선언할 수 없기 때문임)
  • 스크립트릿 코드 내에서 JSP의 내장객체인 out을 사용하여 브라우저에 변수또는, 메서드의 결과값을 HTML페이지에 출력할 수 있다.

예제2

  • 스크립트릿 내의 변수는 선언문 내의 변수와 달리 반드시 초기화가 되어야한다.
  • 또한 선언된 이후에만 해당 변수를 참조할 수 있다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Scriptlet Example</title>
</head>
<body>

<%! 
int one;
String strOne;
%>

<%
	int two = 2;
	//String strTwo;
%>
	<div>one : <%= one %></div>
	<div>two : <%= two %></div>
	<div>strOne : <%= strOne %></div>
	<%-- <div>strTwo : <%= strTwo %></div> --%>
	<div><%= application.getRealPath("/") %></div>

<%
	int random = (int)Math.random()*10;
	java.util.Date date = new java.util.Date(); 
%>
	<div>Random Number : <%= random %></div>
	<div>Now Date : <%= date.toString() %></div>

</body>
</html>

실행결과

선언문과 스크립트릿의 차이점

  • 각각의 영역에서 선언된 변수는 참조할 수 있는 위치가 다르다.
  • 선언문 : 선언문 영역 내에서 선언되는 변수는 멤버변수로 JSP페이지 전체에서 접근이 가능하며, 메서드의 선언또한 가능하다.
  • 스크립트릿 : 스크립트릿  영역 내에서 선언되는 변수는 지역변수로 반드시 초기화를 해줘야 하며, 선언문과 달리 선언된 이후의 라인에서부터 참조가 가능하다. 또한 문장 블록을 닫지 않고 끝낼 수 있는 셩격을 갖기 때문에 JSP 제어문 처리에 유연하게 사용이 가능하다. 특히 조건문이나 순환문, 에러를 처리할 때 유용하게 사용되며 만약 if/else문 사이에 정적인 코드(HTML/Javascript)가 들어갈 경우 서블릿처럼 out 내장객체를 사용하거나 필요에 따라 스크립트릿을 닫고 다시 필요한 부분에서 스크립트릿을 사용할 수 있다.

예제 2를 통해 선언문과 스크립트릿 차이점 확실하게 구분해보기

  • 예제 2에서 application.getRealPath("/")로 어떤 URL을 얻었을 것이다.
  • 해당 URL의 상위폴더인 temp0으로 이동하고, work폴더의 계층을 쭉 따라가다보면 servlet으로 변환된 파일을 확인할 수 있다.
  • 주목할점은 선언문 내에서 선언한 변수의 위치와, 스크립트릿 내에서 선언된 변수의 위치이다.
  • 선언문내 변수는 클래스의 멤버변수로, 스크립트릿내 변수는 _jspService()메서드의 지역변수로 선언된것을 확인할 수 있다.

변환된 Servlet파일

  • 클래스 내의 int one, String strOne과 _jspService()메서드를 주의깊게 살펴보도록하자
/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/8.5.77
 * Generated at: 2023-03-06 09:57:48 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class scriptletExample_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

 
int one;
String strOne;

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = null;
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    final java.lang.String _jspx_method = request.getMethod();
    if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP들은 오직 GET, POST 또는 HEAD 메소드만을 허용합니다. Jasper는 OPTIONS 메소드 또한 허용합니다.");
      return;
    }

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html; charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("<!DOCTYPE html>\r\n");
      out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("<meta charset=\"UTF-8\">\r\n");
      out.write("<title>Scriptlet Example</title>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");
      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");

	int two = 2;
	//String strTwo;

      out.write("\r\n");
      out.write("	<div>one : ");
      out.print( one );
      out.write("</div>\r\n");
      out.write("	<div>two : ");
      out.print( two );
      out.write("</div>\r\n");
      out.write("	<div>strOne : ");
      out.print( strOne );
      out.write("</div>\r\n");
      out.write("	");
      out.write("\r\n");
      out.write("	<div>");
      out.print( application.getRealPath("/") );
      out.write("</div>\r\n");
      out.write("\r\n");

	int random = (int)Math.random()*10;
	java.util.Date date = new java.util.Date(); 

      out.write("\r\n");
      out.write("	<div>Random Number : ");
      out.print( random );
      out.write("</div>\r\n");
      out.write("	<div>Now Date : ");
      out.print( date.toString() );
      out.write("</div>\r\n");
      out.write("\r\n");
      out.write("</body>\r\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}
  • 이러한 내용을 바탕으로 예제2의 내용을 간단한 클래스로 표현시 아래와 같다.
public class Temp {
	//Declaration 영역
	int one;
	String strOne;
	
	public void _jspService() {
		//Scriptlet 영역
		
		int two = 2;
		//String strTwo;
	}
    
}
  • 즉 JSP을 서블릿으로 변환시 선언문은 클래스영역이고 스크립트릿은 메서드영역이라 볼 수 있다.
  • 그렇기 때문에 선언문 (<%! ... %>)영역 내에서는 변수와 메서드의 선언이 가능했던 것이고, 선언된 멤버변수를 초기화하지 않았을 경우 각 자료형의 초기값으로 초기화가 된것이였다.
  • 그리고 스크립트릿(<% ... %>)영역은 내에서 선언된 변수는 반드시 초기화가 되어야하며, 메서드 내부이기때문에 메서드를 선언할 수 없었던 것이다.
  • 이러한 특성으로 인해 JSP파일내의 선언문의 위치와는 상관없이 스크립트릿 영역에서 참조가 가능한것이였고, 스크립트릿 영역내에서 선언된 변수는 반드시 초기화가 되고 순서또한 중요했던 것이다.

표현식(Expression)2 - <%= ... %>

  • <%= 변수 혹은 메서드 =>
  • 동적인 JSP 페이지를 브라우저로 표현하기 위한 요소
  • 변수를 출력하거나 메서드의 결과 값을 브라우저에 출력할 수 있다.
  • 스크립트릿의 out객체와 달리 변수나 메서드를 출력하고자 할 때는 세미클론(;)은 표기하지 않는다.(내부적으로 서블릿 코드로 변환시 자동으로 붙기 때문)
  • 결과로만 출력이 가능하기 때문에 조건적인 문장은 표현식으로 사용할 수 없다. 단 삼항연산자는 조건 검사의 결과 값을 리턴하기 때문에 표현식에서 사용 할 수 있다.

예제3

  • 스크립트립의 특성을 이용하여 반복문을 통해 HTML태그를 동적으로 생성하였다.
  • 표현식 <%= %>는 변수 또는 메서드를 호출한 결과값을 화면상에 출력해준다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%! String[] name = {"java", "jsp", "servlet", "apache-tomcat"}; %> 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ExPression Example</title>
</head>
<body>

	<h1>Expression Example</h1>
	<table border="1">
	<%for(int i=0; i<name.length; i++) {%>
		<tr>
			<td><%= i %></td>
			<td><%= name[i] %></td>
		</tr>
	<%}%>
	</table>
	
	<br>
	
	<% 
		java.util.Date date = new java.util.Date();
		int hour = date.getHours();
		int tempInt1 = date.getMinutes();
		int tempInt2 = date.getSeconds();
	%>
	<%!
		public int operation(int tempInt1, int tempInt2) {
			return tempInt1 > tempInt2 ? tempInt1 : tempInt2;
		}
	%>
	<div><%= hour > 12 ? hour - 12 : hour %>시(<%= hour > 12 ? "오후" : "오전" %>)</div>
	<div>두 수중 큰 수 : <%= operation(tempInt1, tempInt2)%></div>

</body>
</html>

실행결과

 

주석(Comment) - <%-- ... -%>, <-- ... -->, <% //... %>

  • <%-- ... %>
    • JSP형식의 주석으로써, 웹브라우저의 페이지 소스보기로도 확인이 불가능하다.
    • JSP의 문법을 주석처리하므로, 내부에 표현식이 있더라도 무시된다.
  • <-- ... -->
    • HTML형식의 주석으로써, 웹브라우저의 페이지 소스보기로 확인이 가능하다.
    • 주석 내부에 표현식을 사용해 주석을 동적으로 생성시킬 수 있으나, 표현식의 값이 틀리면 주석이라 할지라도 컴파일 에러가 발생한다.
  • <% //... %>
    • JAVA형식의 주석으로써, 자바에서 사용되는 주석 처리방법과 동일하다.

예제

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP Scripting Element Example</title>
</head>
<body>
	<h1>Script Example</h1>
	
	<!--  -->
	<%! String declaration = "Declaration"; %>
	<%! public String declarationMethod() {
		return declaration;
	} %>
	
	<%
		String scriptlet = "Scriptlet";
		String comment = "Comment";
		out.println("내장객체를 이용한 출력 : " + declaration + "<p>");
	%>
	
	<div>선언문 출력1 : <%= declaration %></div>
	<div>선언문 출력2 : <%= declarationMethod() %></div>
	
	<div>스크립트릿의 출력 : <%= scriptlet %></div>
	
	<!-- 
	 기존 HTML에서 사용하던 주석방식 + JSP가 제공하는 제공방식 총 두가지가 존재하는데,
	 HTML에서 사용하던 주석방식은 브라우저상에서 표출된다는 점에서 차이점이 존재한다.
	-->
	<!-- <span>JSP 주석1 : <%= comment %></span>  -->
	<%-- <span>JSP 주석2 : <%= comment %></span> --%>
	<%
		//스크립트릿 내부는 자바 프로그램과 다를것이 없다.
		/*
			때문에 한줄주석 또는 여러줄 주석이 가능하다.
		*/
	%>
	
</body>
</html>

실행결과

  • 페이지 소스보기의 결과이다.
  • <!-- ... --> 형식의 주석은 페이지 소스보기에서 출력이 되지만, <%-- ... %>와 <% //... %>는 출력되지 않는다.
  • 또한 HTML형식의 주석 내부에 표현식또한 문제없이 동작한다.

정리

  • 선언문 <%! ... %>영역은 Servlet변환시 클래스영역이므로, 변수선언 및 메서드의 선언이 가능하며, 변수는 멤버변수로써 초기화를 하지 않으면 기본값으로 초기화된다. 또한 선언문은 선언된 위치와 관계없이 해당 JSP페이지 어디에서든 참조가 가능하다.
  • 스크립트릿<% ... %>영역은 Servlet변환시 _jspService()메서드 내부의 영역으로, 변수선언만 가능하며, 해당 변수는 지역변수로 초기화를 반드시 해줘야한다. 또한 선언문과 달리 선언이후에만 참조가 가능하다. 단 문장 블록을 닫지않고 유연하게 사용할 수 있다는 점을 활용해 제어문을 사용한 동적 페이지 생산을 할 수 있다.
  • 표현식<%= ... %>영역은 Servlet변환시 _jspService()메서드 내부의 out.println("[<tag> ... </tag>]")형태이며, JSP페이지의 스크립트릿 영역에서 사용할 수 있는 JSP 내부객체의 out.println()과 똑같으나 편의상 지원하는 JSP 스크립트 문법이다.  선언문, 스크립트릿에서 선언된 변수나 메서드를 호출할 수 있으며 세미클론(;)을 붙이지 않아도 된다.  
  • 주석은 JSP주석 HTML주석 Java주석이 있으며, HTML주석은 내부에 표현식을 이용해 동적으로 주석을 만들 수 있으며 페이지소스보기에 노출이된다. 반면 Java주석과 JSP주석은 페이지소스보에 노출이 되지 않는다.

'JSP' 카테고리의 다른 글

[JSP] 내부객체  (0) 2023.03.15
[JSP]JSP의 지시자와 액션태그  (0) 2023.03.15
[JSP]Model1, Model2  (0) 2023.03.14
[JSP]JSP의 개념  (0) 2023.03.14
[JSP]동적 페이지를 위한 기술 CGI  (0) 2023.03.10