[웹 개발] 4. Servlet

0woogie·2023년 8월 14일
0

동기 VS 비동기

동기 요청

  • Servlet: 클라이언트 요청을 처리(Program), Servlet이 요청을 처리할 때 DB 접근하는데 이때 생기는 데이터를 jsp에게 넘겨줌
  • jsp: 데이터를 최종적으로 클라이언트에게 응답하는 역할

Servlet 실행 후 반환받은 데이터를 jsp에게 전달한다.
데이터를 가진 jsp가 결과페이지가 된다.
응답은 jsp 결과 페이지를 뜻한다.

비동기 요청

화면은 서버에서 만들어지는 것이 아니라 클라이언트 측에서 데이터를 받아서 직접 작성한다.
=> 다양한 Device들에 대한 화면 구성을 클라이언트 측에서 자유롭게 할 수 있음
=> 클라이언트와 서버의 분리

서버 설정 및 프로젝트 생성

Tomcat 서버를 Eclipse와 연동하고 나서 서버를 처음 실행하기 전에 설정을 바꿔줄 수 있다.

  • Use Tomcat installation 선택
    - 지정된 Tomcat 경로를 통해 서버를 실행하기 위해 선택
  • Deploy path 설정
    - webapps: 작성한 코드가 context-path 단위로 배포되는 위치의 상위 폴더

  • Dynamic Web Project 생성하기 (web01_Servlet)
  • Servlet을 제대로 배우기 위해 2.5 version 선택

  • DD 파일 (Deployment Descriptor)
    - 2.5 version으로 프로젝트를 생성하면 DD 파일을 자동으로 생성해준다.
    • web.xml이 DD 파일 (web.xml에 역할에 대해서는 이후 정리)

Request & Response

  • Webserver가 Container에 요청을 넘길 때 Container는 request, response, thread를 만든다.
  • thread는 요청을 수행하는 단위로, thread == service 메서드라고 생각하면 된다.
  • 클라이언트의 요청은 서블릿 안에서 thread 단위로 수행된다.
    - 요청이 오면 이를 처리하기 위해 thread 하나가 메모리에 올라간다.
  • 요청을 처리했다면 thread 그리고 그 안에서 로컬로 존재하는 ServletRequest, ServletResponse 또한 메모리에서 Death 된다. Servlet(Process)이 죽는 것이 아님!!
  • 이를 통해 메모리 효율성이 개선됨 (->멀티쓰레드)
  • Servlet은 Process, service()는 Thread

Project - Web01_Servlet

구성 요소

  • MyGenericServlet.java
  • hello1.html
  • web.xml

MyGenericServlet.java

package web.servlet.generic;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/*
 MyGenericServlet 서블릿 클래스는 자바 기반으로 만들어진 클래스
 자바클래스	---		JVM(Platform)
 서블릿 		---		Container(WAS, Engine)
 */
public class MyGenericServlet extends GenericServlet {

	@Override
	public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
		//웹 브라우저로 응답을 하기위한 객체
		PrintWriter out = response.getWriter();
		out.println("<html><body><h2>");
		out.println("Hello Generic Servlet~!!");
		out.println("</h2></body></html>");
		
		out.close();
	} //클라이언트 응답이 끝났다 == thread, request, response 객체는 메모리에서 내려온다

}

hello1.html

<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>Request</h2>
<a href="My">서블릿으로 요청</a>
</body>
</html>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<!-- 
web.servlet.generic.MyGenericServlet MyGenericServlet = new web.servlet.generic.MyGenericServlet();
 -->
<servlet>
	<servlet-name>MyGenericServlet</servlet-name>
	<servlet-class>web.servlet.generic.MyGenericServlet</servlet-class>
</servlet>

<!-- 클라이언트 매핑 -->
<servlet-mapping>
	<servlet-name>MyGenericServlet</servlet-name>
	<url-pattern>/My</url-pattern>
