[WEB] Servlet

WEB 개요

servlet0
  • Web Server

    • 정적 컨텐츠(HTML, CSS, image 등) 제공
    • 동적 컨텐츠 제공을 위해 클라이언트의 요청을 WAS에 전달, WAS가 처리한 결과를 클라이언트에게 응답
  • WAS(Web Application Server)

    • parameter의 내용에 따라 다양한 로직 처리(DB조회 등)를 수행하여 동적 컨텐츠 제공
    • Web Container 라고도 한다.

Web Server와 WAS를 함께 사용하는 이유

  • 정적 컨텐츠 제공 / 동적 컨텐츠 제공 기능 분리하여 서버 부하 방지
  • WAS는 외부와 간접적으로 연결됨 - 보안을 고려해야 하는 파일 및 리소스를 안전하게 보호
  • 여러대의 WAS 연결하여 수많은 요청을 분산해서 안정적으로 운영할 수 있는데, 이 때 Web Server가 Load Balancing 역할 수행해준다.
  • Web Server를 WAS 앞에 두고, 필요한 WAS들을 Web Server에 플러그인 형태로 설정하면 더욱 효율적인 분산 처리가 가능하다.

Servlet

클라이언트의 요청을 처리하고 그 결과를 반환하는, Servlet 클래스의 구현규칙을 지킨 자바 웹 프로그래밍 기술

  • 원칙적으로는 javax.servlet.Servlet 인터페이스를 구현한 자바 클래스이다.
  • 클라이언트의 요청에 대해 웹서버가 동적인 페이지를 제공하는 기능을 하는 자바 클래스이다.
  • 자바로 구현된 CGI라고도 한다.

    💡 CGI (Common GateWay Interface)

    웹서버와 외부 프로그램 사이에서 정보를 주고받는 방법이나 규약

  • MVC 패턴에서 Controller로 이용된다.

Servlet Container

WAS(Web Application Server) 중 Servlet API를 지원하는 것.

클라이언트의 요청/응답을 처리하기 위해 서블릿을 관리하고 동작시킬 수 있는 환경을 제공하는 서버 프로그램으로, 주된 역할은 다음과 같다.

  • 통신 지원

    • 웹 서버와 서블릿이 통신하는 과정(소켓 만들고, 특정 포트를 리스닝하고, 스트림 생성 등등..)을 알아서 제공한다.
  • 생명주기 관리

    • 아래 Servlet LifeCycle에서 자세히 설명
  • 멀티스레딩 관리

    • 클라이언트 최초 요청시 서블릿 생성 후, 이미 생성된 서블릿에 대한 요청은 스레드를 생성해 실행한다. (아래 Servlet과 객체 생성 에서 자세히 설명)
    • 즉, 동시에 여러 요청이 들어오면 멀티스레딩 환경으로 동시다발적인 작업을 관리한다.
  • 보안관리

    • 보안 관련된 기능을 지원하므로 서블릿 코드 안에 보안 관련 메소드를 구현하지 않아도 된다.
  • JSP 지원

🐱 이클립스에서 Tomcat 사용하기

Apache Tomcat은 대표적인 서블릿 컨테이너이다.

  1. Tomcat 9버전 다운로드
  2. 환경변수 설정

    • 시스템변수 Path 편집 - tomcat\bin 까지의 경로 등록 (jdk 아래에 위치)
    • 시스템 변수 새로만들기 - 이름 CATALINA_HOME 설정, tomcat까지의 경로 등록
servlet3 servlet4
  1. 이클립스에서 File - New - Server 선택 후 Tomcat 선택
servlet2

프로젝트의 Java Resources - Libraries 하단에 Tomcat이 들어갔는지 확인하자. 그 안에 servlet-api.jar 파일이 들어있다.

  1. 이제 상단 메뉴에서 초록색 run 버튼을 눌러 tomcat 서버를 실행할 수 있다. 혹시 기본 포트번호인 80을 다른 무언가가 사용하고 있어 실행이 안된다면 server.xml 파일을 열어서 포트번호를 수정하자 (나는 8088번으로 함)
servlet5

서블릿 활용 이클립스의 다이나믹 웹프로젝트 개발구조

  • src 폴더 내

    • 순수 DTO, DAO 등등.. 일반 모든 자바 소스 위치
    • http 기반으로 요청/응답 처리하는 Servlet 파일 위치 (Controller로 사용)
  • WebContent 폴더 내

    • *.html, *.jsp (View로 사용) / *.css / *.js / 이미지, 동영상 … 등 위치

Servlet의 동작 방식

img

[이미지 출처] https://mangkyu.tistory.com/14

1) Servlet과 객체 생성

  • Servlet 객체최초의 클라이언트 요청시 단 한번만 생성된다.

    • 서블릿 객체 수 : 요청한 클라이언트 수 = 1 : N
  • deGet() / doPost() 메소드클라이언트 요청 수만큼 실행된다.

    => 하나의 프로세스 내에 여러 스레드로 개별 실행 = 멀티스레딩

    • deGet() / doPost() 메소드 수 : 요청한 클라이언트 수 = 1 : 1
    • doGet() / doPost()는 parameter로 개별 HttpServletRequest, HttpServletResponse를 받는다
    • client 한 명당 1:1로 HttpServletRequest 객체와 HttpServletResponse 객체가 자동 생성된다 - client 간에 공유되지 않고 개별적으로 할당됨

2) 클라이언트 request의 method : GET vs POST

