🔖Servlet이란?
서블릿이란, 웹 프로그래밍에서 클라이언트의 요청을 처리하고, 처리 결과를 클라이언트에 전송하는 기술이다
Servlet은 WAS 내부에 위치하며, 동적인 페이지를 만들기 위해 WAS에 포함된 프로그램이다
이는 Java로 구현된 *CGI(Common Gateway Inteface)로, 쉽게 말하면 Java를 사용해서 웹을 만들기 위해 필요한 기술이다
💡 CGI
- 별도로 제작된 웹 서버와 프로그램간의 교환 방식
- 어떠한 프로그램이 언어로도 구현이 가능하며, 별도로 만들어 놓은 프로그램에 HTML의 GET/POST 방법으로 클라이언트의 데이터를 환경 변수로 전달하고 프로그램의 표준 출력 결과를 클라이언트에게 전송하는 것을 말한다
일반적으로 웹 서버는 정적인 페이지만 제공하는데, 동적인 페이지를 제공하기 위해 Servlet을 활용한다
'동적인 페이지'란 사용자의 요청에 의해 변화되는 무언가를 제공하는 페이지로, Servlet이 바로 이러한 동적인 페이지를 제공하기 위해 도움을 주는 어플리케이션이다
Servlet의 장점
- HTTP 요청을 하게 되면 위와 같은 결과를 보내주게 되는데, servlet을 사용하지 않는 경우 개발자가 위의 텍스트를 모두 작성해야 한다
- 그러나 Servlet을 사용하면 HTTP 요청에 대한 분석 및 응답을 알아서 수행하기 때문에, 복잡한 HTTP 요청 메소드를 분석할 필요가 없고 응답 메소드를 만들 필요도 없다
- 또한 HTTP 요청 정보를 쉽게 사용할 수 있기 때문에 개발자는 실제 처리 로직(비즈니스 로직)에만 집중할 수 있게 된다!
Servlet의 특징
- 클라이언트의 요청에 대해 동적으로 작동하는 웹 어플리케이션 컴포넌트
- HTML을 사용해서 요청에 응답한다
- Java Thread를 통해 동작한다
- MVC 패턴 중 Controller로 이용된다
- HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속받는다
- UDP보다 속도가 느리다
- HTML 변경 시 Servlet을 재 컴파일 해야 한다
Servlet의 동작 과정
- 사용자가 URL을 클릭하면 HTTP Request를 서블릿 컨테이너로 전송한다
- HTTP Request를 전달받은 서블릿 컨테이너는 HttpServletRequest, HttpServletResponse 두 객체를 생성한다
- web.xml은 사용자가 요청한 URL을 분석하여 어느 서블릿에 대한 요청을 한 것인지 찾는다
- 해당 서블릿에서 service 메소드를 호출한 후 클라이언트의 요청 종류(GET/POST)에 따라 doGet 혹은 doPost를 호출한다 -> HTTP 메소드에 따라서 doXXX 메소드 호출한다
- doGet, doPost 메소드는 동적 페이지를 생성한 후 HttpServletResponse 객체에 응답을 보낸다
- 응답이 끝나면 HttpServletRequest, HttpServletResponse 두 객체를 소멸시킨다
Servlet의 한계와 Servelet Container의 필요성
서블릿은 요청받은 작업을 수행하거나 정적인 페이지를 만들어서 웹서버로 전달한다
그러나 서블릿은 도움이 필요하다
요청이 들어오면 누군가 요청을 처리할 새로운 스레드를 만들어야 하고 서블릿에서 필요한 메서드를 호출해야 한다
또 파라미터로 받은 값을 넘겨주기도 해야 한다
이러한 역할을 해주는 것이 서블릿 컨테이너이다
웹 서버가 사용자로부터 서블릿에 대한 요청을 받으면 컨테이너에게 해당 요청을 넘긴다
요청을 넘겨받은 컨테이너는 서블릿을 찾아 필요한 메서드를 호출하게 된다
🧱 Servlet Container
서블릿 컨테이너는 서블릿의 생명주기를 관리해주는 컨테이너를 말한다
서블릿 컨테이너는 클라이언트의 요청을 받아주고 응답할 수 있도록 웹 서버와 소켓을 만들어 통신한다
즉, 서블릿 컨테이너는 개발자 대신 서블릿을 생성하여 필요한 순간에 호출하고 적절한 순간에 소멸시킨다
WAS가 바로 이러한 서블릿 컨테이너(웹 컨테이너)와 Web Server의 결합으로, 대표적인 예시로 톰캣(Tomcat)이 있다
컨테이너는 사용자로부터 요청을 받을 때마다 요청을 처리할 스레드를 생성한다
그리고 그 스레드에서 필요한 서블릿 메서드를 호출하게 된다
이 때 스레드는 무제한으로 생성하는 것이 아니라, 컨테이너 내부에 스레드풀(Thread pool)에 스레드를 저장하고 필요할 때마다 꺼내서 사용한다
💡 여기서 유의할 점은 요청이 올 떄마다 스레드를 새로 생성하거나 스레드풀에서 꺼내서 쓰는 것이지, 서블릿 인스턴스를 새로 생성하는 것은 아니다!
(서블릿 인스턴스는 싱글톤 패턴을 사용하기 때문에 최초 한번만 생성!)
Servlet Container의 역할
- 웹 서버와의 통신 지원
- 서블릿 컨테이너는 서블릿과 웹 서버가 쉽게 통신할 수 있게 해준다
- 소켓 기능들을 API로 제공하여 복잡한 과정을 생략하고, 개발자는 구현해야 할 비즈니스 로직에 대해서만 초점을 맞추면 된다
- 서블릿 생명주기 관리
- 서블릿 컨테이너는 서블릿의 탄생과 죽음을 관리한다
- 서블릿 클래스를 로딩하여 인스턴스화 하고, 초기화 메소드를 호출하고, 요청이 들어오면 적절한 서블릿 메소드를 호출한다
- 멀티쓰레드 지원 및 관리
- 서블릿 컨테이너는 요청이 올 때마다 새로운 자바 쓰레드를 하나 생성하는데, HTTP 서비스 메소드를 실행한 후 쓰레드는 자동으로 죽는다
- 이러한 관리를 컨테이너가 알아서 해준다
- 선언적인 보안 관리
- 보안 관리는 XML 배포 서술자에 기록하므로 보안적 문제로 인해 자바 소스를 수정할 일이 없다
Servlet의 생명주기
- 사용자(클라이언트)가 URL을 통해 요청을 보내면 HTTP Request를 Servlet Container로 전송한다
- HTTP Request를 전송받은 Servlet Container는 HttpServletRequest, HttpServletResponse 객체를 생성한다
- 서블릿 설정 파일에서 매핑한 서블릿을 확인한다
- 컨테이너는 해당 서블릿의 인스턴스가 메모리에 존재하는지 확인하고, 없을 경우 init() 메소드를 호출하여 생성한다
- init()은 최초 한번만 실행되기 때문에 서블릿의 쓰레드에서 공통적으로 사용해야 하는 것이 있다면 오버라이딩하여 구현한다
- init()이 호출된 후 클라이언트의 요청에 따라서 서블릿 컨테이너에 스레드를 생성하고, Servlet Request, Serlvet Response 객체를 인자로 사용하여 해당 서블릿에서 service를 호출하여 개발자가 정의한 비즈니스 처리 로직을 수행한다
- service에서 HTTP 요청에 대한 응답이 HTTP 메소드에 따라 분기되어 doGet(), doPost()와 같은 메서드를 호출한다
- 이 때 서블릿 컨테이너가 클라이언트의 요청이 오면 가장 먼저 처리하는 과정으로 생성된 HttpServletRequest, HttpServletResponse에 의해 request와 response 객체가 제공된다
- Servlet Response 객체에 응답을 보내고 HttpServletRequest, HttpServletResponse 객체를 소멸한다
- 컨테이너가 서블릿에 종료 요청을 하면 destroy() 메소드가 호출되는데, 한번만 실행되며 종료 시에 처리해야 하는 작업들은 destroy() 메소드를 오버라이딩하여 구현하면 된다
🚨 이 때 서블릿 인스턴스는 소멸되지 않는다!
- 서블릿 인스턴스는 싱글톤(Singleton) 패턴이기 때문에, 서블릿을 컨테이너에 담아두고 호출이 발생할 때마다 꺼내 사용한다
- 여기서 HttpServletRequest, HttpServletResponse 객체를 생성한 컨테이너는 요청에 알맞은 서블릿을 찾게 되는데, 이 서블릿을 찾기 위해서는 개발자가 서블릿을 매핑해줘야 한다
- 그렇지 않으면 적절한 서블릿을 찾을 수 있는 정보가 없기 때문에 컨테이너는 서블릿을 찾지 못하게 된다
- 서블릿 초기 표준에는 '배포 서술자'가 반드시 필요했지만, servlet 3.0부터는 Annotationㅇ르 지원하기 때문에 쉽게 서블릿 매핑이 가능해졌다!
Q. 만약 한 번에 여러 요청이 들어오면 어떻게 될까?
- 이떄는 요청을 멀티 스레드를 통해 관리한다
- 요청이 들어올 때마다 서블릿을 정의하고, 요청 수행 시 매번 스레드를 생성한다
- 여러 스레드가 생성되고 스레드 당 다른 서블릿이 처리할 수도 있고, 여러 스레드에서 한 서블릿의 여러 요청을 동시에 처리할 수도 있을 것이다
- 그러나 이 때 스레드 생성 시마다 오버헤드가 발생하고, 다른 스레드로 전환할 때마다 발생하는 context switching 등의 문제가 야기될 수 있다
- 또한 스레드 생성에 제한을 두지 않으면, 많은 요청을 처리하기 위해 그만큼 많은 스레드를 생성하다가 서버의 하드웨어 한계를 넘어버리면 서버가 터질수도 있다
Servlet의 한계
- 요청당 서블릿을 정해주는 곳에는 비효율적인 부분이 존재한다
- 관리 측면에서는 멀티 스레딩을 다뤄야 한다는 어려움이 존재하고, 개발 측면에서는 핸들러의 공통 로직이 매번 중복된다
아래의 예시를 보자
위를 보면 1번과 3번의 과정이 중복되는데 이를 따로 뺴서 관리하는 것이 더욱 효율적일 것이다
이렇게 음료를 만드는 개별적인 부분만 별도로 빼서 관리한다
즉, 위와 같이 요청을 앞단에서 처리할 수 있는 일을 전담하는 매니저를 두는 것을 프론트 컨트롤러 패턴이라고 한다
스프링 MVC도 프론트 컨트롤러 패턴을 따르고, 모든 요청을 받는 전면 컨트롤러 서블릿을 Dispatcher Servlet이라고 부른다
서블릿은 하나만 두고 모든 요청을 다 받을 수 있도록 한다
(이는 [Dispatcher Servlet] 토픽에서 자세하게 정리하도록 하겠다!)
Dispatcher Servlet
- Dispathcer Serlvet 하나로 모든 요청을 수행한다
- 요청이 들어오면 서블릿 컨테이너의 제일 앞에서 모든 요청을 받아 적절한 하위 서블릿으로 작업을 위임한다
- Dispatcher Servlet은 Spring에서 웹 요청을 처리할 때 사용한다
- 개발자는 컨트롤러(Handler)에만 집중하면 된다
- 나머지 요청 처리 핸들러 검색, 핸들러 호출, 뷰 검색 또는 생성하는 기능은 IoC 컨테이너로부터 주입을 받아 사용하고 동작한다
Spring MVC에서의 웹 요청 처리 흐름
- 클라이언트로부터 들어오늘 모든 요청을 Dispatcher Servlet이 받는다
- Dispathcer Servlet은 Handler Mapping을 통해 요청을 처리할 Controller를 검색한다
- Dispathcer Servlet은 검색된 Controller를 실행하여 클라이언트의 요청을 처리한다
- Controller는 비즈니스 로직의 수행 결과로 얻어낸 Model 정보와 Model을 보여줄 View 정보를 ModelAndView 객체에 저장하여 리턴한다.
- Dispatcher Servlet은 전달받은 View이름과 매칭되는 실제 View를 찾기 위해 ViewResolver에게 요청하고ViewResolver는 결과를 보여줄 View를 찾아서 Dispatcher Servlet에게 전달한다.
- Dispatcher Servlet은 ViewResolver를 통해 찾아낸 View를 실행하여 사용자에게 응답을 전송한다.
JSP(Java Server Page)
서블릿이 자바 소스코드 속에 HTML이 들어가는 형태라면, JSP는 JAVA 코드가 들어있는 HTML 코드이다
이렇게 작성도니 HTML 코드는 브라우저로 전송되는 것이 아닌, 웹 서버 내에서 실행되는 부분이다
이는 프로그래머의 개발 효율성을 위해 등장한 것으로, 실질적으로 컨테이너에 의해 (WAS) 서블릿으로 변환되어 사용된다
JSP의 동작 방식
- 웹 서버가 사용자의 요청을 받으면 서블릿 컨테이너의 그 요청을 넘긴다
- 서블릿 컨테이너는 이를 Servlet 객체로 변환하고, 기존 서블릿 처리를 진행하듯이 동작 결과를 웹 브라우저로 응답하는 일련의 과정을 거친다
💡결론
Spring Servlet을 사용함으로써 웹 요청을 처리하는데, 개발자는 요청을 처리하는 로직에만 집중할 수 있다!
참고)
[Spring] Servlet이란?
[Spring] Servlet이란? 1. Servlet Spring 공부를 하기위해서는 서블릿의 이해가 필수적이다. http 통신 기반의 클래스(대부분의 컨트롤러가 이에 해당된다.)를 살펴보면 어노테이션 기반으로든, 매개변수
kohen.tistory.com
https://www.youtube.com/watch?v=calGCwG_B4Y&t=84s
https://webfirewood.tistory.com/38
서블릿(Servlet)의 동작구조
웹 서버의 주된 기능은 웹 페이지를 클라이언트로 전달하는 것입니다. 주로 그림, CSS, 자바스크립트를 포함한 HTML 문서가 클라이언트로 전달됩니다. 하지만 이런 웹 서버의 경우 이미 존재하는
webfirewood.tistory.com
'야미스터디 > Spring' 카테고리의 다른 글
[Spring] bean vs component 📌 (0) | 2022.09.08 |
---|---|
[Spring] maven vs gradle 📌 (0) | 2022.08.18 |
[Spring] Spring vs Spring Boot 📌 (0) | 2022.08.02 |
[Spring Boot] Gradle 버전과 OAuth2.0 구현 관련 (0) | 2022.04.12 |
3강 메세지 컨버터가 무엇인가요? (0) | 2022.01.10 |
댓글