티스토리 뷰

do/java

Servlet, JSP

dooo.park 2019. 4. 23. 23:42

서블릿(Servlet)

웹 프로그래밍에서 클라이언트의 요청을 처리하고 그 결과를 다시 클라이언트에게 전송하는 

Servlet 클래스의 구현 규칙을 지킨 자바 프로그램

 

서블릿은 서버에서 웹페이지 등을 동적으로 생성하거나 데이터 처리를 수행하기 위해 자바로 작성된 프로그램이다. 

자바 서블릿은 서버측 기능을 확장시킨 자바 프로그램으로, 자바 EE(Java Platform Enterprise Edition)의 한 기능이다. 

Java코드 안에 HTML태그가 삽입되며 자바언어로 되어있고 .java가 확장자이다.  

 

유사 기술로 펄(Perl)을 이용한 CGI, PHP를 아파치 서버 위에서 구동시키는 mod_php 등의 모듈, 

마이크로소프트 사가 제공하는 asp 등이 있다. 

CGI의 경우 클라이언트의 요청마다 새 프로세스를 시작하는 반면 

서블릿은 메모리에 상주하여 요청마다 프로세스보다 작은 스레드(thread)를 시작하기 때문에 효율이 좋다. 

 

서블릿 실행환경은 웹 컨테이너 혹은 서블릿 컨테이너로 불린다. 

순수 서블릿을 처리하는 경우 서블릿 컨테이너라 부르는데, 서블릿 컨테이너를 포함한 JSP, HTTP 서버로서의 기능을 포함하기 때문에 웹 컨테이너라고 부르기도 한다.

웹 컨테이너로는 아파치 톰캣(Apache Tomcat), IBM 웹스피어(Web Sphere) 어플리케이션 서버, 레진(Resin) 등이 있다.

 

JSP가 HTML문서 안에 Java 코드를 포함하고 있는 반면, 서블릿은 자바 코드 안에 HTML을 포함하고 있다.

 

Servlet 특징

클라이언트의 요청에 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트
JAVA 프로그램 내부에 HTML 표현
main() 메소드가 없다
반드시 public 이어야 한다
주기함수(Life Cycle)
new 로 객체를 생성하여 사용하지 않는다
서버 안에 저장한다

html을 사용하여 요청에 응답한다

Java Thread를 이용하여 동작한다

MVC 패턴에서 Controller로 이용된다

HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속받는다. UDP보다 속도가 느리다.

HTML 변경 시 Servlet을 재컴파일해야 하는 단점이 있다.

 

Servlet 동작 방식

1. 클라이언트가 URL을 클릭하면 HTTP Request를 Servlet Conatiner로 전송한다.

2. HTTP Request를 전송받은 Servlet Container는 HttpServletRequest, HttpServletResponse 두 객체를 생성한다.

3. web.xml은 사용자가 요청한 URL을 분석하여 어느 서블릿에 대해 요청을 한 것인지 찾는다.

4. 해당 서블릿에서 service메소드를 호출한 후 클라이언트의 POST, GET여부에 따라 doGet() 또는 doPost()를 호출한다.

5. doGet() or doPost() 메소드는 동적 페이지를 생성한 후 HttpServletResponse객체에 응답을 보낸다.

6. 응답이 끝나면 HttpServletRequest, HttpServletResponse 두 객체를 소멸시킨다.

 

Servlet Container(서블릿 컨테이너)

서블릿을 관리해주는 컨테이너

 

서버에 서블릿을 만들었다고 해서 스스로 작동하는 것이 아니고, 서블릿을 관리해주는 것이 필요한데 그 역할을 하는 것이 바로 서블릿 컨테이너이다.

서블릿 컨테이너는 클라이언트의 요청(Request)을 받아주고 응답(Response)할 수 있게, 웹서버와 소켓을 만들어 통신하며 대표적인 예로 톰캣(Tomcat)이 있다.

톰캣은 실제로 웹서버와 통신하여 JSP(자바 서버 페이지)와 Servlet이 작동하는 환경을 제공준다.

 

Servlet Container 역할

