코딩관계론

JSP 어떻게 Servlet으로 변환되서 Client에게 전달되는가 본문

개발/Java

JSP 어떻게 Servlet으로 변환되서 Client에게 전달되는가

개발자_티모 2024. 6. 27. 01:36
반응형

JSP 어떻게 Servlet으로 변환되서 Client에게 전달되는지를 알기 위해서는 was가 무엇인지, 서블릿이 무엇인지, 서블릿 컨테이너가 무엇인지를 알고 있어야 이해하기 쉽다. 따라서 해당 개념을 먼저 설명한 후 JSP가 어떻게 변환되는지 설명하겠습니다.

 

1. 웹 요청과 Tomcat

먼저, 우리가 웹 브라우저에서 어떤 페이지를 요청하면, 그 요청은 패킷이라는 작은 데이터 묶음으로 서버에 전달됩니다. 이 패킷을 이해하고 처리하는 프로그램이 필요합니다. 이 프로그램을 WAS(웹 애플리케이션 서버)라고 부르는데, 자바에서는 Tomcat이라는 프로그램이 주로 사용됩니다.

 

웹 요청을 받는 Tomcat은 크게 두 가지 역할이 있습니다

  1. 웹 서버: 요청을 받아서 정적 파일을 보내주는 역활
  2. 서블릿 컨테이너: 요청을 받아서 자바 프로그램을 실행하고 그 결과를 보내주는 역할

요청 구조

 

2. 서블릿 컨테이너란

서블릿 컨테이너는 서블릿을 관리하고 실행하는 역할을 합니다. Tomcat, Jetty, WildFly 등이 대표적인 서블릿 컨테이너입니다. 이 서블릿 컨테이너가 필요한 이유는 생명주기 관리와 멀티스레드, 요청과 응답을 관리해주기 때문입니다 

생명주기 관리

서블릿 컨테이너는 개발자가 생성한 서블릿 클래스를 인스턴스화하기 위해서 다음과 같은 순서를 수행하게 됩니다. 

1.  @WebServlet 애노테이션을 스캔하여 서블릿 클래스를 찾습니다

2. 찾아진 클래스를 인스턴스화합니다.

3. init() 메서드를 호출해 객체를 초기화하는 과정을 수행합니다

멀티스레드

자바에서는 멀티스레드를 지원하는데 이 서블렛 컨테이너가 처음 시작할 때 쓰레드를 만들고 사용자 요청을 해당 스레드로 매핑해서 서블릿 서비스를 호출할 수 있게 해 줍니다.  이 서블릿은 싱글톤 서비스임으로 공유 변수 사용에 주의할 필요성이 있습니다

요청과 응답 관리

서블릿 컨테이너는 패킷을 수신받아 해당 패킷을 파싱해 HttpServletRequest 객체를 생성합니다. 이 객체는 HTTP 요청의 모든 정보를 담고 있으며, 서블릿이 요청을 처리할 수 있도록 합니다. 이렇게 생성된 HttpServletRequest 객체를 통해 서블릿 컨테이너는 클라이언트의 요청을 적절한 서블릿으로 전달하여, 요청에 대한 응답을 생성하고 반환할 수 있게 됩니다

 

3. 서블릿이란

서블릿은 HttpServlet을 상속받아서 구현한 클래스를 의미하며, 사용자의 웹 요청을 받아서 처리하고 응답을 돌려주는 역할을 수행합니다.

@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("Hello, World!");
    }
}

 

HttpServlet은 아래의 인터페이스를 구현하고 있습니다. 각 메서드의 역할은 다음과 같습니다.

  • init(ServletConfig config): 서블릿 초기화
  • service(ServletRequest req, ServletResponse res): 요청 처리
  • destroy(): 서블릿 종료 전 정리 작업
  • getServletConfig(): 초기화 정보 반환
  • getServletInfo(): 서블릿 정보 반환
public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

 

 

4. JSP의 등장 배경

서블릿을 사용하면 응답을 HTML로 작성할 때 코드가 길고 복잡해지게 됩니다. 이를 해결하기 위해 JSP(JavaServer Pages)가 등장했습니다. 

//서블릿을 사용해 응답 html을 생성하는 코드
@WebServlet("/example")
public class ExampleServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>Hello, World!</h1>");
        out.println("</body></html>");
    }
}

 

JSP는 HTML과 자바 코드를 함께 쓸 수 있는 파일입니다. 아래의 코드가 JSP파일의 형식입니다. 자바 코드를 사용하기 위해서는 <% %>를 사용하고, 코드를 출력하기 위해서는 <%= %> 형식을 사용한다.

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page import="java.io.*, java.util.*" %>
<html>
<head>
    <title>Simple Calculator</title>
