[ KOSTA 교육 26일차 ] 웹서버 vs 클라이언트 | HTML | HTTP Protocol | Session, Cookie | CGI | 서블릿 | 프로세스 vs 쓰레드 | JSP MVC Pattern | 직렬화, 역직렬화 | 기본 태그 - form, input, select, textarea | input 속성 type = {"text", "password", "radio", "checkbox", "file", "hidden", "submit"

junjun·2024년 5월 21일
0

KOSTA

목록 보기
23/48

Servlet

  • 네트워크를 통해 접근할 수 있는 Java Program

웹서버(Server)

  • 네트워크에서 서비스를 제공하는 프로세스

클라이언트(Client)

  • 네트워크에서 서비스를 요청하는 프로세스

HTML

  • 웹 서비스를 제공하기 위한 마크업 언어

HTTP Protocol (HyperText Transfer Protocol)

  • TCP/IP 프로토콜을 기반으로 웹 서버와 클라이언트 간 웹 서비스를 제공하기 위한 통신 규약

  • 요청(Request)응답(Response)으로 구성됨.

  • 즉, 클라이언트서버 역할이 구분됨.

  • 서버가 클라이언트의 상태를 유지할 수 없는 Stateless Protocol의 특징을 가진다.

  • 요청마다 서버는 클라이언트와 새로운 접속을 맺고 응답을 전송한다.

  • 서버는 요청에 대한 응답을 전송하면, 해당 클라이언트의 어떠한 상태정보도 유지하지 않는다.

  • 웹 상에서 클라이언트의 상태를 유지하기 위해 Session, Cookie를 사용한다.

  • 쿠키는 브라우저에서 저장하고, 보안에 취약하다. 중요한 정보는 쿠키에 담으면 안된다.

  • 세션은 서버에서 저장하기에, 중요한 정보를 저장해도 된다.

그럼 쿠키는 나쁜거고, 세션은 좋은거. 이렇게 일반화해도 되는것일까?
  • 세션의 문제점) 네이버 도메인을 공유하는 네이버 카페, 네이버 메일, 네이버 쇼핑몰.. 이렇게 여러 개의 서비스에서 여러 서비스를 이용할 때마다 로그인을 하지는 않는다.

그럼 카페 서버 / 메일 서버 / 쇼핑몰 서버 가 있을 때, 유저의 정보를 네트워크로 쏠까?
만약 패킷이 스니핑 당한다면 큰일날 것이다.

쿠키를 통해 이 문제를 해결할 수 있다.

  • 쿠키 정보는 서버 단이 아닌, 도메인 단에서 관리한다.

  • 쿠키는 도메인이 맞으면 통과시킨다.

  • 그렇기에, 한 도메인 내에 여러 개의 서버를 두고 운영하는 서버의 경우에는
    세션과 쿠키를 반드시 써야한다. ( 쿠키는 도메인이 같으면 통과됨 )

HTTP Protocol

  • Host

  • User-Agent

  • Encoding 정보

  • HTTP Header ( A Byte ~ B Byte 까지 인코딩 정보.. X Byte ~ Y Byte 까지 호스트 정보.. 등의 정보들이 미리 규칙으로 잡혀있다. )

  • HTTP Header는 노출이 됨. Header에 있는 데이터는 아무나 다 볼 수 있다. ( WireShark )

HTTP Method - GET 방식의 특징

  • 게시글 작성 이런 곳에서 GET 방식으로 쓰면, 주소창에 데이터가 다 보인다.

  • GET 방식의 한계

  1. 보안에 취약하다
  2. 보낼 수 있는 양에 제한이 있다.
  • 보여도 되는 것, 짧은 것에 GET을 쓴다.
    ( ex. 회원가입 시 ID/PW는 길이가 짧아서 GET으로 충분히 보낼 수 있는데..?
    URL에 데이터가 그대로 노출되기에 보안에 매우 취약 )

  • SEO를 위해 노출하면 좋을 정보인데,
    데이터 양이 많아서 어쩔 수 없이 POST를 사용할 수도 있다.
    (ex. 남들이 다 봐줬으면 좋겠는 카페에 글 쓰기.. 양이 너무 많아서 POST로 밖에 전송 못함. )

HTTP Method - POST 방식의 특징

  • HTTP Body에 데이터를 담는다.

  • URL이나 Header에 전송 정보가 노출되지 않는다.

  • 주로 서버에게 특정 데이터를 보내서 어떤 작업을 요청하는 경우에 사용한다.

  • GET보다는 보안에서 좋다.