① 웹서버와의 통신 지원

    서블릿 컨테이너는 서블릿과 웹서버가 통신할 수 있게 해준다.

    일반적으로 소켓을 만들고 listen, accept 등을 해야하지만 서블릿 컨테이너는

    이러한 기능을 API로 제공하여 복잡한 과정을 생략할 수 있게 해준다.

 

② 서블릿 생명주기(Life Cycle) 관리 

    서블릿 컨테이너는 서블릿 클래스를 로딩하여 인스턴스화하고, 초기화 메소드를 호출하고,

    요청이 들어오면 적절한 서블릿 메소드를 호출한다. 

    서블릿이 수명을 다 한 순간에 Garbage Collection(가비지 컬렉션)을 진행하여 편의를 제공한다.

 

③ 멀티쓰레드 지원 및 관리 

    서블릿 컨테이너는 요청이 올 때 마다 새로운 자바 쓰레드를 하나 생성하는데,

    HTTP 서비스 메소드를 실행하고 나면, 쓰레드는 자동으로 죽는다.

    원래는 쓰레드를 관리해야 하지만 서버가 다중 쓰레드를 생성 및 운영해줘서 쓰레드의 안정성에 대해서 걱정하지 않아도 된다.

 

④ 선언적인 보안 관리 

    서블릿 컨테이너를 사용하면 보안에 관련된 내용을 서블릿 또는 자바 클래스에 구현해 놓지 않아도 된다.

 

 

Servlet 주기

클라이언트의 요청이 들어오면 컨테이너는 해당 서블릿이 메모리에 있는지 확인하고,

없을 경우 init()메소드를 호출하여 적재한다.

 

init()메소드는 처음 한번만 실행되기 때문에, 서블릿의 쓰레드에서 공통적으로 사용해야하는 것이 있다면

오버라이딩하여 구현하면 된다.

 

실행 중 서블릿이 변경될 경우, 기존 서블릿을 파괴하고 init()을 통해 새로운 내용을 다시 메모리에 적재한다.

 

init()이 호출된 후 클라이언트의 요청에 따라서 service()메소드를 통해 요청에 대한 응답이 doGet()가 doPost()로 분기된다.

이때 서블릿 컨테이너가 클라이언트의 요청이 오면 가장 먼저 처리하는 과정으로 생성된

HttpServletRequest, HttpServletResponse에 의해 request와 response객체가 제공된다.

 

컨테이너가 서블릿에 종료 요청을 하면 destroy()메소드가 호출되는데 마찬가지로 한번만 실행되며,

종료시에 처리해야하는 작업들은 destroy()메소드를 오버라이딩하여 구현하면 된다.


JSP(Java Server Pages)

Java 코드가 들어가 있는 HTML 코드

서블릿의 단점을 보완하고자 만든 서블릿 기반의 스크립트 기술이다.

 

서블릿은 자바 소스코드 속에 HTML코드가 들어가는 형태인데,

JSP는 이와 반대로 HTML 소스코드 속에 자바 소스코드가 들어가는 구조다.

 

HTML속에서 자바코드는 <% 소스코드 %> 또는 <%= 소스코드 =%>형태로 들어간다.

자바 소스코드로 작성된 이 부분은 웹 브라우저로 보내는 것이아니라 웹 서버에서 실행된다.

 

JSP는 WAS(Web Application Server)에 의하여 서블릿 클래스로 변환하여 사용된다.

 

JSP는 서블릿 기반의 '서버 스크립트 기술'이다. 
스크립트 기술이란 ASP, PHP 처럼 미리 약속된 규정에 따라 간단한 키워드를 조합하여 입력하면, 

실행 시점에 각각의 키워드에 매핑이 되어 있는 어떤 코드로 변환 후에 실행되는 형태다. 
JSP는 Java소스로 사용하여 웹페이지에 접근하고 페이지 전환을 통하여 웹브라우저에 전달한다. 

 

Servlet과 JSP의 비교

Servlet

JSP

자바코드로 구현하고 컴파일하고 배포해야 한다.
HTML태그로 문자열("")스크림으로 처리해야 한다.
코드가 수정되면 다시 컴파일하고 배포해야 한다.