웹브라우저는 get과 post 두 방식 중 한가지를 이용해서 데이터(requeset의 파라미터)를 전송한다.

  • GET 방식

    • url에 전송되는 데이터 값이 오픈된다
    • (보안과 관계 없는) 소량의 데이터 전송, web page 구분용으로 사용
  • POST 방식

    • 우편을 편지봉투에 넣어서 보내듯, 전송값을 은닉하여 전송
    • 보안이 필요한 경우(예: id 및 pw 제출), 전송하는 데이터 양이 많은 경우 사용

3) Servlet LifeCycle

servlet6
  1. 기본생성자 - 객체 생성

    • 최초 클라이언트가 호출시 실행되서 객체 생성
    • 서블릿 파일 혹은 jsp 파일이 수정되면 기존 서블릿 자원을 해제시킨 뒤 새로 객체 생성
  2. init()

    • 생성자 호출(객체 생성) 직후에 단 한번 실행
    • 공유하는 자원 초기화하는 로직 개발하기에 적합
  3. service() / deGet() / doPost()

    • 클라이언트 요청시 1:1 실행
    • service()는 요청방식(method)에 무관하게 실행, 요청 방식에 따라 doGet() 또는 doPost() 실행
  4. destroy()

    • 서블릿 파일을 수정하여 갱신된 servlet bytecode가 서버 메모리에 로딩시 자동 호출, 자동으로 구버전 객체 메모리 해제
    • 자원 반환용 로직 구현하기에 적합

Servlet API

servlet7

1) HttpServlet

HTTP 프로토콜을 지원해주는 클래스이다.

일반적으로 서블릿이라 하면 대부분 javax.servlet.http.HttpServlet를 상속받은 것을 의미한다. HttpServlet은 GenericServlet을 상속받아 추상 메서드인 service를 HTTP 프로토콜 요청 메서드에 적합하게 구현한 것이다.

처리하고자 하는 방식 (method)에 따라 알맞은 메소드를 오버라이딩해서 구현한다.

메소드

  • doGet() : get방식으로 처리시 사용한다. HttpServletRequest와 HttpServletResponse 두 파라미터를 갖는다.
  • doPost() : post방식으로 처리시 사용한다. HttpServletRequest와 HttpServletResponse 두 파라미터를 갖는다.
  • service() : 서블릿이 초기화된 후 클라이언트로부터 온 요청에 대한 서비스 수행 (get/post 방식 관계없이)

2) HttpServletRequest

http 프로토콜 기반으로 클라이언트의 request 정보를 서블릿에게 전달하기 위한 클래스이다.

ip, 브라우저 기본정보, 클라이언트가 서버에 전송하는 입력 데이터 등등의 정보를 담고 있다.

메소드

  • setCharacterEncoding() : 클라이언트 request로 들어오는 데이터의 포맷 및 인코딩 설정

    • 한글 인코딩 설정시 - request.setCharacterEncoding("utf-8");
  • getRequestQueryString() : 클라이언트가 서버에 전송하는 map 구조의 데이터 (queryString) 을 받아옴
  • String getParameter(name) : 클라이언트가 서버에 전송한 데이터 획득 (queryStringkey값을 받아옴)
  • String [] getParameterValues(name) : 데이터값이 여러개일때 배열 형태로 받음
  • setAttribute(key, value) : request 객체에 map 구조로 데이터 저장 (key에 저장할 데이터인 value 매핑)
  • getRequestDispatcher() : 페이지 이동

💡 참고: url의 형식

http://ip:port/project명/file명?key1=value1&key2=value2

여기서 key1=value1&key2=value2 … 부분을 queryString라고 함

3) HttpServletResponse

http 프로토콜 기반으로 클라이언트 브라우저에게 응답하기 위한 클래스이다.

메소드

  • setContentType(): 클라이언트 브라우저에 응답하는 데이터의 포멧 및 인코딩 설정

    • 한글 인코딩 설정시 - response.setContentType("text/html;charset=utf-8");
  • getWriter() : 2byte 출력 가능한 PrintWriter 객체 생성
  • sendRedirect() : redirect 방식으로 화면 이동

✅ Servlet 사용 실습

<index.html>

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>index.html</title>
</head>
<body>
	
	<form action="page1">
        <!-- page1에 해당하는 곳으로 form태그 내 모든 input값을 전송(default : GET방식) -->
		
		id: <input type="text" name="id"><br>
		pw: <input type="password" name="pw"><br>
		interest: 
			Java <input type="checkbox" name="interest" value="Java">
			Python <input type="checkbox" name="interest" value="Python">
			기타 <input type="checkbox" name="interest" value="기타">
		<br>		
		
		<input type="submit">
	</form>
	
</body>
</html>

이렇게 form에 입력한 데이터들을 가지고 화면 이동하면 URL값은 http://localhost:8088/test/page1?id=abc&pw=123&interest=Java&interest=Python&interest=기타 이 된다. URL의 queryString 값을 가지고 화면에 출력하는 연습을 해보자.

<ServletTest.java>

package test;

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

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("/page1")  // url mapping값 : page1
public class ServletTest extends HttpServlet {
    
	// GET방식으로 데이터 전송하므로 doGet() 메소드 사용
	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
		
		// request값 한글 인코딩 설정
		request.setCharacterEncoding("utf-8");
		
		// queryString의 value값 획득
		String id = request.getParameter("id");
		String pw = request.getParameter("pw");
		String [] interest = request.getParameterValues("interest");
		
		// response값 출력형식 및 한글 인코딩 설정
		response.setContentType("text/html;charset=utf-8");
		
		// 클라이언트 브라우저에 출력가능한 객체 생성
		PrintWriter out = response.getWriter();
		out.print("아이디: " + id);
		out.print("<br>비밀번호: " + pw);
		out.print("<br>관심사: ");
		for(String v : interest) {
			out.print(v + " ");
		}				
	}

}

Written by@[hyem]
Hyem's Dev Note

GitHub