본문 바로가기

코딩/JAVA 공부

[Spring] 웹애플리케이션 이해 - Servlet

HTTP 메시지로 모든 것을 전송할 수 있다.

ex) HTML, Text, Image, 음성, 영향, 파일, JSON, XML (API)

 

웹 시스템 구성 : WEB, WAS, DB

WEB: 정적 리소스 처리

WAS: 애플리케이션 로직 같은 동적인 처리

 

 

서버에서는 클라이언트의 요청을 수행하기 위해 서블릿이라는 기술을 사용한다.

서블릿은 자바를 사용해 웹 서버를 만들 때 필요한 기술로, 클라이언트의 요청을 분석해 결과를 만들어 다시 전송하는 역할을 한다.

사용자의 입력을 받아 동적인 웹페이지를 만드는 것을 CGI 라 하는데, 서블릿은 JAVA 언어로 구현된 CGI다.

 

클라이언트에서 요청이 왔을 때 서버에선 아래와 같은 작업이 필요하다

 - 서버 TCP/IP 연결 대기, 소켓 연결  -(1)
 - HTTP 요청 메시지 파싱해서 읽기  -(2)
 - HTTP 메서드 인지, URL 인지       -(2)
 - Content-Type 확인                     -(2)
 - HTTP 메시지 바디 내용 파싱         -(2)
 - 비즈니스 로직 실행                        -(3)
 - HTTP 응답 메시지 생성                 -(2)
- TCP/IP에 응답 전달, 소켓 종료        -(1)

 

서버를 구현할 때 위에 모든 작업을 구현한다면 어마어마한 작업량이 필요할 것이다.

그래서 우리는 WAS와 Servelet의 도움을 받아 웹서비스에서 가장 중요한 비즈니스 로직 구현에 집중할 필요가 있다.

먼저 TCP/IP 및 소켓 연결은 WAS에서 진행해 준다. Spring은 Tomcat 이라는 WAS 가 내장되어 있고 이를 대신 진행해준다. (1)

또 클라이언트에서 요청한 내용을 분석하고 개발자가 사용하기 쉽도록 HTTPRequest 객체 생성은 Servlet Container에서 진행해 준다. (2)

이를 통해 개발자는 비즈니스로직 (3)만 개발하면 되는 것이다!

추가로 Servelet Container는 WAS에 포함되어 있다. 즉 Tomcat에서 (2) 도 진행해 준다.

이를 진행하는 방법은, Severlet  Container에서 HTTP 메시지를 통해 HTTPRequest, HTTPResponse 객체를 생성해, URL에 따라 필요한 Servlet으로 전달해 준다.

이때 Servlet은 싱글톤이며, 동시 요청을 처리하기 위해 쓰레드 풀에 있는 쓰레드를 통해 Servlet을 실행한다.

(여기서 실행한다는 의미는 Servlet 객체의 service() 함수를 호출한다는 의미)

이후 비즈니스로직을 통해 HTTPRequest에 필요한 정보를 담아 Servlet Container에 넘기면 이를 HTTP message로 변환해 클라이언트로 보내게 된다.

이를 요약해 보면 아래 그림과 같다

 

개발자는 각 URL에 따른 필요한 비즈니스 로직을 HttpServlet을 상속받은 객체로 구현해야 한다.

HttpServlet은 GenericServlet을 상속받고, GenericServlet은 Servlet Interface를 구현한 구현체이다.

여기서 Servlet을 살펴보면 의외로 매우 간단한 인터페이스라는 걸 알 수 있는데,

public interface Servlet {

    void init(ServletConfig config) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

이처럼 5개의 메서드만 있고, 이 중 init(), service(), destory() 메서드를 라이프 사이클 메서드 라고 한다.

Servlet Container는 라이프 사이클 메서드를 호출해 서블릿의 생애 주기를 관리한다.

init() 메서드는 서블릿 생애 주기 중 단 한 번만 실행되며, service()를 실행하기 전에 무조건 작업이 완료되어야 한다.

service() 은 개발자가 작성해야 하는 비즈니스 로직이 작성될 메서드이다.

destory()를 통해 서블릿을 제거한다.

 

Servlet을 구현하면 아래와 같다.

@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponseresponse) throws ServletException, IOException {
      
    String username = request.getParameter("username");
    
    response.setContentType("text/plain");
    response.setCharacterEncoding("utf-8");
    response.getWriter().write("hello " + username);
    }
}

위 Servlet은 쿼리 파라미터를 읽어와 화면에 표현해 주는 Servlet이다.

만약 Servlet을 통해 HTML 형식으로 응답하고 싶다면 아래 코드를 추가해야 한다.

    response.setContentType("text/html");
    response.setCharacterEncoding("utf-8");
	
    PrintWriter writer = response.getWriter(); 
    writer.println("<html>"); 
    writer.println("<body>");
    writer.println(" <div>안녕?</div>"); 
    writer.println("</body>"); 
    writer.println("</html>");

이 처럼 HTML을 자바로 작성하기는 매우 어렵다.

이를 해결하기 위해 템플릿 엔진이 만들어졌다!

HTML 문서에 동적으로 변경해야 하는 부분만 자바코드를 넣을 수 있도록 만들어진 것이 템플릿 엔진이다.

JSP, Thymeleaf, Freemarker, Velocity 등이 있으며 Spring과 가장 잘 통합되는 건 Thymeleaf 이다.

다음 게시글에서 JSP가 어떻게 작동하는지 간단히 작성해보겠다.