Servlet과 Spring Dispatcher

jonghyun.log·2023년 2월 6일
0

spring

목록 보기
4/7

스프링 개발을 하다보면 ServletSpring Web MVC Dispatcher 라는 용어를 접하게 되는데 이에 대해 공부한 내용을 정리해 보고자 한다.

Servlet 이란?

Servlet 웹 애플리케이션을 만들 때 필요한 인터페이스이다. 하지만 이렇게만 설명하면 Servlet 이 무엇인지 와닿지가 않을 것이다. 이를 이해하기 위해서 우선 웹 프로그래밍의 역사부터 간단한게 알아야한다.

옛날의 웹 페이지는 지금과 같이 사용자의 클릭에 반응해서 다른 움직임을 보여주거나 혹은 화면이 변하는 등의
정적 페이지가 아닌 그냥 html 문서 자체를 보여주는 정적 페이지만 존재했다.
(정적페이지의 예시로 위키백과 같은 단순 문서 페이지를 생각하면 된다. )

그래서 정적 페이지에서는 어떠한 사용자가 접속을 하여도 매번 똑같은 페이지만 보여주는게 가능했다.
하지만, 시간이 흐름에 따라 유저에 따라 다르게 응답을 하는등의 동적인 처리를 해주어야 하는 요구가 대두되었고 이에 맞춰 기술의 발전으로 CGI 라는 것이 개발되게 된다.

CGI?

CGI 란 (Common Gateway Interface) 의 줄임말로 ApacheNginx 같은
웹 서버 프로그램이 클라이언트로 부터 요청을 받아오면 그 요청을 받아서 동적으로 처리를 가능하게 해준다.
(WEB Server는 정적 페이지만 응답이 가능하다.)

인터페이스라는 단어에서 유추할 수 있듯 위 이미지에서의 CGI 들은 CGI 구현체로 C, PHP, PERL 등 다양한 언어로 존재한다.

CGI의 문제점

하지만 CGI 도 문제점이 두가지 존재하였는데

CGI의 1번째 문제

CGI웹 서버로 부터 request 가 들어올때마다 process를 새로 할당해서 처리한다 하지만
process 는 할당된 메모리를 모두 사용하고 만드는데 시간도 많이 소요되는 작업이기 때문에 대용량 요청에 대응 할 수 없다는 문제점이 존재하였다.

이를 해결하기 위해 프로세스 대신,
한 프로세스 내에서 메모리를 공유하고 만드는데 비교적 시간이 적게 드는 thread 를 사용해서 요청을 처리하게 되었다.

CGI의 두번째 문제

또한, thread 마다 CGI 구현체가 일대일로 생성이 되어 불필요한 메모리 낭비가 일어난다는 단점이 존재하였다. 이를 해결하기 위해서 다발적으로 생성되던 CGI 구현체를 Singleton Pattern 을 이용하여 단 한개만 생성되도록 변화시킨 것이 Servlet 이다.

WAS와 Servlet 의 등장

위에서 CGI 구현체들을 한개만 생성하도록 변경시킨것이 Servlet 이라고 했는데 정확히는 갑자기 Servlet 튀어 나온 것이 아니라 WAS(WEB Application Server)의 등장으로 탄생한 개념이다.

WAS(WEB Application Server) 는 동적 데이터 처리를 위해 탄생한 서버로
WAS 내의 Web container 에서 Thread 를 생성하고 Servlet 을 실행시켜준다.

즉, Servlet 은 동적인 페이지를 만들기 위해 Web Server 에 붙여서 같이 사용하는 프로그램이다.

Spring에서 Servlet을 다루는 방법

위에서 Servlet이 동적인 동적인 페이지를 만드는데 필요한 프로그램이라는 것을 알았다.
하지만, 여기서 멈추지 않고 스프링에서 어떤식으로 서블릿을 다루는지에 대해 한번 중점적으로 알아보자.

만약 Http 요청을 개발자가 직접 처리해야 한다면?

