서블릿, 웹 애플리케이션

corncheese·2023년 7월 2일
0

웹서버에 서블릿이 어떤 구조로 있어야 하는지, 클라이언트가 서블릿에 접근하는 방법에 대해 알아볼 차례.

웹 애플리케이션 위치

서비스는 서버에서 애플리케이션 단위로 이루어 진다. 웹서버가 시작될 때 자동으로 애플리케이션으로 인식하여 서비스를 올려주는 디렉터리가 있다.
WAS 종류에 따라 애플리케이션이 위치하는 이름이 다르며
톰캣을 예를 들면, 톰캣은 톰캣을 설치한 디렉토리 하위의 webapps 디렉토리에 애플리케이션들이 있다.
webapps 디렉토리에 있는 하위 디렉토리 또는 디렉토리가 압축된 war파일은 하나의 애플리케이션으로 인식한다.

웹 애플리케이션 구조

웹 애플리케이션은 디렉터리나 디렉터리가 압축된 형태로 웹서버에 올려서 웹서비스를 한다.
모든 웹 애플리케이션이 공통으로 가져야 하는 디렉토리와 파일이 있다.

  • 루트 디렉토리하위의 WEB-INF 디렉토리

  • WEB-INF 디렉토리에는 web.xml 파일이 있어야 한다.

  • 현재 웹 애플리케이션에서 서비스하려는 클래스 파일이 있디면 WEB-INF/classes 디렉토리의 하위에 있어야 한다.

  • 클래스 파일들이 jar로 압축뒤어 있다면 WEB-INF/libs 디렉토리에 있어야 한다.

web.xml

웹서버가 서비스를 시작할 때에, 웹서버는 각 애플리케이션의 web.xml 파일을 읽어 서비스를 처리한다.

서블릿 디렉터리

서블릿 디렉터리란, 서블릿이 공식적으로 존재하는 디렉터리로서 모든 WAS의 구조가 같다.

서블릿 구현

서블릿을 구현할때 반드시 상속받아야 하는 클래스가 있는데, javax.servlet.http 패키지에 있는 HttpServlet 클래스이다.
HttpServlet은 GenericServlet 클래스를 상속받고, Serializable, Servlet, ServletConfig 인터페이스를 상속받고 있다.

  • Servlet 인터페이스
    init(), service(), destroy(), getServletConfig(), getServletInfo() 등 5개 메소드를 선언하고 있으며, 이는 서블릿 프로그램 실행의 생명주기와 연관된 메소드들이다.

  • GenericServlet 클래스

GenericServlet클래스는 Servlet인터페이스를 상속하여 클라이언트-서버 환경에서 서버단의 애플리케이션으로서 필요한 기능을 구현한 추상 클래스이다.
service()메소드를 제외한 모든 메소드를 재정의하여 적절한 기능을 구현하였다.

  • HttpServlet 클래스
    HttpServlet 클래스는 GenericServlet 클래스를 상속하여 service() 메소드를 재정의함으로써 HTTP 프로토콜에 알맞은 동작을 수행하도록 구현한 클래스이다. 즉, HTTP 프로토콜 기반으로 브러우저로부터 요청을 전달받아서 처리하도록 하는 클래스이다.
    service() 메소드에는 요청방식에 따라 doGet(), doPost() 등 정해진 사양의 메소드가 호출되도록 구현되어 있다.
    HttpServlet 클래스를 상속하여 웹서버 기반의 서블릿 프로그램을 구현할 때 반드시 재정의해야 하는 메소드는 없으며, 어떠한 요청방식을 지원하는 서블릿인지에 따라서 필요한 메소드를 재정의하여 구현한다.

서블릿 실행 순서

서블릿의 실행 순서를 이해하려면 IoC를 이해해야 한다.
Java EE 기반 프로그램은 실행의 흐름을 개발자가 제어하는 것이 아니라 컨테이너가 제어한다. 이처럼 개발자가 아닌 제 3자가 프로그램의 실행 흐름을 제어하는 것을 IoC(Inversion of Control) / 제어의 역전 이라고 한다.

실행순서 및 설명

  1. 클라이언트로부터 처리 요청을 받음
    웹서버는 요청정보의 헤더 안에 있는 URI를 분석하고, 요청받는 페이지가 서블릿이면 서블릿컨테이너로 처리를 전달한다.
    서블릿 컨테이너는 요청받는 서블릿을 WEB-INF/classes나 WEB-INF/lib에서 찾아서 실행 준비를 한다.

  2. 최초 요청 여부 판단 ( 최초요청일 경우 객체셍성 / init() 메소드 실행 )
    서블릿 컨테이너는 현재 실행할 서블릿이 최초의 요청인지 판단한다. 실행할 서블릿 객체가 메모리에 없으면 최초의 요청이고, 이미 있으면 최초의 요청이 아닌 것으로 판단한다.

  3. 서블릿 객체 생성
    서블릿 컨테이너는 요청받는 서블릿이 최초의 요청이라면 해당 서블릿을 메모리에 로딩하고 객체를 생성한다. 일반 자바 객체는 new 명령문으로 여러 개의 객체를 생성할 수 있지만, 서블릿은 최초 요청이 들어왔을때 한 번만 객체를 생성하고 이때 생성된 객체를 계속 사용한다.

  4. init() 메소드 실행
    init()는 서블릿 객체가 실행된 다음에 호출되는 메소드로서, Servlet 인터페이스에 선언이 되어 있고, 기능은 GenericServlet 클래스에 구현되어 있다.
    init() 메서드는 처음 요청시 서블릿 객체가 생성된 다음 호출되므로 주로 서블릿 객체의 초기화 작업이 구현되어 있다. 재정의하여 사용 가능하다.

  5. service() 메소드 실행
    service() 메소드는 실행하는 서블릿의 요청 순서에 상관없이 클라이언트의 요청이 있을 때마다 실행된다. 따라서 service() 메소드는 실제 서블릿에서 처리해야 하는 내용이 구현되어 있다. service() 메소드는 Servlet 인터페이스에 선언되어 있고, GenericServlet 클래스에 abstract 메소드로 선언되어 있으므로, HttpServlet 클래스에 메소드 몸체가 구현되어 있다. 재정의하여 사용 가능 하다.

  6. service() 메소드가 끝나면 서버에서의 실행은 끝이 난다. 서버 프로그램 실행이 완료된 후에는 서블릿 컨테이너가 실행결과를 웹서버에 전달하고, 웹서버는 서비스를 요청한 클라이언트에 응답한다.