키워드가 태그화 되어 서블릿에 비해 배우기 쉽다.
자바코드를 <%%>태그 안에 처리해주어야 한다.
HTML처럼 태그를 사용하여 자바코드도 사용이 가능하다.

 

Servlet과 JSP의 역할

JSP는 웹 애플리케이션 구조에서 사용자에게 결과를 보여주는 프리젠테이션 층을 담당하고

Servlet은  사용자의 요청을 받아 분석하고, 비지니스 층과 통신하여 처리하고 처리한 결과를 다시 사용자에게 응답하는

컨트롤러 층을 담당한다.

 

MVC 패턴의 JSP와 Servlet

JSP는 HTML태그 사용이 용이하고 자바코드 사용이 불편하기 때문에 웹어플리케이션에서

사용자에게 결과를 보여주는 View(Client)를 담당하고,

Servlet은 자바코드 작성이 편리하기 때문에 주로 화면과 통신하여 자료를 받아 가공하고 가공한 자료를

다시 화면에 전달하는 Controller역할을 하고 있다.

① JSP와 Servlet 동시에 사용 MVC모델(View는 JSP, Controller는 Servlet을 사용)

② 프리젠테이션 로직과 비즈니스 로직 분리

     - 보여지는 부분은 HTML이 중심이 되는 JSP,

      다른 자바 클래스에게 데이터를 넘겨주는 부분은 Java코드가 중심이 되는 Servlet이 담당

MVC패턴

Model2

기능

Model

서비스클래스

or 자바빈

비지니스 로직을 처리하는 모든 것

컨트롤러부터 특정 로직에 대한 처리 요청이 들어오면

이를 수행하고 수행 결과를 컨트롤러에 반환한다.


(request 객체나 session객체에 저장하기도 함)

View

JSP페이지

클라이언트에 출력되는 화면

모델1과는 달리 로직 처리를 위한 코드가 내포되어있지 않다.

요청 결과의 출력 뿐만 아니라 컨트롤러에 요청을 보내는 용도로도 사용된다.

 

(request객체나 session객체에 저장된 정보를 토대로 화면 출력)

Controller

Servlet

MVC패턴(Model2) 모든 흐름제어를 맡는다

브라우저로 요청이 들어오면 어떤 요청이 들어오는지 분석하여

이 요청을 처리하기 위한 모델을 사용하여 처리한다.

사용한 모델로 부터 처리결과를 받으면 추가로 처리하거나

가공해야 할 정보가 있다면 처리 후 request객체나 session객체에 저장하고,

View(JSP페이지)를 선택하여 Foward나 redirect하여 클라이언트에 출력한다.


JSP파일은 결국 서블릿으로 변환이 되어 실행된다.

JSP파일이 Servlet으로 변환되는 과정은 한 번만 일어나므로 같은 페이지에 수많은 요청이 있더라도

처리속도는 거의 떨어지지 않게 된다.

만약 JSP페이지의 코딩 내용이 변경된다면 다시 변환 과정을 거친다.

 

서블릿을 자바로 구현 된 CGI라고 흔히 말한다.

일반적으로 웹서버는 정적인 페이지만을 제공한다.

동적인 페이지를 제공하기 위해서 웹서버는 다른 곳에 도움을 요청하여 동적인 페이지를 작성해야 한다.

동적인 페이지로는 임의의 이미지만을 보여주는 페이지와 같이 사용자가 요청한 시점에 페이지를 생성해서

전달해 주는 것을 의미한다.

 

여기서 웹서버가 동적인 페이지를 제공할 수 있도록 도와주는 어플리케이션이 서블릿이며,

동적인 페이지를 생성하는 어플리케이션이 CGI다. 

 

※ CGI(Common Gateway Interface)

CGI는 별도로 제작된 웹서버와 프로그램간의 교환방식이다.

CGI방식은 어떠한 프로그래밍언어로도 구현이가능하며, 별도로 만들어 놓은 프로그램에 HTML의 Get or Post 방법으로