</servlet-mapping>
</web-app>
  • EE 레벨에서는 개발자가 아닌 컨테이너가 객체를 메모리에 올리게 된다.
  • 즉, 객체 생성의 주체는 컨테이너(Servlet)이고 xml을 이용한다.
  • 상단의 코드는 두 가지 역할을 수행한다.
  1. 객체를 메모리에 로딩

    web.servlet.generic.MyGenericServlet MyGenericServlet = new web.servlet.generic.MyGenericServlet();

  2. 서블릿 매핑

서블릿 매핑

  1. 서버 내부 매핑
<servlet-name>MyGenericServlet</servlet-name>
<servlet-class>web.servlet.generic.MyGenericServlet</servlet-class>

서블릿 클래스의 이름과 별칭의 매핑

  1. 클라이언트 매핑
<servlet-name>MyGenericServlet</servlet-name>
<url-pattern>/My</url-pattern>

서블릿 클래스 별칭과 url의 매핑

  • 클라이언트는 /My를 통해 MyGenericServlet에 접근하고 이는 내부적으로 web.servlet.generic.MyGenericServlet을 의미한다.

실행 화면


Servlet API

  • GenericServlet: 컨테이너에서 실행되는 자바 기반의 프로그램, CGI 기술

    CGI 기술: 컨테이너 환경에서 실행되는 프로그램 (Servlet, ASP, PHP, Pear..)

  • ServletConfig
    - 하나의 서블릿을 초기화하는 역할
    - getInitParameter는 Servlet Life Cycle의 init()에서 동작
    - init()은 사용자 요청이 오는 시점이 아니라, 서블릿 생성 직후에 돌아감
    - 초기화 시 이용하는 정보는 DD 파일(web.xml)에서 가져옴
    - getServletContext(): ServletContext 인터페이스와 association

  • ServletContext
    - 하나의 서블릿이 아니라 Global한 초기화를 수행
    - 대표적인 메서드: setAttribute(), getAttribute(), getInitParameter()
    - 여기서의 getInitParameter()는 ServletConfig의 getInitParameter()와 scope가 다르다.

  1. GenericServlet, Servlet, ServletConfig..
    • javax.servlet 패키지에 존재
    • 해당 패키지는 프로토콜 독립적인 패키지 (ftp 등 다른 통신의 요청도 처리할 수 있음)
  2. HttpServlet..
    • javax.servlet.http 패키지에 존재
    • 해당 패키지는 프로토콜 종속적인 패키지 (http 통신의 요청만 받을 수 있음)
    • Http 통신에 집중, 이에 특화된 기능

서블릿에서 폼값 받아오기 (여기부터)

Annotation

xml을 짧게 표현한 것
4.0 버전에서는 web.xml을 직접 만드는 것이 아니라
annotation을 컨테이너가 보고 web.xml을 만든다.

GET 방식

GET VS POST


사진 교체 필요
login.html 주석 참고


참고사진

Context & Servlet Life Cycle

사진 교체 필요

  • Client가 요청하기 전 준비 상태 (1~4번)
  1. Contatiner는 DD 파일(web.xml)을 읽어들인다.
  2. ServletContext 생성, by Container
  3. 서블릿 생성
    • 기본 생성자 호출, by Container
  4. ServletConfig 생성
    • init() 호출 (calling by Container) -> ServletConfig pass into
  • 요청이 들어올 때마다 반복 (5~8번)
  1. req, res, thread 객체 생성
  2. service() ---> doGet()
    ---> doPost()
    이때 req, res 객체가 인자값으로 passing into
  3. doGet(){ } | doPost(){ } 응답을 완료
  4. req, res, thread 객체가 메모리에서 unbind -> Death
    //////////////////////////////////////////
  5. destroy() 호출 -> 서블릿 Death
  • 4~7번: 요청이 들어올때마다 반복됨

Lazy Loading

첫 번째 클라이언트의 요청이 들어오면 그제서야 Ready On 상태까지의 과정을 수행함
이를 Eager Loading으로 바꾸기 위해서는 xml에 아래와 같은 코드 추가

<load-on-startup>1</load-on-startup>

