서블릿과 톰캣의 관계
서블릿이란
- HTTP 요청으로부터 웹 페이지를 동적으로 생성하는 서버 프로그램이다.(자바 클래스)
- 개발할 때 마다 이런 기능을 구현할 수 있겠지만 불편하기 때문에 서블릿이라는 것이 생겨났고,
성능 향상이 되었다. - 서블릿은 JPA와 같이 인터페이스가 되며, 이를 지원하는 것이 아파치 톰캣(WAS)이다.
- JSP와 비슷하지만 서블릿은 자바 코드에서 HTML을 포함하고,
JSP는 HTML에 자바 코드를 포함한다. 서블릿에서 동적으로 HTM 만들기 어려워서 JSP가 등장한 것이다.
JSP는 결국 내부적으로 서블릿을 호출하게 된다. 이 JSP와 서블릿을 실행할 수 있는 것이 아파치 톰캣이다.
- 만약 서버를 바꾸고 싶다면 초록색 박스인 톰캣만 서블릿과 JSP(JSP를 사용한다면)를 지원하는 서버로 갈아 껴주면 된다.
아파치 웹 서버
- NGINX와 같은 HTTP 웹 서버이다.
- 톰캣과 연동하여 사용할 수 있다.
웹 서버
란 웹 브라우저와 같이 클라이언트로부터 HTTP 요청을 받고, HTML 문서와 같은 웹 페이지를
반환하는 컴퓨터 프로그램이다.
아파치 톰캣
- 아파치에서 만든
서블릿 컨테이너
만 있는 WAS이다. - 웹 서버와 연동하여 실행할 수 있는 자바 환경을 제공하여
JSP와 자바 서블릿을 실행할 수 있는 환경을 제공한다.
톰캣은 웹 서버 자체를 내장한다.
- 서블릿 컨테이너란 서블릿들을 관리하는 컨테이너이다.
MVC 패턴으로 예를 들면,컨트롤러에 /members, /members/save
와 같은 것을 서블릿으로 생성하여
이 2개를 서블릿 컨테이너에 생성하는 것이다.
톰캣이 서블릿을 지원하는 과정
맨 위 서블릿 설명 글의 그림이 있지만 JSP를 제외하고 서블릿과 톰캣과의 관계만 살펴 보자.
스프링 부트와 함께 생각 해보자. 스프링 부트는 톰캣을 내장하고 있다.
서버 생성 과정
- 스프링 부트를 실행한다.
- 스프링 부트는 톰캣을 실행하여 서버를 띄운다.
- 톰캣은 컨트롤러에 있는 url기반으로 서블릿을 생성하고 서블릿 컨테이너에 관리한다.
톰캣이 서블릿 컨테이너이기 때문에 결국 서블릿 컨테이너가 서블릿을 생성하는 것이다.
마치 스프링이 스프링 빈을 스프링 컨테이너에 관리하는 것과 같다.
톰캣은 HTML 동적 생성을 자바에서 하기 위해 존재하고, 톰캣은 아파치 웹 서버를 포함하는 형태로
톰캣 서버는 그림과 같이 요청 받을 준비가 완료 되었다.
하지만 반드시 서버가 뜨면서 서블릿이 생성되는 것은 아니고 설정이 가능하다.
요청이 왔을 때 생성을 할 수도 있다고 한다.
코드로도 살펴 보자.
컨트롤러 코드이고, JSP와 함께 사용하는 서블릿 컨트롤러이다.
아래 두 서블릿이 코드상으로 그림에 있는 서블릿이 된다.
**memberSaveServlet 서블릿**
/members/save
라는 url 요청을 담당하는서블릿
이 된다.
@WebServlet(name = "memberSaveServlet", urlPatterns = "/members/save")
public class MemberSaveServlet extends HttpServlet {
MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
Member member = new Member(username, age);
memberRepository.save(member);
// Model에 데이터를 보관한다.
request.setAttribute("member", member);
String viewPath = "/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
}
}
**memberListServlet 서블릿**
/members
라는 url 요청을 담당하는서블릿
이 된다.
@WebServlet(name = "memberListServlet", urlPatterns = "/members")
public class MemberListServlet extends HttpServlet {
private MemberRepository memberRepository = MemberRepository.getInstance();
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Member> members = memberRepository.findAll();
request.setAttribute("members", members);
String viewPaht = "/WEB-INF/views/members.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPaht);
dispatcher.forward(request, response);
}
}
요청 응답 과정
위에서 서버가 생성되는 과정을 알아 보았고, 이번에는 서버와 클라이언트가 통신하는 과정을 알아 보자.
그림에서 1번 ~ 2번은 서버가 생성되는 과정이다. 설명은 생략한다.
- 클라이언트(웹 브라우저)는 서버에게 [
localhost:8080/members로](http://localhost:8080/members로) 요청
을 보낸다. - 톰캣에 내장되어 있는 아파치 웹 서버는 요청을 받는다.
- 톰캣은 요청온 HTTP 정보를 읽어 서블릿 컨테이너에서 알맞는 서블릿 객체를 찾는다.
- 찾은 서블릿을 개발자가 사용할 수 있도록 셋팅을 해준다.
- 개발자는 서블릿을 이용해 개발을 한다.
- 서블릿 컨테이너는 사용이 완료된 서블릿 객체 정보로 HTTP 응답 정보를 생성하여 웹 서버에 전달한다.
- 웹 서버는 이를 클라이언트에 응답한다.
- 웹 브라우저는 HTTP 응답 정보로 렌더링을 한다.
웹 서버와 WAS를 분리해서 쓰지 않나?
요즘은 WAS와 웹 서버 구분이 모호하다고 한다. 서로간에 역할을 각자가 모두 할 수 있기 때문이라고 한다.
톰캣 역시 웹 서버를 내장하고 있다. 그렇다면 웹 프론트 서버와 백엔드 서버를 분리해서 사용하는 경우가 많은데 이건 뭘까?
우리가 그림에서 본 톰캣 서버를 백엔드 서버라고 하고, 프론트 서버를 담당하는 웹 서버를 따로 분리하면 아래와 같이 될 것 같다.
이런 식으로 분리를 하면 프론트 웹 서버에 먼저 요청을 하고 프론트 웹 서버는 백엔드 서버에 요청을 하게 된다.
분리를 하면 장점이 2가지로 추릴 수 있다.
- 만약 요청 했을 시 서버가 다운 됐어도 프론트
웹 서버는 독립적
이기 때문에서버가 다운 됐어요. 죄송합니다
라는 응답을 해줄 수 있다. - 백엔드 서버나 웹 서버 중 트래픽티 많은 곳만 따로 증설하거나 필요 없다면 제거할 수 있다.