자바 서블릿(Java Servlet)은 자바를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 사양을 말하며, 흔히 "서블릿"이라 불린다. 자바 서블릿은 웹 서버의 성능을 향상하기 위해 사용되는 자바 클래스의 일종이다. 서블릿은 JSP와 비슷한 점이 있지만, JSP가 HTML 문서 안에 Java 코드를 포함하고 있는 반면, 서블릿은 자바 코드 안에 HTML을 포함하고 있다는 차이점이 있다. [출처 : 위키백과]
서블릿 컨테이너란 말 그대로 서블릿을 담고 관리해주는 컨테이너이다.
서블릿 컨테이너는 다음과 같은 주요기능을 갖고 있다.
생명주기 관리
서블릿의 생명주기를 관리한다. 서블릿 컨테이너가 서블릿 클래스를 로딩해서 인스턴수화하고, 초기화 메서드를 호출하고 요청이 들어오면 적절한 서블릿 메서드를 찾아서 동작한다.
통신 지원
클라이언트의 Request를 받아주고 Response를 보낼 수 있게 웹서버와 소켓을 만들어서 통신을 해준다. 서블릿컨테이너가 소켓을 만들고 listen, accept등의 기능을 API로 제공하여 복잡한 과정을 생략할 수 있게 해주고 개발자로서 비즈니스 로직에 더욱 집중할 수 있게 해준다.
멀티스레딩 관리
서블릿 요청이 들어오면 스레드를 생성해서 작업을 수행한다. 그렇기에 동시에 여러 요청이 들어와도 여러 작업을 관리할 수 있다.
선언적인 보안관리
대체적으로 보안관리는 XML 배포 서술자에 기록하기 때문에 보안이슈로 스스로 수정할 일이 생겨도 자바코드를 수정하여 다시 컴파일 하지 않아도 된다.
POST는 URL에 queryParameter 로 변수를 넣어 전송하는 방식이 아닌, body부분에 데이터를 넣어 전송하는 방식이다. POST를 사용하면 많은 양의 data를 전송할 수 있고, url에 넣어 전송하지 않기 때문에 기본 보안성을 지닌다는 장점이 있다. 하지만 GET method와 비교하여 다소 느린 속도를 갖는 것이 단점이다.
WAS(Tomcat v9) 에서는 기본적인 인코딩 방식이 UTF-8이 아닌, ISO-8859-1을 인식한다. 즉, 한글을 인식하지 않기 때문에 개발자가 별도의 설정을 해 줘야 한다. (ISO-8859-1은 1byte를 한 문자로 인식한다.)
이를 해결하는 방법은 간단하다. Servlet에서 개발자가 별도로 인코딩방식을 설정해주면 해결가능하다.
doGet(HttpRequest req, HttpResponse res){
req.setCharacterEncoding("UTF-8");
}
요청이 오면, Servlet 클래스가 로딩되어 요청에 Servlet 객체가 생성된다.
서버는 init() 메소드를 호출해서 Servlet()을 초기화 한다.
2-1 init() 메소드는 한번 호출되는 것이 보장되기 때문에 초기설정 등을 여기서 설정한다.
service() 를 호출하여 브라우저의 요청을 처리한다.
3-1 이때 service()를 호출하면, Servlet은 사용자의 method에 따라서 doGet(), doPost() 등을 실행한다.
서버는 destroy() 메소드를 호출하여 Servlet을 제거한다.
사용자의 request마다 Servlet을 생성(init)하고 삭제(destroy) 하는것은 많은 cost를 요구한다.
따라서 처음의 요청에 servlet을 init 한 후, memory에 저장해 두었다가 WAS(Tomcat)이 reload or shutdown 이 될 경우에만 생성된 servlet들의 destroy를 호출한다.
<%! 멤버변수와 method작성 %> // '!" 를 통해서 선언문임을 명시
// <%! 들 사이에 공백이 들어가면안됨
<%!
String name; // 안의 변수는 전부 전역변수로 처리됩니다.
public void init(){
name = '~~~';
}
%>
<% [~~~~~~~~~~~~~~~~~] %> // req나 res를 처리한다.
<%
out.print("hihi"):
%>
<%= ~~~~~~~~~~~~~~~~~~~ %> // '=' 으로 출력문임을 명시
// 문자열 로만 이루어짐, ;은 쓰면안됨!
<%
hihi
%>
→ 처리문의 hihi출력과 출력문의 hihi는 같다!
<%-- 주석할 code --%>
JSP 주석과 HTML 주석의 차이
<%@ page attr1="val1" attr2="val2" ... %>
속성 | 기본값 | 설명 |
---|---|---|
language | java | 스크립트에서 사용할 언어 지정 |
info | 현재 JSP 페이지에 대한 설명 | |
contentType | text/html;charset=”ISO-8859-1” | 브라우저로 내보내는 내용의 MIME형식 지정 및 문자집합 지정 |
pageEncoding | ISO-8859-1 | 현재 JSP 페이지 문자집합 지정 |
import | 현재 JSP페이지에서 사용할 java패키지나 클래스를 지정 | |
session | true | 세션의 사용유무 설정 |
errorPage | 에러가 발생할 때 대신 처리될 JSP페이지 설정 | |
isErrorPage | false | 현재 JSP페이지가 에러 핸들링하는 페이지인지 지정하는 요소 |
buffer | 8KB | 버퍼의 크기 |
isThreadSafe | true | 현재 JSP페이지가 멀티쓰레드로 동작해도 안전한지 여부를 설정, false일 경우 JSP페이지는 singleThred로 서비스됨 |
extends | javax.servlet.jsp.HttpJspPage | 현재 JSP페이지를 기본적인 클래스가 아닌 다른 클래스로부터 상속하도록 변경. |
autoflush | true | 버퍼의 내용을 자동으로 브라우저로 보낼지 지정 |
<%@ include file="..."%>
<%@ taglib prefix="c" uri="..........." %>
정적 include 는 다음과 같이 사용한다.
<%@ include file="filePath" %>
이는 해당 파일이 해당 정적include의 코드부분이 해당 파일로 대체되어 진행하게 된다.
즉, 부모 JSP파일과 include 되는 자식 jsp 파일이 하나로 합쳐진 후, 진행된다.
부모/자식 jsp 합쳐짐 -> Java 파일로 컴파일 -> class 파일로 컴파일 -> HTML로 랜더링
즉, 자식.jsp 를 수정해도 부모 jsp파일의 수정이 없으면 재 컴파일이 안된다.
동적include에 대한 사용법을 살펴보면 다음과 같다.
<jsp:include page=""/>
이는 부모 jsp 파일이 java로 변경된 후 class로 컴파일 되고, HTML로 랜더링 되는 실행시점에 자식.jsp 파일이 include 된다.
forward | sendRedirect | |
---|---|---|
사용방법 | RequestDispatcher dispatcher = request.getRequestDisaptcher(path); | |
dispatcher.forward(request, response); | response.sendRedirect(location); | |
이동범위 | 동일 서버(Project)내 경로 | 동일 서버 포함 타 URL 가능 |
location bar | 기존 URL 유지(실제 이동되는 주소는 확인 불가) | 이동하는 Page로 변경 |
객체 | 기존의 Request와 Response가 그대로 전달 | 기존의 request와 response는 소멸되고, 새로운 request와 response가 생성 |
속도 | 비교적 빠름 | forward() 에 비해 느림 |
데이터유지 | request의 setAttribute(name, value)를 통해서 전달 | request로는 data 저장이 불가능하다. session이나 cookie를 이용한다. |
서블릿을 이용할 경우, view단의 화면을 구성하기 위해서 많은 양의 html코드를 print로 처리해야 한다는 단점이 있다.
비즈니스 로직의 변경이 발생할 경우, 해당 코드에 수정이 많아지며 UI를 변경할 일이 있어도 비즈니스 로직이 함께있는 파일을 수정해야한다.
JSP를 사용하게 되면, 상단에 비즈니스 로직이 들어가며 하단의 HTML코드를 통해서 view 단의 코드가 작성된다.
위와 같은 단점은 추후의 MVC 패턴이 등장한 계기가 된다.