1. 톰캣과 web.xml

톰캣은 Servlet Container, Servlet Engine으로써 Servlet을 실행하여 동작합니다.


웹 프로젝트 폴더를 생성할 때 같이 생성한 web.xml 파일에는 클라이언트가 어떤 URL을 요청했을 때 어떤 Servlet 파일을 실행시킬 것인지를 매핑해놓은 파일입니다.

톰캣은 web.xml에 매핑되어진 자바 파일을 Servlet으로 변환시키고, 그 Servlet을 실행하여 요청에 응답하게 됩니다.

이 때 Servlet으로 변환되기 위해서는 개발자가 Servlet이라는 것을 명시해줘야 하는데, 그 방법은 Servlet 구조를 통해 알아보겠습니다.





2. Servlet 기본 구조

Servlet으로 변환되기 위해서는 기본적으로 다음의 구조를 만족해야 합니다.

  • 톰캣에서 만들어 놓은 HttpServlet 클래스를 상속
  • HTTP 요청 메서드인 Get방식과 Post 방식을 처리하기 위해 doGet()과 doPost()를 오버라이딩
    • 매개변수로는 HttpServletReqeustHttpServletResponse 클래스를 정의합니다.


직접 Servlet을 만들어 보도록하겠습니다.

  1. 프로젝트 폴더 ( Dynamic Web Project )를 생성
  2. Java Resources 폴더 우클릭 
  3. new -> Servlet
  4. 클래스 이름 작성


Servlet 파일을 생성하면 위의 사진처럼 기본적인 구조가 잡혀있을 것입니다.





3. URL과 Serlvet 매핑 - web.xml

톰캣은 web.xml 파일을 확인하여 Servlet 클래스를 매핑한 후, 이를 실행한다고 초반에 언급했었습니다.


그런데 어노테이션을 활용하면 web.xml에 직접 작성하여 매핑을 할 필요가 없습니다.

위에서 생성한 클래스를 보면 @WebServlet("/hello") 어노테이션을 확인할 수 있습니다.

톰캣은 어노테이션을 확인하여 "해당 Servlet으로 접근하기 위해서는 URL에 /hello로 접근하면 된다"는 매핑을 합니다.

Servlet 클래스를 만들면 자동으로 어노테이션이 생성되고, 이를 수정하여 URL을 바꿀 수도 있습니다.


직접 web.xml에 작성하는 방법은 아래와 같습니다.

프로젝트 폴더/WebContent/WEB-INF/web.xml 파일을 클릭하여 하단에 보이는 Source 탭을 클릭해주세요.




아래와 같이 xml을 작성하면, Servlet과 URL이 매핑됩니다.

( 이미 선언된 어노테이션과 중복되면 톰캣 실행이 안됩니다. )

  <servlet>
  	<servlet-name>MappingTest</servlet-name>
  	<servlet-class>hello</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>MappingTest</servlet-name>
  	<url-pattern>/hello</url-pattern>
  </servlet-mapping>
  • servlet-name
    • web.xml에서 매핑을 구분하기 위한 이름
    • <servlet>과 <servlet-mapping>의 <servlet-name>이 같은 것을 확인할 수 있습니다.
  • servlet-class
    • Servlet 클래스 이름
  • url-pattern
    • Serlvet에 대응하는 URL
    • 루트 경로는 생략합니다.

어노테이션으로 매핑하는 것이 훨씬 간단하므로, "web.xml 파일로 직접 Servlet과 URL을 매핑 시킬 수 있다" 정도만 알아두시면 좋을 것 같습니다.



참고로 기존에 작성된 <welcome-file> 태그는 URL에 특정 파일경로가 아닌 도메인만 입력했을 때 보여 줄 페이지를 나열한 것입니다.

즉, 대표 페이지 목록을 나열한 것이라고 생각하면 됩니다.

예를 들어, 클라이언트가 localhost:8080/testing 으로 요청했을 했을 경우, ( 저의 Root 경로가 testing임을 참고해주세요. )

  1. index.html
  2. index.htm
  3. index.jsp
  4. ...

순서로 소개 페이지를 찾게 됩니다.

이 부분은 Servlet 매핑과 관련이 없지만 참고로 말씀드렸습니다.





4. Request / Response

doGet(), doPost() 메서드는 HTTP 요청을 처리하는 메서드라고 언급했었습니다.

그리고 각 메서드는 HttpServletRequest , HttpServletResponse 두 객체를 파라미터로 명시하는데,

