티스토리 뷰
서블릿과 톰캣
우선 서블릿을 이해하기 위해 클라이언트가 서버로 HTTP 요청을 보내서 서버가 처리하는 기본적인 프로세스를 상상해보자 (클라이언트에서 Form으로 서버에게 "회원가입" HTTP 요청을 보냈다고 가정한다)
그러면 서버 측에서는 다음과 같은 일련의 과정을 실행한다
0. TCP/IP 대기, 소켓 연결
1. HTTP 요청 메시지 헤더 부분 파싱
2. 어떤 방식인지 파악 (POST, GET 등등)
3. Content-type 파악
4. HTTP 바디 부분 파싱
5. 비즈니스 로직(회원가입) 실행 (이름, 나이를 받아와서 DB에 저장)
6. HTTP 응답 메시지 작성 시작 (라인 생성, 헤더 작성, 바디에 HTML 생성)
7. TCP/IP 응답 전달, 소켓 종료
이렇게 클라이언트의 요청을 수행하고 응답까지 완료했다
선대 자바 개발자들은 5. 비즈니스 로직 수행 부분을 제외한 다른 부분을 굳이 다른 개발자들이
다시 코드를 쳐서 사용해야 할까?라는 의구심을 갖기 시작했다 (당연히 매우 비효율적일 것이다)
그래서 공통된 일련의 과정을 수행해주는 녀석을 개발하는데 걔가 바로 "서블릿"이다
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response){
// empty
}
}
서블릿은 이렇게 생겼다
즉, 서블릿은 클라이언트의 HTTP 요청과 서버의 HTTP 응답을 알아서 파싱 해서 읽고, 만들어주는 역할을 하는 자바 클래스다
이러한 서블릿들은 요청이 올 때마다 새로 생성되면 상당히 자원소모적일 것이다
그리고 동시에 여러 사용자가 동일한 로직을 수행하는 서블릿을 호출하면 어떻게 처리할 것인가?
이런 문제들을 보완하기 위해서 서블릿을 관리하는 주체를 만들었는데,
이를 "서블릿 컨테이너"라고 한다
서블릿 컨테이너는 서블릿의 생성과 호출, 모든 생명 주기를 관리하고 싱글톤으로 유지하며, 다중 사용자의 요청을 처리할 멀티쓰레딩을 환경을 지원한다
서블릿 컨테이너 중 오픈소스이며 가장 사용이 많이 되는 녀석이 바로 "톰캣"이다
JSP(Java Server Pages)
그렇다면, 이제 서블릿을 이용해서 HTTP 요청에 맞춰, 동적으로 HTML을 내려보자
@WebServlet(name = "memberSaveServlet", urlPatterns = "/servlet/members/save")
public class MemberSaveServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
System.out.println("MemberSaveServlet.service");
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
System.out.println("member = " + member);
memberRepository.save(member);
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
PrintWriter w = response.getWriter();
w.write("<html>\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
"</head>\n" +
"<body>\n" +
"성공\n" +
"<ul>\n" +
" <li>id="+member.getId()+"</li>\n" +
" <li>username="+member.getUsername()+"</li>\n" +
" <li>age="+member.getAge()+"</li>\n" +
"</ul>\n" +
"<a href=\"/index.html\">메인</a>\n" +
"</body>\n" +
"</html>");
}
}
(회원 저장을 서블릿으로)
완성하고 보니 유지보수성이 거의 제로에 가까운 코드가 되었다
이대로 개발하면 문자열 혐오증이 생길 수도 있기에, 선대 개발자들은 다른 방법을 모색한다
위 코드의 문제점은 HTML을 자바에서 사용하려고 해서 발생한 문제점이다
그래서 방식을 바꾸어서 HTML에서 자바 코드를 사용해보는 시도를 하게 되는데, 그게 바로 JSP다
JSP를 이용해서 회원저장 기능을 구현해보자
<%@ page import="hello.servlet.domain.member.MemberRepository" %>
<%@ page import="hello.servlet.domain.member.Member" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
MemberRepository memberRepository = MemberRepository.getInstance();
System.out.println("save.jsp");
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
System.out.println("member = " + member);
memberRepository.save(member);
%>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
성공
<ul>
<li>id=<%=member.getId()%></li>
<li>username=<%=member.getUsername()%></li>
<li>age=<%=member.getAge()%></li>
</ul>
<a href="/index.html">메인</a>
</body>
</html>
확실히 자바에서 HTML을 문자열로 쓰는 것보다 훨씬 나아진 것 같다
(참고로 JSP는 나중에 서블릿으로 변환되어 동작하게 된다)
MVC 패턴의 등장
JSP로 편하게 개발을 하던 선대 개발자들은 이제 다른 문제에 직면하게 된다
그것은 바로 JSP가 "너무 많은 일을 수행하고 있다"는 점이다
이게 무슨 뜻이냐면, 현재 JSP는 회원을 저장하는 비즈니스 로직도 수행하고, 화면을 그리는 일도 수행한다
이게 웹 서비스가 작으면 상관없는데, 커질수록 분명 유지 보수하기 힘들 것이다
그래서 선대 개발자들은 관심사를 나눠서 각자 맡은 일만 잘할 수 있도록 분리하는 작업을 진행하게 된다
핵심 비즈니스 로직(회원 저장)을 수행하는 부분과 화면을 그리는 부분 두 가지로 나눠서 각각 Controller, View라는 이름을 지어 분리했다
가만 생각해보니, 화면을 그릴 때 데이터가 필요할 경우도 있으므로 Controller와 View에서 데이터를 주고받을 수 있도록 데이터를 전달해주는 Model이라는 부분 또한 만들게 된다
그리하여 웹 서비스에서 서로 맡은 역할을 나눈 구조인 Model, View, Controller 패턴이 등장하게 되었다
결과적으로, 모든 웹 개발자들이 생으로 완전 밑바닥부터 하나하나 개발해 오면서 불편함을 하나, 둘 개선하다 보면 결국 MVC 패턴의 스프링 프레임워크 비슷한 게 만들어져 있을 것이다
하지만, 우리가 회사에 갈 때 대중 교통을 이용하지 걸어가지 않는 것처럼 굳이 모든 개발자가 처음부터 하나하나 불편함을 겪으면서 이 MVC 패턴을 만들 필요는 없다
따라서 선대 개발자들이 갈고닦아 만든 스프링 MVC를 잘 사용하자
<정리>
서블릿 : HTTP 요청, 응답 스펙을 대신 파싱 해서 만들어주는 녀석
서블릿 컨테이너 : 서블릿들을 관리하는 주체 (+부가기능 제공)
톰캣 : 서블릿 컨테이너 중 하나
JSP : HTML에 자바 코드를 삽입하는 방법으로 서블릿을 좀 더 쉽게 사용하는 기술
MVC : JSP는 너무 많은 역할을 위임 중이라 관심사에 따라서 역할을 분리한 아키텍처