2022. 5. 23. 12:49ㆍJAVA/Servlet&JSP
1. Servlet과 JSP
JSP(Java Server Page)
- 확장자가 .jsp 파일
- html 문서안에 자바 언어를 삽입해 사용할 수 있도록함
- Servlet을 사용해 웹을 만들 경우 화면 인터페이스 구현이 어렵다는 단점을 보완하기 위해 만든 스크립트 언어
Servlet
- 확장자가 java 파일
- 자바의 일반적인 클래스와 동일한 개념
- 웹을 다룰 수 있도록 해주는 “HttpServlet” 클래스를 상속받은 클래스를 의미함
웹 어플리케이션의 수행과정
- 사용자가 URL(또는 IP)을 통해 WEB 서버를 호출하고 요청사항을 객체(request)에 담아서 전송함
- WEB 서버는 요청 객체(request)을 받아서 바로 처리하거나 어플리케이션 서버(WAS)로 객체를 전달함
- WAS 서버는 요청에 대한 내용과 요청 객체(request)를 받아 적절히 처리함(필요시 DB 작업도 진행함)
- WAS 서버는 요청 처리후 결과를 응답 객체(response)에 담다 WEB 서버로 회신
- WEB 서버는 응답 객체(response)을 다시 사용자에게 회신
- 사용자의 브라우저는 WEB 서버가 보내준 코드를 해석해 화면을 구성하여 출력
2. WEB 서버 단일 구성
WEB 서버 수행과정
- 사용자가 URL 또는 링크가 걸린 글/그림등을 클릭하여 웹 서버에게 페이지를 요청함
- 웹 서버(WEB Server)가 해당하는 페이지를 사용자에게 전송
- 웹 브라우저는 페이지를 받아서 화면으로 만든뒤 사용자에게 출력
페이지의 구성
- html : 페이지의 컨텐츠를 나타냄
- css : html의 컨텐츠를 꾸며주는 정적 언어
- javascript : 컨텐츠를 동적으로 표현해주는 스크립트 언어
웹 서버가 브라우저에게 html/css/javascript로 구성된 파일을 전송하면 웹 브라우저는 그 파일을 해석하여 실행합니다.
단일 WEB 서버 아키텍처의 단점
- 필요한 페이지마다 자바스크립트 등으로 복잡한 로직을 구성해서 모든 페이지를 미리 준비해야함
- 복잡한 로직이 들어있는 페이지를 모두 사용자(웹 브라우저)에게 전송해야한다는 문제점을 가짐
3. WEB-WAS 구성
WAS(Web Application Server)
웹 서버가 계산하기 복잡한 연산을 처리해주는 서버
WEB-WAS 아키텍처 수행과정
- 사용자(브라우저)가 서버에게 서비스를 요청(페이지 또는 복잡한 연산)함
- WAS는 사용자의 요청 내용(request)을 받아서 처리한 다음 웹 페이지를 생성하여 사용자에게 전송
- WEB 서버는 만들어진 웹 페이지를 사용자에게 전달
WEB-WAS 아키텍처의 장점
- WAS에서 프로그래밍 언어(Java, C++ 등)을 사용해 로직을 처리하기 때문에 보다 복잡한 로직 처리가 가능함
- 사용자는 WEB 서버가 주는 페이지만 받아서 실행하므로 내부의 로직을 알수 없기 때문에 보안이 강화되는 효과를 얻을 수 있음
- 복잡한 연산은 서버단에서 처리하고 사용자(브라우저)에게 결과값만을 전송하기 때문에 사용자는 그만큼 빠르게 결과를 받을 수 있고 받는 정보량(코드)이 줄어들어 네트워크 부하도 줄일 수 있음
WEB-WAS 아키텍처의 특징
- WEB 서버와 WAS 서버는 물리적으로 나눌 수도 있고 한 서버안에 기능적으로 나눌수도 있음
- WEB, WAS 서버는 서로 수행하는 기능이 다름
- WEB 서버 : 연산이 필요없는 정적 페이지(또는 이미지, 파일 등)를 처리함
- WAS 서버 : 연산이 필요한 경우 WAS 서버가 처리하고 WEB 서버에게 전달함
4. WEB-WAS-DB 아키텍처
Database
- 논리적으로 연관된 하나 이상의 자료의 모음
- 데이터(내용)들을 고도로 구조화함으로써 검색과 갱신(추가, 수정, 삭제)의 효율화를 시도함
- 데이터베이스는 DBMS(Database Management System)에 의해서 관리됨
- DBMS는 데이터베이스를 사용자가 직접 접근하는 대신 데이터베이스를 관리하는 시스템입니다.
Database의 필요 이유
- WAS 서버가 복잡한 연산을 위해 필요한 각종 정보를 저장해두기 위해서입니다.
- 사용자가 데이터에 직접 접근하는 것을 방지하여 보안성을 강화하기 위해서입니다.
WEB-WAS-DB 아키텍처 특징
- 복잡한 연산을 위해 필요한 정보를 데이터베이스에서 가져와서 처리함
- 사용자가 데이터베이스에 직접 접근할 수 없기 때문에 보안성이 좋음
WEB-WAS-DB 아키텍처 수행과정
- 사용자(브라우저)가 로그인 서비스를 요청함. 서비스를 요청하면서 웹 서버에 입력한 ID와 비밀번호 정보를 전달함
- 웹 서버는 WAS에게 데이터(ID, 비밀번호)를 전달함
- WAS는 로그인 서비스 로직을 처리하는 도중 사용자가 입력한 아이디와 비밀번호에 해당하는 유저가 있는지 데이터베이스에 검색을 요청함
- 데이터베이스에서 쿼리 결과를 다시 WAS에게 전달함
- WAS에서 WEB 서버를 통해서 사용자에게 로그인 서비스 요청 결과를 응답함
5. Java SE & Java EE
Java SE(Java Standard Edition)
Java SE는 Java의 핵심 API와 기능들을 제공하는 에디션입니다. 간단한 응용 프로그램과 서버 구축이 가능함
Java EE(Java Enterprise Edition)
- Java EE는 Java SE의 확장 버전으로 서버 개발을 위한 추가 기능을 제공하는 플랫폼
- Tomcat 등의 WAS를 이용하는 서버 개발은 Java EE에서 추가로 제공하는 기능을 사용함
- 특히 JSP와 Servlet을 만들고 실행하는 규칙과 EJB(Enterpise JavaBeans)의 분산 컴포넌트, 웹 서비스 규칙 등을 추가로 가지고 있으며, 서블릿과 JSP를 구현하는 기능을 서블릿 컨테이너라고 함
6. Apache Tomcat
- Apache : WEB Server
- Apache Tomcat : WAS(Web Application Server)
Apache
Apache는 Apache 재단에서 만든 HTTP 서버이며 웹 서버 전용 기능을 제공합니다.
Apache Tomcat
Apache Tomcat은 웹 서버 전용 기능인 Apche와는 다르게 WAS 기능을 제공합니다.
Tomcat
- Tomcat은 WEB/WAS의 기능을 가진 자바 어플리케이션
- Tomcat은 Java EE 기반으로 생성됨
- Tomcat(WAS)는 자바로 만들어진 JSP와 Servlet을 구동하기 위한 서블릿 컨테이너 역할을 수행함
Servlet Container란 무엇인가?
- JSP를 Servlet으로 변경하여 실행해주는 역할을 수행함
- Servlet의 생명 주기를 관리하며 웹 환경에서 Servlet이 실행될 수 있도록 해주는 프로그램
- WAS에서는 여러 개의 컨테이너를 구성해서 각각 독립적인 서비스로 구동시키는 것이 가능함
WAS의 Servlet Container 수행과정
- 웹 서버에서 보내준 요청을 가지고 스레드를 생성함
- 필요한 JSP나 Servlet 파일을 실행해서 서비스 요청을 수행함
- 수행 결과를 응답 객체(response)에 담아서 사용자에게 전달함
7. Servlet & JSP(Java Server Page)
Servlet
- Servlet은 Java EE에서 제공하는 서블릿 클래스를 상속받은 클래스를 의미함
- Servlet만을 이용하여 사용자에게 웹 페이지를 생성하여 응답하기에는 불편한점이 존재함
- 웹페이지 생성시 html 코드를 출력해주는 작업이 매우 번거로움
- 스트림 객체를 생성하여 사용자에게 응답할 html 코드를 전부 출력해주어야함
다음은 Servlet에서 사용자에게 응답할 html 코드를 출력하기 위해서 스트림 객체에 print하는 코드입니다.
@WebServlet("/home")
public class HomeController extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
OutputStream out = response.getOutputStream();
PrintStream writer = new PrintStream(out, true);
writer.println("<html>");
writer.println("<head>");
writer.println("</head>");
writer.println("<body>");
writer.println("<h1>helloWorld~</h1>");
writer.println("name : " + request.getParameter("name") + "<br/>");
writer.println("</body>");
writer.println("</html>");
writer.close();
}
}
Servlet 단독 사용의 문제점
- 자바안에 html 코드가 들어가 있지만 코드를 삽입하는게 아닌 그저 출력해주는 방식임
- 복잡한 레이아웃을 가진 페이지를 응답하려면 코드가 길어질 수 밖에 없음
JSP(Java Server Page)
- Servlet을 단독으로 사용하여 웹 페이지를 구성하는 태그요소들을 출력하는 번거로운 문제를 해결하기 위해 나온 스크립트 언어
- Servlet은 자바 언어안에 html 코드를 삽입하는 것이라면 JSP는 html 코드안에 자바 언어를 삽입하는 방식
- 스크립트릿(<% %>)을 삽입하여 그 안에 자바 언어를 넣을 수 있음
- JSP 파일의 확장자는 .jsp입니다.
다음은 JSP 페이지의 예시입니다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP 예제</title>
</head>
<body>
<h1>hello world</h1>
<%
for(int i = 0; i < 10; i++){
out.println(i);
}
%>
</body>
</html>
JSP의 실행과정
- JSP 파일을 Servlet 파일(.java)로 변환
- 변환된 Servlet 파일을 컴파일해서 자바 바이트 코드 파일(.class)을 생성함
- 컴파일된 파일을 실행 결과 자바 언어가 모두 사라진 html 코드를 출력함
JSP→ Servlet으로 변환된 코드는 다음과 같습니다.
public final class home_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
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 {
if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
final java.lang.String _jspx_method = request.getMethod();
if ("OPTIONS".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
return;
}
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
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>JSP �삁�젣</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write(" <h1>hello world</h1>\r\n");
out.write(" ");
for(int i = 0; i < 10; i++){
out.println(i);
}
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);
}
}
}
JSP(.jsp) → Servlet(.java) → .class 파일 변환후 최종적으로 사용자에게 전달되는 코드는 다음과 같습니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSP 예제</title>
</head>
<body>
<h1>hello world</h1>
0
1
2
3
4
5
6
7
8
9
</body>
</html>
References
Apache Tomcat
Tomcat(톰캣), JSP, Servlet(서블릿)의 기본 개념 및 구조
'JAVA > Servlet&JSP' 카테고리의 다른 글
[JSP] 15. JSTL(JSP Standard Tag Library) #1 JSTL이란 무엇인가? (0) | 2022.06.29 |
---|---|
[Java][Servlet] Servlet & JSP의 MVC 패턴 (0) | 2022.05.23 |
[JSP] 14. 표현 언어(Expression Language) (0) | 2022.04.28 |
[JSP] 11.5 자카르타 DBCP API를 이용한 커넥션 풀 사용 (0) | 2022.04.28 |
[JSP] 11.4 JSP에서 JDBC 프로그래밍하기 (0) | 2022.04.28 |