본문 바로가기
Java/Spring | SpringBoot

[Servlet, JSP and Spring] Servlet & JSP

by wiggleji 2022. 11. 6.

 

 

시리즈 목차

- Servlet & JSP

- Servlet & Servlet container

- 그리고 Spring


제주 보롬왓

“Those who don't know history are doomed to repeat it.”
역사를 모르면 그것을 반복하기 마련이다.
-Edmund Burke

 

Python, Django를 거쳐 Spring, SpringBoot 를 공부하며, 공통점으로 느낌 점이 하나 있다.

프레임워크라는게 더 빠르고 편한 개발을 위해 만들어진 도구이지만, 이에 종속된 개발을 할 수 밖에 없는 양날의 검이라고 생각했다.

문득 이렇게 편한 도구 뒷편(내부)의 세계와 이가 만들어지기 전의 모습을 알아야 내가 사용하는 도구를 이해함으로써 다른 이들에게도 합리적인 의사를 전달할 수 있겠다 느꼈다.

회사의 Servlet 코드를 시작으로 이에 대해 더 공부하고 Spring으로 이전하기 위해 정리하게 되었다.

 

 


public String resolveTokenFromRequest(HttpServletRequest request) {
    // JWT 인증과정에서 request의 Authorization 헤더를 확인하는 메소드

    String bearerToken = request.getHeader("Authorization");
    if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
        return bearerToken.substring(7, bearerToken.length());
    } else return null;
}

 

Spring 베이스로 코드를 작성하면 Servlet를 직접 사용하는 코드보다는 아래와 같이 Controller, Service, DAO, DTO 를 구성하는 POJO 형태의 코드를 보게된다.

 

@RequiredArgsContructor
@RestController
@RequestMapping("/auth")
public class AuthController {

    private final AuthService authService;

    @PostMapping("/login")
    public ResponseEntity<?> userLogin(@RequestBody UserLoginDto loginDto) {
        // 로그인 로직 시작
        // ...
    }
}

Spring의 코드를 보면 ServletRequest, Servlet Container 등 Servlet이 포함된 용어를 볼 수 있다.

이번 편에서는 Servlet과 JSP는 무엇이고, 둘의 차이점에 알아본다.

 

만약 Servlet과 JSP의 차이에 대해 빠른 이해가 필요하다면 아래 블로그 글을 읽어보자.

https://gmlwjd9405.github.io/2018/11/04/servlet-vs-jsp.html

 


JavaEE (현재는 JakartaEE)

국내외 많은 기업에서 Java 는 enterprise 급 어플리케이션을 만드는데 많이 이용된다. 그 외 여러 언어와 프레임워크도 존재하지만, 문법과 구조가 조금 다를 뿐, 웹페이지를 제공하는 웹서버와 동적인 데이터처리를 하는 WAS의 역할을 동일하게 수행한다.

웹서버(WEB)과 웹어플리케이션(WAS)의 구조와 차이는 아래 글을 참고하자. 매우 깔끔하게 정리를 잘해주셨다.

https://gmlwjd9405.github.io/2018/10/27/webserver-vs-was.html

 

 

웹이 처음 등장했을 땐 정적인 HTML 페이지에 필요한 정보를 전달하는 흐름을 가졌다. 그 속에서 웹서버는 외부로부터 요청한 URL에 맞는 페이지 소스를 반환해주는 형태였고, 이후 로그인/쇼핑/채팅 등 여러 복잡한 로직을 동적으로 처리하며 좀더 유연한 웹 어플리케이션을 개발하기 위해 Java에서는 Servlet과 JSP가 주로 사용되었다. 두 가지의 차이점에 대해 알아보자.

 

Servlet

Java 클래스 형태로 코드가 작성되어 여러 request-repsonse 웹 요청에 대한 동적인 처리가 가능하도록 사용된다. javax.servlet 패키지 코드와 주석을 살펴보자.

// javax.servlet.Servlet

package javax.servlet;

import java.io.IOException;

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

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

    String getServletInfo();

    void destroy();
}

// javax.servlet.http.HttpServlet
import ...

public abstract class HttpServlet extends GenericServlet implements Serializable {
    private static final String METHOD_DELETE = "DELETE";
	private static final String METHOD_HEAD = "HEAD";
    ...
	
    public HttpServlet() {}
	
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }
    }
    ...
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }
    ...
}

javax.servlet.Servlet 인터페이스 주석

Servlet 은 웹서버 위에서 실행되는 자바프로그램이며, 주로 HTTP 를 통해 웹 클라이언트의 요청을 받아 처리하며, 웹 개발에서는 주로 HttpServlet을 상속받아 사용한다.

 

servlet은 life-cycle을 가지는데, init - service - destroy 순으로 메소드가 호출되며 관리된다.

  • init: servlet이 생성자로 인스턴스가 생기고, init 메소드를 통해 초기화된다.
  • service: 클라이언트의 호출을 처리한다. doGet, doPost 등 메소드로 분기한다.
  • destroy: servlet 인스턴스를 삭제할때 호출되며, Servlet에서 사용되는 자원을 추후 GC가 처리한다.

HttpServlet 클래스속 doGet과 doPost 메소드를 살펴보면 HTTP 요청을 처리하기위한 GET, POST, PUT, DELETE 에 따른 메소드(doGet, doPost, doPut, doDelete)와 Servlet 인터페이스를 implement 한 GenericServlet 을 상속받아 init, service, destory 메소드 등을 가지고 있다.

 

javax.servlet.HttpServlet 상속구조

Oracle API 문서: https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html

 

 

위 구조와 코드를 보면, Servlet은 요청과 응답을 처리해주는 Java 객체로 동적 처리에 필요한 기능을 가지는 것을 확인할 수 있다.

 