Web Browser는 GET / POST 방식으로만 요청이 가능하다. ( 사실 OPTIONS과 같은 메소드는 CORS 요청을 위해 미리 사용 가능하지만 논외 )
  • PUT, PATCH 등의 메소드는 JS 요청 / 서버 - 서버간의 요청 등으로만 가능. ( RestTemplate, FeignClient ..)

HTML & HTTP Protocol

  • 초창기 HTTP 1.0 프로토콜은 웹 상에서 HTML을 전송하기 위한 목적의 프로토콜이었다.

  • 기능이 확장되어 Data를 보내는 등 API 방식으로 동작 가능하다.

  • HTML은 왜 Header로 못보내나요?
    - HTTP Protocol Spec 상 Header에 담아 보낼 수 있는 데이터의 양이 제한되기 때문

HTTP 요청 ( Post 방식 )

HTTP 응답

  • 포함되는 것
    - Status Code & 상태코드에 대한 텍스트 버전
    • Content-Length ( Byte 단위 )
    • Content-Type
    • Server
    • Connection : close, keep-alive

CGI ( Common Gateway Interface )

  • C 기반
  • 1990년 초 웹 서비스를 위해 만들어진 방식 ( 방식이지, Language가 아님 )
    - CGI 방식을 구현하는 Language
    • C, Perl, ASP, Java Servlet..
  • 서버에서 데이터를 내리는 용도로 사용됨.
  • 서버와 클라이언트 간에 정보교환을 가능하게 해주는 인터페이스
  • 단점 : 프로세스로 움직인다.
    - 동일 요청 시, 하나의 프로세스에서 처리해주는 것이 아닌, 여러 개의 프로세스를 만듬.
    • 예전에 라이코스 라는 어플리케이션은 새로고침(F5)를 누르면 프로세스를 생성한다.
    • F5 키에 테이프 꼽고 나가면 메모리 초과로 서버가 누워버렸음.
    • 예전에도 네이버는 안그랬음.
  • 웹 서버에서 요청 수행 후 클라이언트의 결과값을 HTML 형태로 전송

프로세스 vs 쓰레드

  • 공장과 작업자들의 관계이다.

  • 작업자는 한가지 일만 처리할 수 있다.

  • 크롬 : 프로세스
    - 크롬의 키보드 리스너 기능 담당 작업자.( Ctrl + T 누르면 화면 이동, Ctrl + N 누르면 새 창 생성 .. )

    • 크롬의 화면 랜더링 기능 담당 작업자.
  • 프로세스 안에 쓰레드는 엄청나게 많음.

서블릿

  • 서버에서 실행되는 동적 컨텐츠를 생성하는 자바 기반 웹 컴포넌트

  • 컴포넌트(Component)
    -구성요소라는 의미를 가진다.

    • 웹을 만드는 데에 필요한 구성요소
    • Java Language로 웹을 만드는데 필요한 구성요소이다.
  • 바이트 코드로 컴파일된 플랫폼 독립적인 자바 클래스

  • 웹 서비스 개발에 필요한 자바 클래스

  • 서버-사이드 애플릿(Server-Side Applet)

  • 서블릿 컨테이너에 의해 관리된다.

  • 컨테이너 : 서버에서 특정 업무를 담당하는 영역 / 서블릿 코드를 관리하는 영역 / 환경을 마련해준다.

  • 서블릿 컨테이너는 Tomcat (WAS)이 관리한다.
    - 유료 WAS인 Jeus, WebLogic 또한 있다.

  • WASJVM의 관계
    - WASVM 위에 있다.

    • - Tomcat( WAS )는 VM을 기반으로 해서 동작하고, WAS 안에 Servlet Container가 있다. VM위에 Spring Container가 있다.

서블릿과 쓰레드

  • HttpServlet라는 추상 클래스를 상속받아 구현하고자 하는 기능을 오버라이딩 하는데 대표적으로 init(), service(), destroy() 메소드가 존재한다.

  • init(), service(), destroy() 는 대표적인 쓰레드의 메소드이다.

  • 즉, 서블릿은 쓰레드이다.

  • 단일 프로세스에, 요청이 들어올 때마다 프로세스 내에서 쓰레드를 생성하는
    멀티 쓰레드 방식으로 동작한다.

  • 아무리 과도하게 호출 요청을 해도 OS가 누울 일이 절대 없다는 것이 장점.

서블릿의 장점

  • 쓰레드를 기반으로 하므로, Web Application 운영에 효율적이다.

  • 자바를 기반으로 하므로 모든 Java API를 사용할 수 있다.

  • 웹 어플리케이션에서 효율적인 자료 공유 방법을 제공한다.

  • 요청이 들어올 때마다 Servlet Thread가 init되어 생성된다.

