본문 바로가기
🍃Spring ,SpringBoot 공부/스프링의 정석 : 남궁성과 끝까지 간다

[Spring 공부/스프링의 정석] 서블릿(Servlet)과 JSP - 1

by 코코의 주인 2022. 11. 8.

 스프링은 서블릿을 발전시킨 것이므로 스프링을 잘 이해하기 위해서는 서블릿에 대한 이해가 필요하다.

 

1. 서블릿(Servlet)과 Controller의 차이

 Servlet과 Controller의 선언부를 보면서 둘의 차이를 알아보겠다.

 

1) Servlet

@WebServlet("/hello")
	public class HelloServlet extends HttpServlet {
		@Override
		public void init() throws ServletException {
  • HttpServlet을 상속받는다.
  • 매개변수로 request와 response를 반드시 포함해야 한다.
  • URL mapping을 클래스 단위로 한다.

2) Controller

@Controller
public class LoginController {
	@RequestMapping("/login")
	public String loginForm() {
  • 상속이 없다.
    • 자바는 단일 상속이기 때문에 최대한 상속을 받지 않는 것이 유리함
  • 매개변수를 반드시 필요로 하지 않는다.
  • URL Mapping을 메서드 단위로 한다.
    • 하나의 클래스 안에서 또다른 Mapping이 가능함

Controller는 Servlet을 더 발전시킨 형태임을 알 수 있다.

 

 

2.  Servlet의 구조

@WebServlet("/hello")
	public class HelloServlet extends HttpServlet {
		@Override
		public void init() throws ServletException {  
			// 서블릿 초기화 - 서블릿이 생성 또는 리로딩 때, 단 한번만 수행됨.
			System.out.println("[HelloSerlvet] init()");
		}
		   
		@Override // 호출될 때마다 반복적으로 수행됨.
		public void service(HttpServletRequest request, HttpServletResponse response) {
			// 1. 입력
			// 2. 처리 
			// 3. 출력
			System.out.println("[HelloSerlvet] service()");
		}
	
		@Override   
		public void destroy() {   
			// 뒷정리 작업 - 서블릿이 제거(unload)될 때, 단 한번만 수행됨.
			System.out.println("[HelloSerlvet] destroy()");  
		}
	}
  • init()
    • 서블릿 초기화 - 서블릿이 생성 또는 리로딩 할때 수행된다.
  • service
    • 호출될 때마다 반복적으로 수행된다.
    • 실제 작업을 수행한다.
  • destroy
    • 뒷정리 작업 - 서블릿이 제거될 때, 단 한번만 수행된다.

 

 

3. 서블릿의 생명 주기

서블릿은 싱글톤(Singleton)패턴으로 만들어진다.

  • 한 개의 인스턴스를 생성 후 재활용함

1. 클라이언트로부터 요청이 들어옴

 

2. Servlet 인스턴스가 존재하는지 확인

 

3 - (1). 인스턴스가 없는 경우

  • Servlet 인스턴스를 생성함
  • 만들어진 인스턴스를 초기화함
  • 서비스 호출

3 - (2) 인스턴스가 있는 경우

  • 서비스 호출

4. 결과를 반환함

 

프로그램이 종료될 시 destroy()를 호출하여 인스턴스를 삭제함.


4. JSP(Java Server Page)

HTML에 Java 코드를 추가한 형태다.

  • <%! ... %>는 클래스 영역으로 변환됨
  • <% ... %>는 메서드 영역으로 변환됨
  • html부분은 out.println()으로 변환됨

JSP 예시

<%@ page contentType="text/html;charset=utf-8"%>
<%@ page import="java.util.Random" %>
<%-- <%! 클래스 영역 %> --%>
<%!  
	int getRandomInt(int range){
		return new Random().nextInt(range)+1;
	}
%>
<%-- <%  메서드 영역 - service()의 내부 %> --%>
<%
	int idx1 = getRandomInt(6);
	int idx2 = getRandomInt(6);
%>
<html>
<head>
	<title>twoDice.jsp</title>
</head>
<body>
	<img src='resources/img/dice<%=idx1%>.jpg'>
	<img src='resources/img/dice<%=idx2%>.jpg'>
</body>
</html>

 

변환된 Servlet 예시

@WebServlet("/rollDice2")
public class TwoDiceServlet extends HttpServlet {
    int getRandomInt(int range) {
	return new Random().nextInt(range)+1;
    }

    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
        int idx1 = getRandomInt(6);
        int idx2 = getRandomInt(6);

        response.setContentType("text/html");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("</head>");
        out.println("<body>");
        out.println("<img src='resources/img/dice"+idx1+".jpg'>");
        out.println("<img src='resources/img/dice"+idx2+".jpg'>");
        out.println("</body>");
        out.println("</html>");
        out.close();	    
    }
}

 

5. JSP 호출 과정

1. jsp 요청이 들어옴

 

2 - (1). Servlet 인스턴스가 존재하지 않음

  • JSP 파일 변환
  • JSP 파일 컴파일
  • Sevlet 인스턴스 생성
  • Servlet 인스턴스 호출

2 - (2). Servlet 인스턴스가 존재함

  • Servlet 인스턴스 호출

3. 결과 반환


6.늦은 초기화(Lazy-init)와 빠른 초기화(Early-init)

객체가 생성되고 초기화하는 과정이 언제 이루어지는 지에 따라 늦은 초기화와 빠른 초기화로 나눌 수 있다.

1) 늦은 초기화(Lazy-init)

  • 클라이언트로부터 요청이 들어올 때 객체를 생성함
  • Servlet의 경우

2) 빠른 초기화(Early-init)

  • 클라이언트에게 요청이 오기 전에 객체를 생성해둠
  • 스프링의 경우

Servlet의 경우 늦은 초기화를 사용하기 때문에 인스턴스를 처음 호출했을 때와 두번째로 호출했을 때 응답 속도가 다르다. 첫번째 호출의 경우 인스턴스를 생성하는 데 시간이 필요하기 때문이다.


총평

아 재밌다.

댓글