신기한 점은 GET, POST, PUT, DELETE를 처리하는 각 메소드의 반환타입이 void로 명시되어 있다는 것인데, response를 직접 반환하는 형태가 아니다.

 

public class ServletResponseWrapper implements ServletResponse{
    private ServletResponse response;
    ...
    public PrintWriter getWriter() throws IOException {
        return this.response.getWriter();
    }
    ...
}
패키지 코드를 좀 더 살펴보면, javax.servlet.ServletResponseWrapper 의 getWriter 메소드를 호출하여 response의 반환값을 설정할 수 있는 것을 확인할 수 있다.

ServletResponse 인터페이스는 HttpServlet의 doGet, doPost 등 메소드의 response parameter type 으로 명시되어 있다.

 

만약, HTML 코드를 반환하는 Servlet을 구현한다면 아래와 같은 코드를 가질 것이다.

public class HelloWorldServlet extends HttpServlet {
    private String message;

    public void init() throws ServletException {
        message = "Hello World";
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) 
	    	throws ServletException, IOException {
      
        // ContentType 명시
        response.setContentType("text/html");

        // HTML 코드 반환 부분
        PrintWriter out = response.getWriter();
        out.println("<h1>" + message + "</h1>");
   }

   public void destroy() {}
}

Java 코드 내에 필요한 HTML 코드를 출력하여 반환하는 형태로 코드가 형성된다. 최종적으로 HelloWorldServlet 과 연결된 URL을 호출하면 <h1>Hello World</h1> 코드가 반환한다.

Servlet 코드를 보면 Spring 의 Controller 와 유사한 느낌을 받을 수 있다.
Model: Java 코드 (실제로직처리)
View: JSP (페이지렌더링)
Control: Servlet (요청-응답 처리)

 

Servlet을 사용하면, 웹을 통해 요청으로 받은 정보로 필요한 로직을 처리하고, 결과값을 반환한다.

하지만, 위 코드를 보면 HTML 을 출력하는 형태이기에 서비스 혹은 페이지가 더 복잡해지면 코드양이 기하급수적으로 늘어날 수 밖에 없다.

 

이를 해결하기 위해, Servlet 코드에서 HTML코드를 생성하는 형식이 아니라 이 관계를 역전시켜, HTML 코드 속에서 Servlet 코드가 작동하도록 하였다. 이게 바로 JSP(Java Server Pages)이다.

 


JSP (Java Server Pages)

HTML코드 속에 로직처리가 필요한 부분에 Java 코드를 삽입하여 레이아웃을 구성하여 훨씬 편하게 처리할 수 있다.

<!--https://www3.ntu.edu.sg/home/ehchua/programming/java/JSPByExample.html-->
<html>
<head><title>First JSP</title></head>
<body>
  <%
    double num = Math.random();
    if (num > 0.95) {
  %>
      <h2>You'll have a luck day!</h2><p>(<%= num %>)</p>
  <%
    } else {
  %>
      <h2>Well, life goes on ... </h2><p>(<%= num %>)</p>
  <%
    }
  %>
  <a href="<%= request.getRequestURI() %>"><h3>Try Again</h3></a>
</body>
</html>

위 HTML 코드는 java.lang.Math 클래스로 무작위 숫자를 생성하여

0.95 보다 크면 You’ll have a luck day!

그 외는 Well, life goes on … 을 출력한다.

 

Servlet 과 차이는, HTML 코드 안에서 필요한 부분만 Java 코드로 로직을 처리하기에 훨씬 동적인 처리가 가능해지며, 서버 로직 코드 속 불필요한 페이지 관련 코드 없이 처리가 가능하다.

 

JSP 파일은 Servlet 파일(Java) 로 변환되기에, Servlet으로 작성하는 것과 동일한 결과를 보여줄 수 있고, 이를 다시 class 파일로 컴파일하여 실행한다. 그리고 이로 요청한 사용자에게 HTML 코드가 최종적으로 전달된다.

http://www.exforsys.com/tutorials/j2ee/jsp-basics.html & https://ko.wikipedia.org/wiki/자바_서블릿

 

Servlet, JSP 구조와 컴파일 과정

Servlet과 비교했을 때, JSP → Servlet 으로 변환하는 과정이 있지만, 컴파일 과정을 거치면 Servlet과 거의 동일하다.

Servlet, JSP 모두 서버 사이드에서 처리되는 코드이다. (이전에는 JSP 코드를 클라이언트 측에서 받아서 처리하는 줄 알았다..)

 

 


Servlet과 JSP 의 차이점에 대해 알아보았다.

 

둘의 가장 큰 차이점은 아무래도 코드의 주체에 따른 역할의 차이다.

Servlet은 Java 코드가 기반이기에 페이지 정보보다 데이터, 로직 처리에 적합하다.

반면, JSP는 HTML 코드 속에서 필요한 데이터를 보다 동적으로 처리해주기 때문에 View 처리에 적합하다.

 

 

최근 개발 트렌드는 Front/Back을 나누어

Front 는 JS 위주의 개발과 Back 은 Java/Python/Go 등 상황에 맞게 언어를 선택하여 개발하기에

JSP 보단 Servlet 으로 도메인/데이터 중심으로 개발을 하는게 여러 방면에서 좋은 선택이라고 생각한다.

(하지만 우리에겐 숨겨진 수많은 레거시가 존재하기에...)

 

 

다음은 Servlet에 대해 조금 더 알아보며, Servlet container 와 ServletContext 간의 관계에 대해 알아보겠다.

'Java > Spring | SpringBoot' 카테고리의 다른 글

[Servlet, JSP and Spring] Servlet & Servlet container  (0) 2022.11.14