HTML과 JSP

  • JSP는 결국 HTML이다.

  • JSP 내에 Java Code를 넣을 수 있다.

  • 서블릿은 Java Code에 HTML 을 넣었다면, JSP는 HTML 코드에 Java Code를 넣는 방식으로 동작한다.

  • JSP는 결국 Servlet Container에 의해 컴파일 되어 Servlet으로 변환된다. ( JSP -> Servlet )

  • <%@ %> : 페이지 지시자 / JSP가 서블릿으로 변환될 때, 어떻게 변환되어야 하는지 컨테이너에 알려주는 역할을 한다.

  • <% %> : Scriptize : HTML 안에 Java 코드를 사용한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<% for(int i = 0; i < 3; i++){
	out.println(i);
	System.out.println(i);
   }
%>

</body>
</html>
  • 여기서 out 은 jspWriter로 JSP 자체의 내장 객체이다.
    JSP가 Servlet으로 변환될 때, 해당 Servlet화 된 클래스 내에 out이라는 jspWriter 타입(PrintWriter)이 내부적으로 미리 선언되어 있다.

서블릿 동작 과정

    1. 사용자로부터 요청이 들어온다.
    1. Tomcat의 ServerSocket이 해당 요청을 받아, web.xml 설정을 참고하여, 이 요청을 처리할 Servlet 코드를 실행할 쓰레드를 할당하려 한다.
    1. 해당 서블릿이 JVM의 Method Area에 올라와있지 않으면, Class Loader에게 동적 클래스 로딩을 요청한다.

서블릿과 MVC 패턴

    • 동적인 웹을 서블릿을 통해 충분히 구현할 수 있지만, Java 코드에서 Writer 객체를 가져와 HTML 을 직접 생성해서 보내야하는 문제가 있었다.(response.getWriter().append...)
  • 또한, 서블릿에서 요청을 받고, 비즈니스 로직 실행 후 뷰까지 렌더링하는, 너무 많은 책임을 가지고 있었다.

  • 비즈니스 로직과 View를 분리한 JSP를 도입하고, 뷰 단에 넘겨줘야할 데이터를 Model에 담음으로써 역할 분리를 이뤄냈다.

  • JSP의 한계 또한 존재했는데, 컨텐츠 자체와 비즈니스 로직이 분리되지 않았다. ( 과도한 책임 - 단일 책임 원칙 위배 )

  • 어플리케이션을 구성 요소 단위로 분리하여 역할 분담을 이뤄냈다.

  • Model & Business Logic : Java Class ( VO, DAO, DTO )

  • View : JSP, JSTL

  • Controller : 서블릿

서블릿을 통한 Web Application 동작 과정 (BE)

  • JSP는 서블릿 컨테이너에 의해 Servlet으로 다시 변환된다.

서블릿 라이프 사이클

브라우저의 GET / POST 요청 방식에 따른 사용

init, service의 동작과정

init, service, destroy 생명주기 & 쓰레드

Class Loading & Reflection API를 통한 Instance 동적 생성 & init() 이후 여러 쓰레드로 인해 생성되는 service() 서블릿 소멸 시 수행되는 destroy()

  • 서블릿은 Factory를 통해 관리되며 싱글톤 방식으로 생성됩니다.

Servlet API ( javax.servlet.. / jakarta.servlet.. )

  • 서블릿의 개발실행을 가능하게 하는 인터페이스와 클래스들의 모임

  • J2EE에서 추상화된 개념

  • HTTP에 특화된 하부 클래스들을 제공함. ( cf. GenericServlet )

  • 일반적인 서블릿은 HttpServlet 클래스로부터 파생됨.

    	- HTTP에 특화된 요청 핸들러 doGet(), doPost() 등을 제공함.
    • 요청과 응답을 Encapsulate 할 수 있는 객체들을 제공함 ( HttpServletRequest, HttpServletResponse )
    • 다른 서비스와 객체들에 대한 엑세스를 제공 ( Session, ServletContext, init params )