혹은 web03_LifeCycle과 같이 web.xml을 작성하지 않는 방식이라면 어노테이션을 아래와 같이 작성

@WebServlet(urlPatterns ={"/Life"}, loadOnStartup = 1)

서블릿이 값을 받는 통로


사진 교체 필요

  • Ready On 상태 --- 컨테이너 차원의 Extra Resource
  • 클라이언트 요청시 --- 웹브라우저 화면의 폼값

web05_MultiFrom

HttpServletRequest 폼값 받아오는 기능
getParameterValues 포함

Servlet과 JSP의 역할분담

  • Servlet은 로직중심, JSP는 태그중심
    Attribute: 서버 내에서 정보를 저장하는 공간
    setAttribute()와 getAttribute()하는 컴포넌트가 다르다.
    getAttribute() 사용하는 컴포넌트: 결과 페이지를 보여주는 JSP

"그림"과 같이 구조를 만들 예정
-> web06_Forward

Attribute

서버 내에서 데이터를 저장하는 일종의 공간
1. 데이터를 바인딩 - setAttribute("이름", 객체)
2. 저장된 데이터를 찾아옴 - getAttribute("이름")

  • Attribute의 세 종류
    - ServletRequest: 응답하기 전까지만 데이터가 유지
    - HttpSession: 로그인하는 동안에만 유지
    - ServletContext: 서버가 멈출때까지 유지

상황에 맞게 적절한 Attribute를 사용하는 것이 핵심

Forwarding VS Redirect

  • forwarding: 서버상에서 바로 다른 페이지로 이동하는 방식
  • Redirect
    - 브라우저를 한번 거침
    - 다른 서버에 요청을 보낼 수 있음
    - 사용해야하는 상황 정해져있음(ex>에러페이지 핸들링), 대부분은 forwarding 사용

웹 서비스 실행까지의 작업 순서

  1. 코드를 작성
    Static Document / Dynamic Document
  2. 프로그램 Dynamic Document -> 컴파일 성공 -> 실행파일(~.class)
  3. 서버 가동
  4. 소스코드 서버 안으로 배포
  • WEB-INF: SD/DD를 구분하는 기준이 되는 디렉터리
    WEB-INF를 기준으로 상위에는 SD, 하위에는 DD가 위치함
  1. 브라우저로 요청
    http://server IP:port/ContextPath/요청이름

Connection Pooling

Web09_CafeMember

  1. WAS에 Resource Factory를 등록 (context.xml을 이용)

JSP

EL

  • getAttribute() == ${}
    - ${a} -> ServletRequest, HttpSession, ServletContext 순서로 a라는 이름의 Attribute 찾음

JSTL

  • EL이 처리할 수 없는 제어문/반복문을 위해 필요
  • JSTL 하기 위한 사전 작업
    1. jstl.jar / standard.jar 파일을 추가
    2. taglib 옵션을 jsp 선언부에 등록

MVC Pattern

  • 장점
    - 비지니스 로직이 각각 모듈화되어서 호출됨
    - 요구사항이 변경되더라도 다른 컴포넌트에 영향을 끼치지 않음
    => 확장성이 있다
  • 단점
    - 하나의 요구사항(비지니스 로직)을 처리하기 위해서 그에 대한 서블릿이 응대한다
    => Too much

FrontController Pattern

  • MVC Pattern과 달리, 요구사항(비지니스 로직)을 처리하는 단위가 제어문에 따라 달라짐

  • 메서드 단위로 요구사항 처리 (MVC Pattern은 서블릿 단위로 처리하는 반면에..)

  • 장점
    - 하나의 서블릿이 모든 요청을 다 처리한다.

  • 단점
    - 하나의 서블릿에서 모든 비지니스 로직을 메서드 단위로 처리하다보니
    => Heavy Controller, Fat Controller

Factory Method Pattern

profile
정리하고 다듬기 위한 공간

2개의 댓글

comment-user-thumbnail
2023년 8월 14일

좋은 글이네요. 공유해주셔서 감사합니다.

1개의 답글