위 사진은 웹 개발자라면 익숙한 HTTP 요청과 응답의 일부이다.
만약에 개발자들이 request로 들어온 정보를 직접 해석하고 파싱같은 처리를 해주고 아래 response와 같은 텍스트 형식의 응답을 만들어야 한다면? 개발이 매우 어려워질 것이다.

이런 과정을 처리할때 서블릿을 사용해서 위에서 언급한 요청과 응답의 데이터를 처리를 하게 된다.

HttpServletRequest 다루기

위에서 언급한 서블릿을 보다 편하게 다루기 위해 스프링에서는 이미 서블릿을 다루기 위한 인터페이스와 그 구현체를 정의해놓았는데 바로, HttpServletRequest 이다.

위 사진에서 보는거와 같이 HttpServletRequest에는 이미 http 요청 정보를 쉽게 사용하기 위한 여러 메서드들이 정의가 되어있다.

이를 이용하면 클라이언트로 부터 들어오는 요청에 대해 요청과 응답의 정보를 개발자가 관리 하지 않아도 되므로
개발자들이 비즈니스 로직에 집중할 수 있게 된다.

서블릿을 사용할 때는 추상 클래스인 HttpServlet을 상속받아서
init(), destory(), service() 메서드를 구현해서 사용하게 된다.

이름에서 유추해볼 수 있듯이, init()HttpServlet 객체가 생성될때 호춮되고
destory() 메서드는 객체가 사라질때 호출된다.

여기서 중요한 것은 바로 service() 메서드이다. 요 service() 메서드를 통해 개발자가 구현하고자 하는 여러 작업들을 커스텀해서 구현할 수 있기 때문이다.

사실 위 그림과 같이 간단하게 되어있지는 않으며 위 그림은 한눈에 이해를 돕기 위해 원래의 코드를 조금 수정한 것이다.

서비스 매세드를 까보면 위와 같이 각 메서드 별로 매핑이 가능하며 가령 GET HTTP 메서드로 들어온 요청에 대해 특정 작업을 하고 싶으면 doGet 메서드를 재정의해서 구현하고자 하는 로직을 작성해주면 된다.

서블릿 컨테이너

스프링은 이런 서블릿을 어떻게 관리할까?
바로, 서블릿을 담고 관리해주는 서블릿 컨테이너라는 것을 만들어서 서블릿을 관리한다.

  1. Servlet Request / Servlet Response 객체 생성
  2. 설정 파일을 참고하여 매핑할 Servlet을 확인
  3. 해당 서블릿 인스턴스 존재의 유무를 확인하여 없으면 생성(init)
  4. Servlet Container에 스레드를 생성하고, res, req를 인자로 service 실행
  5. 응답을 처리한 뒤 Request, Response 객체를 소멸

Dispatcher Servlet?

위에서 서블릿이란 무엇이고 스프링에서 어떤식으로 사용을 하는지에 대해 알아보았다.

요청의 데이터를 파싱하고 응답으로 보낼때 헤더에 일정한 형식으로 담아서 보내준다는 것을 HttpServlet이 대신해주고 우리는 서비스 로직만 구성하면 된다고 했는데

요청이 들어올때마다 서블릿 객체를 생성해서 사용한다면 불편할것 같지 않은가?

서비스 로직을 제외한 반복되는 작업을 하나로 묶어서 처리해주는 녀석이 있다면 더 효율적인 서버가 되지않을까?

이를 위해 고안한 것이 바로 Dispatcher Servlet 이다.

요청을 수행할때마다 매번 서블릿을 생성하지 않고 하나의 서블릿만 정의해서 모든 요청을 수행하게 되며
요 하나의 서블릿이 바로 Dispatcher Servlet 이다.

요청이 들어오면 위 그림과 같이 Dispatcher Servlet이 응답을 받고 Dispatcher Servlet을 보좌하는 여러 인터페이스 객체들과 메시지를 주고 받으면서 요청을 처리하게 된다.

참고한 자료

우아한 테크코스 유투브 - 타미

우아한 테크코스 유투브 - 코기

http://springmvc.egloos.com/v/504151

0개의 댓글