Java/Java 이론

서블릿이란?

뉴욕피자 2020. 9. 15. 17:49

1. 서론

안녕하세요.

 

오늘은 서블릿에 대해서 작성해보려고 합니다.

 

처음 JSP, 서블릿으로 간단한 웹 구성을 공부할 때는 서블릿에 대해서 깊게 공부하지 않았습니다. 하지만 이 서블릿이라는 것은 스프링 프레임워크를 사용해서 MVC 모델을 구성할 때도 나오게 되면서, 계속 괴롭히는데요. 즉 웹 백엔드 개발자로서 반드시 알아야 하는 것이라고 생각합니다. 

 

그래서 오늘은 서블릿에 대해서 작성하려고 합니다. 하지만 이 글은 웹 서버가 어떻게 동작하는지, 서블릿 컨테이너가 무엇인지 설명하는 글은 아닙니다. 서블릿이라는 기술 자체에 대해서 집중해보려고 합니다.

 

웹 서버의 동작, 서블릿 컨테이너에 대해서 궁금하신 분은 아래의 글을 참고해주세요.

 

[Java/Java 이론] - 웹 서버란?

 

2. Servlet?

일단 먼저 구분을 해야 할 것이 있습니다. 서블릿은 단순 인터페이스나 클래스 같은 것이 아닙니다. 사실 이 말은 조금은 거짓말(?)이 섞여있는데요. 뒤에서 더 나오니, 조금만 기다려주세요. 지금은 그저 동적 콘텐츠를 생성하기 위한 하나의 기술이라고 생각해주세요.

 

사실 서블릿 이전에 동적 콘텐츠 생성을 위한 기술이 있었습니다. 초창기 Applets이라는 기술이었는데요. 그 뒤에 CGI라는 기술도 있었습니다. 하지만 CGI는 기본적으로 Java 프로세스 단위로 동작을 했었습니다. 즉 요청이 있을 때마다 프로세스를 하나씩 생성을 했어야 합니다. 요즘같이 멀티스레딩 개발 환경이 당연시 되는 시점에서, 거대한 프로그램이 프로세스 단위로 동작을 하게 되면 비효율적일 것 입니다. 즉 서버의 자원을 많이 사용할 수밖에 없었습니다.

 

하지만 Servlet은 Thread 단위로 동작을 하며, 한번 초기화되어서 메모리에 올라간 서블릿은 다시 부르지 않아도 됩니다. 여기서 다시 부르지 않아도 된다는 말은, 초기화를 통해서 메모리에 다시 올리는 과정이 없어졌다는 의미입니다. 또한 사용하지 않을 때는 destroy를 하기도 합니다. 즉 메모리와 같은 자원을 효율적으로 사용할 수 있게 되었습니다. 

 

앞에서 설명 했듯이 Servlet은 동적 콘텐츠를 생성하기 위한 기술입니다. 그런데 이러한 동적 콘텐츠를 어떻게 생성하는 것일까요? 그냥 아무것도 없는 HTML 페이지가 갑자기 동적으로 움직이지는 않을 것입니다. 기본적으로 HTML은 정적 페이지 입니다. 즉 이미 만들어지고, 정해진 콘텐츠만 보여줍니다. 사용자에 맞게 페이지 안에서 다른 정보를 전해줄 수 없습니다. 하지만 서블릿이 서블릿 컨테이너라는 것을 통해서 서버와 통신을 하며, View 페이지에 알맞은 콘텐츠를 보내줍니다.

 

서블릿 컨테이너가 무엇인지는 아래의 글을 참고해주세요

[Java/Java 이론] - 웹 서버란?

 

3. Servlet Package

서버와 통신을 하는 서블릿은 당연히 HTTP 프로토콜을 이용합니다. javax.servlet / javax.servlet.http 2개의 패키지가 서블릿 기술을 사용하기 위한 핵심적인 인터페이스와 클래스를 제공합니다. IDE에서 서블릿 클래스를 생성하시면, 자동으로 javax.servlet.http 패키지의 HttpServlet 클래스를 상속받는 것을 볼 수 있습니다. HttpServlet 클래스는 웹사이트를 구현하기 위해서 HTTP를 다룰 수 있는 메서드들을 오버라이딩할 수 있게 하는데요. 흔히 우리가 사용하는 doGet, doPost 같은 메서드들입니다. 이러한 패키지를 통해서 서블릿이 단순 클래스이지만 HTTP 프로토콜의 요청을 받고, 응답할 수 있는 기능을 할 수 있습니다. 

 

4. Servlet Class Hierarchy

위에서 언급한 HttpServlet는 어떻게 작동을 하는 것일까요? 분명한 건 프로그래밍을 함에 있어서 아무런 기능을 구현하지 않았는데도, 자동으로 동작하는 것은 없습니다. 

 

먼저 아래의 그림을 보겠습니다.

 

서블릿 계층

 

서블릿 기술을 구현하는 javax.servlet 패키지에는 뿌리에 해당하는 Servlet 인터페이스가 있습니다. GenericServlet 클래스는 Servlet 인터페이스를 구현하고 있으며, 동시에 ServletConfig 인터페이스도 구현하고 있습니다. 서블릿 컨테이너가 서블릿들을 초기화하는 동안 정보를 넘겨주는 역할을 합니다.  그리고 마지막으로 MyServlet, 즉 우리가 작성한 서블릿 클래스가 HttpServlet 클래스를 상속하는 구조입니다.  당연히 MyServlet의 이름은 사용자가 자유롭게 지을 수 있습니다. 정해진 이름이 아닙니다.

 

