[CS - 자바] 서블릿(Servlet)

Seongho·2023년 10월 26일
1

CS - 자바

목록 보기
4/6

intro..

스프링 부트로 프로젝트를 하던 중, 스프링 시큐리티 설정에서 커스텀 필터를 추가하는데, 스프링 디스패쳐 서블릿을 너무 많이 만나서,,, 근데 또 서블릿이 뭔지 정확히 모르는 상태라 한번 공부해보았다.

서블릿 이전

서블릿이 등장하기 이전에는 클라이언트가 웹 서버에 요청을 보내면, 웹 서버는 정적인 페이지(HTML, CSS, image..)를 응답으로 줄 수 있었다. 그러니까, 사용자마다 다른 화면을 제공할 수 없었던 것이다. 점점.. 동적인 페이지에 대한 필요성이 증가했고, 이를 해결하기 위해 서블릿이 등장하였다.

만약, 위와 같은 Http 요청 메세지를 개발자가 직접 문자열 파싱하여 개발을 한다면 어떻게 될까..
개발자는 서비스 로직이 집중하지 못하고 요청 메세지 파싱하는 것에 시간을 다 보내게 될 것이다.

서블릿이란?

"서블릿은 웹 페이지를 동적으로 생성하는 서버 측 프로그램이다." - 위키백과
서블릿은 WAS의 서블릿 컨테이너(웹 컨테이너)에 의해 생성되고 관리된다.
** 대표적인 서블릿 컨테이너로 톰캣이 있다.

서블릿 관련된 동작 (알기 쉽게)


클라이언트에서 웹 애플리케이션 서버에 /hello라는 요청을 보낸다. 그러면 웹 서버는 해당 Http 요청을 받아 서블릿 컨테이너에 전송하면, 미리 xml 파일에 등록된 대로 HelloServlet이 동작하도록 한다.

뭉뚱그려 말하자면, 컨트롤러 역할을 한다고 봐도 될 것 같다.
서블릿 객체는 싱글톤으로 관리되는데, 웹 컨테이너가 HTTP 요청을 받으면 서블릿 객체를 공유하는 스레드를 요청마다 생성한다.

interface Servlet

  • init() : 서블릿을 초기화하는 매서드로, 서블릿이 처음 생성될 때 호출된다. ServletConfig 설정 정보에 따라 서블릿 객체를 생성한다.
  • service() : 클라이언트 요청을 처리하는 매서드이다. 서블릿의 메인 기능이다.
  • destroy() : 서블릿 객체가 소멸될 때 호출된다. 리소스 해제 등의 작업을 수행한다.

abstract class GenericServlet

service() 매서드를 제외한 모든 매서드를 구현한 추상클래스이다. GenericServlet class를 상속받은 클래스는 프로토콜에 따라 매서드를 재정의한다. 그 중, HttpServlet이 Http 프로토콜에 따라 GenericServlet을 재정의한다.

abstract class HttpServlet

GenericServlet 추상 클래스를 상속받은 추상 클래스로, HTTP 프로토콜을 기반으로 동작하는 서블릿을 구현한다. service() 매서드를 구현한다.

위 코드는 HttpServlet class의 service() 매서드이다.
http 요청 메세지에서 get, post, put 등 요청 헤더 매서드에 따라 doGet(), doPost(), doPut(), doDelete() 등의 동작을 처리함을 알 수 있다.

HelloServlet class


위와 같이 비지니스 로직에 맞는 세부 동작을 구현한다.

서블릿 컨테이너의 동작

  1. 클라이언트에서 WAS에 /hello 라는 Http 요청이 들어오면,
  2. 웹 서버는 서블릿 컨테이너로 요청을 전달한다.
  3. 서블릿 컨테이너는 web.xml의 매핑 정보에 따라 매핑된 서블릿을 찾는다.
    3-1. 만약, 해당 요청이 최초라면, 서블릿 인스턴스를 생성한다.
    3-2. 만약, 해당 요청이 이전에 들어왔던 요청이라면, 이전에 생성된 서블릿 인스턴스를 사용한다.
  4. init() 매서드를 이용해 서블릿 인스턴스를 초기화한다.
  5. HttpServletRequest 인스턴스와 HttpServletRequest 인스턴스를 생성하여 서블릿 인스턴스에 주입한다.
  6. 서블릿 인스턴스의 service()를 요출하여 doGet, doPost와 같은 매서드를 처리한다.
  7. 로직이 끝나면, 서블릿 컨테이너에서 클라이언트로 직접 HttpSerlvetResponse 인스턴스를 전송한다.
  8. HttpServletRequest, HttpServletRequest 인스턴스를 소멸시킨다.

서블릿 인스턴스는 소멸 안시킴?

서블릿 인스턴스는 한번 생성되면 프로젝트가 종료될 때까지 소멸되지 않고, 싱글톤으로 관리된다.
여러 클라이언트로부터 동시에 요청이 올 때, 서블릿 컨테이너는 요청마다 스레드를 생성하는데, 서블릿 인스턴스 하나를 여러 스레드가 공유할 수도 있고, 한 서블릿마다 한 스레드가 생성될 수도 있다.
예를 들어, /hello 요청이 A, B 컴퓨터에서 하나씩, /hi 요청이 C 컴퓨터에서 하나. 이렇게 요청이 동시에 들어오면, 두 개의 스레드가 HelloServlet 인스턴스를 공유하고, 한 개의 스레드가 HiServlet 인스턴스를 공유한다.

단점

이렇게 자바에서 요청당 서블릿을 직접 매핑해 주는 방식에는 비효율적인 부분이 있다.
만약, 동시에 10000번의 같은 요청이 들어온다면, 10000개의 스레드가 한 인스턴스를 공유하는 일이 생긴다.
서버를 다운시킬 수 있는 위험이 있다.
또한, 핸들러의 공통 로직이 중복된다는 문제가 있다. 모든 서블릿에 Http 헤더에서 method를 뽑아내고, HttpServletRequest를 만들고.. 이런 로직이 중복된다.
보통 이렇게 비유한다.
이렇게 해결하면 좋지 않을까?

스프링에서는 위와 같이 프론트 컨트롤러 패턴을 적용하여, 스프링 디스패쳐 서블릿이 모든 요청을 수행한다.

스프링 디스패쳐 서블릿에 대해서는 다음에...

참고
서블릿 : https://www.youtube.com/watch?v=calGCwG_B4Y&t=624s
웹 서버 vs WAS : https://www.youtube.com/watch?v=NyhbNtOq0Bc&t=1s
https://zuyo.tistory.com/803
https://kgvovc.tistory.com/26
https://www.inflearn.com/questions/505167/%EC%84%9C%EB%B8%94%EB%A6%BF-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-was%EA%B0%80-%ED%97%B7%EA%B0%88%EB%A6%BD%EB%8B%88%EB%8B%A4
https://velog.io/@yoho98/%EC%84%9C%EB%B8%94%EB%A6%BFServlet%EA%B3%BC-%EC%84%9C%EB%B8%94%EB%A6%BF-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88Servlet-Container-y88kny7g#%EC%84%9C%EB%B8%94%EB%A6%BF-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88servlet-container

profile
Record What I Learned

0개의 댓글