클라이언트의 데이터를 환경변수로 전달하고, 프로그램의 표준 출력 결과를 클라이언트에게 전송하는 것 이다.

즉, 자바 어플리케이션 코딩을 하듯 웹 브라우저용 출력 화면을 만드는 방법이다.

 

 


Servlet 실습 예제


※ 환경 설정

Windows 10 기준

윈도우 탐색기  ->  제어판  ->  모든 제어판 항목  -> 시스템  ->  고급 시스템 설정 ->  메뉴 탭에서 [고급]  ->  "환경 변수(N)..." 

 

① [JDK설정] JAVA_HOME 설정
     [환경변수 창]에서 시스템 변수(S)  ->  "새로 만들기(W)" 

 

변수이름 : JAVA_HOME

변수   값 : C:\Program Files\Java\jdk1.8.0_172

② [TOMCAT설정] TOMCAT_HOME 설정

     [환경변수 창]에서 시스템 변수(S)  ->  "새로 만들기(W)" 클릭

 

변수이름 : TOMCAT_HOME

변수   값 : C:\Program Files\Apache Software Foundation\Tomcat 8.0

 


※ 주기함수 (Life Cycle)

init() : 맨 처음에 한 번만 호출
   ↓
service()   - doGet()   :  클라이언트가 요청시마다 호출
                 - doPost() 
   ↓
destroy()

 

서블릿을 이용해서 응답하기

서블릿 파일을 만들 때의 소스코드

package com.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HiServlet")
public class HiServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public HiServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

주기함수를 추가해주기 위해 상단 메뉴바에서 Source > Override/Implement Methods.. 를 선택한다.

 

 

GenericServlet 하위에 있는 destroy(), init(ServletConfig) 메소드를 Override 한다.

간단히 동작을 확인하기 위해 서블릿을 수정한다.

package com.servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HiServlet")
public class HiServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public HiServlet() {
        super();
    }

	@Override
	public void destroy() {
		System.out.println("서블릿 종료");
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("서블릿 시작");
	}

	/* 역할 */
	// 1. 클라이언트에서 넘어온 data처리 
	// 2. 클라이언트로 응답으로 보내줄 문서
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
	 throws ServletException, IOException {
		// request는 요청, response는 응답을 뜻합니다.
		System.out.println("doGet() 실행");

	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
	 throws ServletException, IOException {
		doGet(request, response);
	}

}

이 상태에서 실행하면 설정해주었던 init() 메소드와 doGet() 메소드가 실행된 것을 확인할 수 있다.

 

서버에서 클라이언트에게 돌려보낼 내용을 설정하지 않았기 때문에, 웹 브라우저 상에는 아무것도 나타나지 않는다.

따라서 클라이언트(웹브라우저)에게 보낼 내용을 작성한다.

package com.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HiServlet")
public class HiServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public HiServlet() {
        super();
    }

	@Override
	public void destroy() {
		System.out.println("서블릿 종료");
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("서블릿 시작");
	}

	/* 역할 */
	// 1. 클라이언트에서 넘어온 data처리 
	// 2. 클라이언트로 응답으로 보내줄 문서
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
	 throws ServletException, IOException {
		// request는 요청, response는 응답을 뜻합니다.
		System.out.println("doGet() 실행");
		// 이후 응답할 문자열을 html문서로 인식할 것을 명령합니다.
		response.setContentType("text/html; charset=UTF-8"); 
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head>");
		out.println("<title>Servlet</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("Hello Servlet!!<br>");
		out.println("Hi 서블릿!!<br>");
		out.println("안녕하세요 서블릿!!<br>");	
		out.println("</body>");
		out.println("</html>");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
	 throws ServletException, IOException {
		doGet(request, response);
	}

}

재실행 결과 클라이언트에 응답할 내용이 웹브라우저 상에 나타난다.


참고사이트

https://terms.naver.com/entry.nhn?docId=3431425&cid=40942&categoryId=32838

https://m.blog.naver.com/PostView.nhn?blogId=acornedu&logNo=221128616501&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

https://blog.naver.com/isaac7263/221367322743

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함