4. 1. Servlet Interface

앞에서 언급드렸듯이 Servlet 인터페이스는 javax.servlet 패키지의 뿌리에 해당합니다. 이 인터페이스는 Servlet Engine안에 Load(적재) 되고 Run 합니다. 이때 Servlet Engine은 Tomcat과 같은 웹 서버를 뜻 합니다. Servlet 인터페이스는 서블릿 컨테이너에 의해서 호출됩니다. 아마도 스프링 프레임워크를 배우신 분들이라면 익숙한 개념일 것 입니다. 스프링 컨테이너가 여러 빈들을 관리하는 것과 같습니다. 그렇기 때문에 지금의 서블릿에 대한 개념을 명확히 해둔다면, 스프링 프레임워크를 배울 때도 조금 더 익숙하게 배울 수 있습니다.

 

Servlet 인터페이스에는 서블릿 컨테이너에 의해서 call 되는 중요한 메서드들이 있는데요. init(), service(), destroy()입니다. 이러한 3개의 메서드들을 묶어서 Servlet life-cycle(생명주기)이라고 합니다. 즉 서블릿이 생기고, 일하고, 없어지는 과정을 메서드로 나타내 놓은 것입니다. 사람도 태어나고, 일하고, 죽는 생명주기가 있습니다. 조금은 슬픕니다.

 

어쨌든 위에서도 언급했지만, 프로그래밍에서 아무것도 없는데 저절로 생기고, 작동하는 것은 없습니다. 모든 기능은 메서드에 의해서 작동하는데요. 

 

 

 

+) 아래의 모든 과정은 서블릿 컨테이너에 의해서 필요한 동적 콘텐츠를 제공하기 위한, 서블릿이 요청되었다는 가정을 하고 있습니다. 그리고 이 서블릿 클래스는 이미 적재되어 인스턴스화 된 상태입니다. 

 

4. 1. 1. init()

서블릿이 처음으로 요청될 때 초기화를 합니다. 자바에서 변수를 초기화하는 것과 같습니다. 우리가 작성한 각 서블릿 클래스도 초기화를 해야 사용할 수 있습니다. 서블릿 컨테이너에 의해서 호출되며, 사용하기 위한 준비과정입니다. 

 

하지만 여기서 알아야 할 것은, 서블릿 클래스는 처음 요청될 때 초기화가 되고 나면, 다시 한번 해당 서블릿 클래스를 호출해도 초기화가 되지 않습니다. 단순히 자바 코드를 생각하시면 됩니다. 이미 초기화한 변수를 또 초기화할 필요는 없으니까요. 

 

4. 1. 2. service()

서브릿 컨테이너가 Request(요청)을 받고 Response(응답)에 필요한 서블릿의 service 메서드를 호출합니다. 여기서 service 메서드는 보통 그 자체를 사용하는 것이 아닌, Servlet interface를 구현한 HttpServlet 클래스의 doGet, doPost 같은 메서드를 사용합니다. 

 

당연하지만 service() 메서드는 서블릿 클래스가 init() 메서드가 실행되어 초기화된 후에 호출됩니다. 절대로 그전에 호출될 수 없습니다.

 

또한 기본적으로 서블릿 컨테이너는 멀티스레드 환경이며, 동시에 여러 요청들을 받을 수 있습니다. 즉 여러 service()가 실행될 수 있습니다. 그렇기 때문에 모든 멀티스레드 환경과 마찬가지로 동기화 문제에 신경을 써야 합니다. 

 

4. 1. 3. destroy()

더 이상 사용되지 않는 서블릿 클래스는 서블릿 컨테이너가 destroy() 메서드를 호출합니다. 여기서 사용되지 않는 것이라는 의미는 해당 서블릿 클래스의 service 메서드들에 해당하는 모든 스레드들이 종료되거나, 사용시간을 넘어서서 타임아웃되는 경우입니다. 즉 이 클래스를 다시 사용하기 위해서는 다시 init() 과정을 거쳐야 합니다.

 

destroy() 메서드 덕분에 사용하지 않는 서블릿 클래스를 제거 함으로써, 메모리와 같은 자원의 효율성을 가져올 수 있습니다. 

 

5. 수정사항

9월 17일 

전체적인 내용 추가 밑 수정

 

6. 참고자료

docs.oracle.com/javaee/6/api/javax/servlet/Servlet.html#destroy()

docs.oracle.com/javaee/5/tutorial/doc/bnafi.html#bnafm

beginnersbook.com/2013/05/servlet-class-hierarchy/

'Java > Java 이론' 카테고리의 다른 글

서블릿이란?  (0) 2020.09.15
[Gradle] Gradle이란?  (0) 2020.08.05
[Spring Framework] IoC container / Scope  (0) 2020.07.27
웹 서버란?  (0) 2020.07.04
Firefox Java Coding Style  (0) 2020.06.13
[Java]왜 JVM이 필요할까?  (8) 2020.06.06