웹 서버(Web Server)는 HTTP(Hypertext Transfer Protocol) 또는 다른 규약을 사용하여 클라이언트에게 정적인 컨텐츠(단순 HTML문서와 같은 즉시 제공가능한 것)를 제공하는 소프트웨어와 하드웨어를 의미합니다. 정적인 컨텐츠들은 즉각적으로 답할 수 있는 컨텐츠로 단순 HTML, CSS 등이 있습니다.
웹 서버의 예시로는 Apache, Windows IIS, NGINX 등이 있습니다.
하지만, 웹이 확장됨에 따라 데이터를 저장하고 저장된 데이터를 다시 불러오는 등 화면을 사용자에 따라 능동적으로 변화가 되는, 일명 동적인 컨텐츠들이 필요해졌습니다. 이를 위해 필요한 것이 WAS 입니다.
우선, 웹 애플리케이션(Web Application), 줄여서 웹 앱은 인터넷을 통해 웹 브라우저에서 이용할 수 있는 응용프로그램입니다. 웹 앱과 서버 환경을 만들어서 동작시키는 기능을 제공하는 소프트웨어 프레임워크가 바로 웹 애플리케이션 서버(Web Application Server, WAS)라 합니다.
이 WAS의 경우 사용자가 요청한 서비스의 결과를 스크립트 언어 등으로 가공하여 생성된 동적인 콘텐츠들을 제공하기에 일반 웹 서버와는 구별이 되고, 주로 DB 서버와 같이 수행됩니다. 대표적인 WAS로는 Tomcat이 있습니다.
Java에서 WAS는 JSP, Servlet 구동 환경을 제공해줍니다.
Servlet은 클라이언트의 요청을 처리하고 그 결과를 다시 클라이언트에게 전송하는 자바 프로그래밍 기술입니다. 이는 javax.servlet
패키지에 정의가 되어 있으며 아래와 같은 세가지 메소드를 정의합니다.
- init()
- service()
- destory()
서블릿의 생명 주기 중 초기화 단계에 호출되는 메소드입니다. 이 때 javax.servlet.ServletConfig 인터페이스를 구현하는 오브젝트가 전달됩니다. 이를 통해서 서블릿이 웹 앱에서 초기화 매개변수에 접근할 수 있도록 합니다.
초기화 이후 각각의 요청들이 들어오면 호출되고, 각각의 요청들은 별도로 나누어진 쓰레드에서 처리됩니다. 웹 컨테이너는 이러한 모든 요청에 대해서 이 service()메소드를 요청하고 이 메소드는 요청 종류를 판별하고 요청을 처리할 적절한 메소드로 전달합니다.
서블릿이 가지고 있는 자원을 풀어주는 역할을 하고, JVM에 의해 서블릿은 Garbage Collection 됩니다.
웹 컨테이너는 서블릿과 상호작용하는 WAS의 구성요소로 서블릿 컨테이너라 불리기도 합니다.
이 때 서블릿은 요구사항 명세서라고 표현한다면, 서블릿 컨테이너는 그 명세서를 보고 개발하는 개발자로 비유할 수 있습니다. 이렇듯 서블릿 컨테이너는 서블릿들을 위한 상자(Container)로 서블릿들의 생성, 실행, 파괴를 담당합니다.
크게 서블릿 컨테이너의 역할은 아래와 같습니다.
- 웹 서버와의 통신 지원
- 서블릿 생명주기 관리
- 멀티쓰레드 지원 및 관리
- 요청을 받을 때 쓰레드가 생성이 되어 원래는 각 쓰레드의 안정성 관리가 필수적이지만, 서버가 알아서 처리해줍니다.
- 선언적인 보안 관리
- 보안에 관련된 내용을 서블릿이나 자바 클래스에 구현해 놓지 않아도 되어 보안 변경 사항을 수정하더라도 자바 소스 코드를 수정하지 않아도 됩니다.
동작 과정은 아래와 같습니다.
- 웹서버가 HTTP 요청을 받음
- 웹서버는 요청을 서블릿 컨테이너로 전달
- 서블릿이 컨테이너에 없다면, 서블릿을 동적으로 검색하여 컨테이너의 주소 공간에 로드
- 컨테이너가 서블릿의
init()
메소드를 호출하면, 서블릿이 초기화 : 서블릿이 처음 로드됐을 때 한번만 호출- 컨테이너가 서블릿의
service()
메소드를 호출하여 HTTP 요청을 처리- 웹서버는 동적으로 생성된 결과를 올바른 위치에 반환한다.
클라이언트가 요청을 주고 서버, DB를 거쳐 응답을 받은 과정을 그림으로 나타내면 아래와 같습니다.
이 과정을 설명하면 아래와 같습니다.
- 웹 서버로부터 요청이 오면 컨테이너가 받아서 처리
- 컨테이너는 web.xml을 참조, 해당 서블릿에 대한 쓰레드를 생성하고
HttpServletRequest
,HttpServletResponse
객체를 생성하여 전달- 컨테이너의 서블릿 호출
- 쓰레드에서는
doGet()
이나doPost()
를 호출- 동적인 페이지를
Response
객체에 담아서 컨테이너에 전달, 이를HttpResponse
형태로 바꾸어 Web Server에 전달- 생성된 쓰레드를 종료하고
HttpServletRequest
,HttpServletResponse
객체를 제거