콜백 메소드와 서블릿 객체의 생명주기

callback method란, 어떤 객체에서 상황이 발생하면 컨테이너가 자동으로 호출하여 실행되는 메소드를 의미한다. 이러한 콜백 메소드들이 서블릿을 실행한다.

서블릿의 콜백 메소드

init() | 클라이언트로부터 최초로 서블릿 요청이 있을때 실행되며 초가화 작업을 한다.
service() | 클라이언트로부터 요청이 있을때마다 실행되며, 실제 서블릿이 처리해야 하는 작업을 한다.
destroy() | 서블릿 객체가 메모리에서 삭제될 때 실행(서비스나 서버 중지)되며, 자원 해제 작업을 한다.

서블릿 객체의 생성

서블릿 객체의 삭제

최초 요청 시 생성된 서블릿 객체가 삭제되는 시점은 서버를 중지시켜 웹 애플리케이션 서비스를 중지할 때이다. 웹서버에서는 전체 서비스를 중지할 수도 있고, 일부 서비스만 중지할 수도 있다.
서블릿 객체가 삭제되는 시점은 웹서버에서 웹 애플리케이션 서비스가 중지되는 시점이다. destory() 메소드를 호출하여 삭제한다.

서블릿 실행

서블릿 파일은 /WEB-INF/classes에 있어야 하지만, /WEB-INf 디렉토리는 클라이언트가 접근할 수 없기 때문 -> web.xml 또는 어노테이션을 통해 클라이언트가 서블릿에 접근 할 수 있도록 설정한다.

  • web.xml 설정으로 접근
web.xml

// 실행할 서블릿을 웹서버에 등록
<servlet> // servlet tag는 HttpServlet을 상속받고 있는 web.xml에 등록할 때 사용한다.
	<servlet-name></servlet-name> // 등록하는 서블릿의 이름을 부여
    <servlet-class></servlet-class> // 실제 동작하는 서블릿의 클래스 이름을 지정한다.
<servlet>

// <servlet>으로 등록한 서블릿을 실행할 URI 지정
<servlet-mapping>
	<servlet-name></servlet-name> // 실행할 서블릿 이름을 지정한다. 지정하는 이름은 반드시 servlet tag에서 지정한 이름으로 지정해야 한다.
    <url-pattern></url-pattern> // 서블릿을 실행할 때 사용할 URL을 지정한다.
</servlet-mapping>
  • @WebServlet을 통해 접근

    import.javax.servlet.annotation.WebServlet;

    @WebServlet("/test");

web.xml 파일로 설정하는 방식은 여러 개의 서블릿을 태그로 등록하기 때문에 전체적인 관리가 쉽다. 또한 URL 값이 변경되어야 할 때는 소스를 수정하지 않고서도 web.xml에서 쉽게 변경할 수 있다. 그리고 @WebServlet 설정 방식은 설정파일 없이 자바 소스에서 @WebServlet 으로 쉽게 URL 패턴을 지정할 수 있다. 그러나 하나의 자바 소스에 하나의 서블릿 매핑만 가능하므로 여러개의 서블릿에 대한 정보를 볼 수 없기 때문에 유지보수성이 떨어진다.

요청방식에 따른 서블릿 실행

서블릿이 실행될 때 service() 메소드가 자동으로 실행되기 때문, HttpServlet 클래스에 구현된 service() 메소드를 재정의하여 구현해야 한다.(서블릿 요청이 있을 때마다 호출되는 메서드 이므로 반드시 재정의해야 한다.)

그런데 service() 메서드를 재정의하지 않을 때가 있다. 이는 HttpServlet에서 구현된 service() 메서드를 그대로 사용할 때이다.

  1. protected void service(HttpServletRequest req, HttpServletResponse resp)
  2. public void service(ServletRequset req, ServletResponse resp)

두가지 형태의 메소드 중 서블릿 요청이 있을 때마다 실행되는 메소드는 2번 메소드로 2번 형태의 service()는 단순히 같은 객체에 있는 1번 형태의 service()만 호출한다.
1번 형태의 service() 메소드는 클라이언트의 실행요청에 따라 서로 다른 메서드를 호출하도록 구현되어 있다.
** 클라이언트의 실행요청 : GET, POST, PUT, DELETE

0개의 댓글