이 두 객체는 톰캣에서 미리 작성해둔 클래스이며, HTTP 요청과 응답에 대한 정보들을 모두 갖고 있습니다.

앞으로는 이들을 간단하게 request , response 객체라고 말하도록 하겠습니다.


  • request 객체
    • 클라이언트가 요청할 때 함께 전송한 데이터들이 있습니다.
    • 예를 들어, URL 파라미터, form에서 전송한 데이터들이 있습니다.
  • response 객체
    • 서버에서 클라이언트로 응답 할 때 필요한 데이터들이 있습니다.
    • 예를 들어, 응답 결과 상태 코드, 클라이언트가 요청한 HTML 문서 같은 것들이 있습니다.

이 두 객체가 하는 일은 앞으로도 계속 나오게 되므로 API는 그 때 그 때 확인하도록 하겠습니다.

지금은  request , response 객체가 HTTP 요청과 응답을 처리하는 객체라는 것만 알면 될 것 같습니다.





5. Servlet 객체로 응답하기 - JSP가 필요한 이유

Servlet은 클라이언트의 요청을 받아서 비즈니스 로직 처리, DB에 접근 등의 요청을 처리한 후, 다시 사용자에게 응답하는 것이 주 역할입니다.

즉, 요청을 관리한다는 점에서 MVC 패턴의 컨트롤러 역할을 합니다.

( MVC에 대해서는 여기를 참고해주세요. )


사용자에게 응답하는 문서는 JSP 파일을 사용하는데, 왜 Servlet을 사용하지 않고 JSP를 사용할까요?

그 이유를 알기 위해서 Servlet을 사용할 때 얼마나 불편한지 확인해보겠습니다.


위에서 생성한 Servlet 클래스에서 클라이언트에게 응답을 하기 위해 doGet() 메서드를 간단하게 수정합니다.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 헤더는 PrintWriter 위에 작성해야 한다.
response.setContentType("text/html; charset=UTF-8");

PrintWriter out = response.getWriter();
out.println("<h1>하이</h1>");
}
  • response.setContentType()
    • HTTP 응답 헤더를 작성하는 코드입니다.
    • 헤더이므로 HTTP body보다 위에 작성합니다.
  • response.getWriter()
    • 브라우저에 출력할 메시지를 작성합니다.


이제 서버를 실행 시킨 후, 브라우저에서 URL로 요청을 해보겠습니다.

( 실행이 된 상태라면 재실행을 해주셔야 컴파일이 됩니다. )

저는 프로젝트 Root가 testing이고, Servlet 클래스 이름이 hello이므로, localhost:8080/testing/hello 경로로 요청을 보냈습니다.



Servlet으로 응답해도 페이지가 잘 응답되는 것을 확인할 수 있는데요.

그런데 out.println() 메서드로 HTML 태그를 자동완성 없이 일일이 쓰는 것은 너무 고통스럽습니다.

게다가 들여쓰기가 없으므로 가독성도 좋지 않고, 실수할 우려도 있죠.

이런식으로 html을 작성하는 것은 바람직하지 않은 것 같습니다.


다음의 사진은 어떤 JSP 파일을 Servlet으로 작성한 파일의 일부입니다.



JSP 파일에서 60줄이었는데, Servlet으로 변환되니 200줄이 되었습니다.



즉, Servlet으로 응답 페이지를 보여주는 것은 비효율적입니다.

그래서 HTML 문서에 Java 코드를 넣을 수 있는 JSP가 필요한 것입니다.


JSP는 MVC 패턴에서 View에 해당합니다.

정리하면 JSP/Servlet을 사용한다는 것은 "모든 요청은 Servlet으로 받고 클라이언트에게 보여 줄 페이지는 JSP로 작성한다"고 할 수 있습니다.




이상으로 Servlet에 대한 개념에 대해 알아보았습니다.


Servlet이 아닌 JSP에서 직접 요청을 받아서 JSP로 응답하는 방법도 있는데 이를 모델1이라고 합니다.

즉, Controller와 View를 모두 JSP가 담당하고 있는 것이죠.

그리고 이 글에서 다뤘던 방식인 Servlet으로 요청을 받고 JSP로 응답하는 방법을 모델2라고 합니다.


이후의 글에서는 JSP에 대해 알아본 후, 모델1으로 간단한 애플리케이션을 만들어보고, 이를 모델2로 바꿔보는 작업을 하려고 합니다.