서블릿은 HTTP만을 위한 API가 아니다.

  • 상속 계층도에서 HttpServlet보다 상위에 있는 GenericServlet의 경우, FTP / SMTP등의 요청도 수용한다.

  • HttpServlet class의 코드에서 파라미터가 ServletRequest, ServletResponse 인데, 이것을 (HttpServletRequest), (HttpServletResponse) 로 다운캐스팅 하는 이유가 바로 이 이유이다.

  • 서블릿은 서버에서 실행되는 동적 컨텐츠를 생성하는 자바 기반 웹 컴포넌트이지, HTTP만을 위한 컴포넌트가 아니다. 자주 사용되는 것이 HTTP 프로토콜일 뿐이다.

  • GenericServlet은 모든 프로토콜을 수용한다.

    • HTTP 프로토콜 뿐이 아닌, SMTP, FTP 등등의 프로토콜 또한 수용할 수 있다.
    • HTTPServlet에서 ServletRequest / ServletResponse 를 HttpServletRequest , HttpServletResponse 로 다운캐스팅 하는 이유 ( ⇒ 웹 관련 서비스만 수용 )
    • SMTP, FTP 등의 프로토콜을 수용하는 Servlet이 되려면?
      • GenericServlet을 상속받아야 한다.

Servlet, GenericServlet, HttpServlet 상속 계층도 & 주요 메서드

maybeSetModified → 언제 마지막으로 쓰였는지 → GC에게 제공하기 위한 정보.

HttpServletRequest vs HttpServletResponse

HttpServlet이 Abstract Class로 설계되어야 하는 이유?

  • 인터페이스는 공통의 기능이 없다.
    또한, 구현 메서드 사이사이에 특정 메서드 호출을 강제하지 못한다.

  • 서블릿이라면 가지고 있어야할 스펙인
    init(), doGet(), doPost(), destroy() 등의
    공통된 기본 기능을 주고 관리해야하기에 사용한다.

실습 - BoardServlet 작성

/**
 * Servlet implementation class BoardServlet
 */
@WebServlet("/board_servlet_url")
public class BoardServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

    /**
     * Default constructor. 
     */
    public BoardServlet() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Servlet#init(ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init called");
		// TODO Auto-generated method stub
	}

	/**
	 * @see Servlet#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String method = request.getMethod();
		System.out.println(method);
		if(method.equals("POST")) {
			doPost(request, response);
		} else if(method.equals("GET")) {
			doGet(request, response);
		}
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().write(1);
//		response.sendRedirect("lec_servlet_call.jsp");//		response.sendRedirect("index.html");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String vUserId = request.getParameter("userid");
		String vUserPw = request.getParameter("userpw");
		String vGen = request.getParameter("gen");
		String vSubject = request.getParameter("subject");
		String vUserfile = request.getParameter("userfile");
		String vSsn = request.getParameter("ssn");
		String vContents = request.getParameter("contents");
		String[] vHabits = request.getParameterValues("habit");
		
		System.out.println(vUserId);
		System.out.println(vUserPw);
		System.out.println(vGen);
		System.out.println(vSubject);
		System.out.println(vUserfile);
		System.out.println(vSsn);
		System.out.println(vContents);
		System.out.println(vHabits);
	}
}

실습 - servlet_call.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
GET 호출
<!-- <a href="localhost:8081/board_servlet_url">서블릿 GET 방식 요청</a> -->
<a href="/board_servlet_url">서블릿 GET 방식 호출</a>

<form method="get" action="/board_servlet_url">
	<input type="submit" value="서블릿 GET 방식 호출">
</form>

<form method="post" action="/board_servlet_url">
	
</form>

<form method="post" action="/board_servlet_url">
	<input name="userid" type="text"><br>
	<input name="userpw" type="password"><br>
	<input name="gen" value="m" type="radio"><input name="gen" value="f" type="radio"><br> 
	
	
	<input name="habit" value="habit" type="checkbox">낚시<br>
	<input name="habit" value="habit" type="checkbox">드럼<br>
	<input name="habit" value="habit" type="checkbox">노래<br>
	<input name="habit" value="habit" type="checkbox">독서<br> 
	
	<select name="">
		<option value="kor">국어</option>
		<option value="eng">영어</option>
		<option>수학</option>
	</select><br>
	
	<input type="file" name="userfile">파일 선택 <br>
	
	<input type="hidden" name="secret" value="12345"><br>
	<!-- 게시판에서 서버로 넘겨야하긴 하는데, 사용자에게 입력 안받는 것? (Seq) -->

	<textarea name="contents" rows=10 cols=50>
	</textarea> <br>
	<input type="submit" value="서블릿 POST 방식 호출">
</form>

</body>
</html>

직렬화, 역직렬화

Serialize

직렬화 ( 객체 → 바이트 )

  • 객체를 바이트로 만드는 과정이다.
  • 객체를 인코딩한다. ( 바이트로 만드는 것 )
  • 객체를 바이트로 인코딩하는 것이 직렬화

Deserialize

  • 바이트에서 객체로 디코딩하는 것이다.

0개의 댓글