</head>
<body>
    <h1>Simple Calculator</h1>
    <form method="post" action="calculate.jsp">
        <label for="num1">Number 1:</label>
        <input type="text" id="num1" name="num1" required><br><br>
        <label for="num2">Number 2:</label>
        <input type="text" id="num2" name="num2" required><br><br>
        <input type="submit" value="Calculate">
    </form>

    <%
        // 비즈니스 로직: 두 숫자의 합을 계산
        String num1Str = request.getParameter("num1");
        String num2Str = request.getParameter("num2");

        if (num1Str != null && num2Str != null) {
            try {
                int num1 = Integer.parseInt(num1Str);
                int num2 = Integer.parseInt(num2Str);
                int sum = num1 + num2;
    %>
                <h2>Result: <%= sum %></h2>
    <%
            } catch (NumberFormatException e) {
                out.println("<p style='color:red;'>Please enter valid numbers.</p>");
            }
        }
    %>
</body>
</html>

 

 

5. JSP의 처리 과정 

우리가 앞서 봤듯이 사용자의 요청은 서블릿으로 연결되게 된다. 그러면 JSP는 어떻게 서블릿으로 변환이 될까?

JSP가 서블릿으로 변환되는 과정을 요약하면 jsp를 자바 파일로, 자바 파일이 컴파일돼서, 바이트 파일이 생성되고, 이 바이트 파일이 실행되고, 이 실행결과가 클라이언트에게 반한 됩니다.

 

  1. 컴파일(Compilation):
    • 첫 요청 시: 클라이언트가 JSP 페이지를 요청하면, JSP 컨테이너는 해당 JSP 파일을 서블릿 클래스로 변환합니다. 이 변환된 서블릿 클래스는 자바 소스 코드로 생성되며, 컴파일러에 의해 컴파일되어 바이트 코드로 변환됩니다.
    • 변환 과정: JSP 파일의 각 코드 블록(<% %> 내의 Java 코드)은 서블릿 클래스의 service() 메서드에 해당하는 코드로 변환됩니다. HTML 부분은 그대로 유지되며, 동적 Java 코드는 서블릿 클래스 내의 메서드로 변환됩니다.
  2. 서블릿 인스턴스화 및 등록:
    • 첫 요청 시: JSP 파일이 처음 요청되면, JSP 컨테이너는 이를 서블릿으로 변환하고 이 변환된 서블릿 클래스를 로드하여 인스턴스화합니다. 이 인스턴스는 메모리에 올라가고, 서블릿 컨테이너에 의해 관리됩니다.
    • 이후 요청: 변환된 서블릿 클래스는 존재하며, 이후의 요청에 대해서는 추가적인 변환 작업 없이 해당 서블릿 인스턴스가 재사용될 수 있습니다. 이는 서블릿의 생명주기에 따라 관리됩니다.
  3. 실행과 응답:
    • 클라이언트의 요청이 들어오면, 서블릿 컨테이너는 해당 JSP에 대응하는 서블릿 인스턴스를 찾아서 service() 메서드를 호출합니다. 이 메서드는 요청을 처리하고, 동적으로 생성된 HTML을 클라이언트에 반환합니다.
    • JSP 페이지는 웹 애플리케이션의 다른 자원(데이터베이스, 다른 서비스 등)에 접근하여 복잡한 작업을 수행할 수 있습니다.

따라서 위의 JSP파일은 아래의 코드로 변환되게 됩니다. __jspService를 호출하는 서비스가 orverride 됩니다.

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

@WebServlet(name = "calculate", urlPatterns = {"/calculate.jsp"})
public class CalculateJSP extends HttpServlet {
    public void _jspService(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            // 비즈니스 로직: 두 숫자의 합을 계산
            String num1Str = request.getParameter("num1");
            String num2Str = request.getParameter("num2");

            if (num1Str != null && num2Str != null) {
                try {
                    int num1 = Integer.parseInt(num1Str);
                    int num2 = Integer.parseInt(num2Str);
                    int sum = num1 + num2;
                    out.println("<html>");
                    out.println("<head><title>Simple Calculator</title></head>");
                    out.println("<body>");
                    out.println("<h1>Simple Calculator</h1>");
                    out.println("<h2>Result: " + sum + "</h2>");
                    out.println("</body></html>");
                } catch (NumberFormatException e) {
                    out.println("<html>");
                    out.println("<head><title>Simple Calculator</title></head>");
                    out.println("<body>");
                    out.println("<h1>Simple Calculator</h1>");
                    out.println("<p style='color:red;'>Please enter valid numbers.</p>");
                    out.println("</body></html>");
                }
            }
        } finally {
            out.close();
        }
    }
}

 

 

6. JSP의 단점

하지만 이 jsp파일도 단점이 생기게 됩니다. 그 이유는 변경주기가 다른 코드들이 하나의 파일에 합쳐져 있습니다.(HTML + 비즈니스 로직)

이 경우에 유지보수 하기가 굉장히 힘들어지게 되고, 새로운 패러다임인 MVC 패턴이 나오게 되는 계기가 되었습니다.

반응형