본문 바로가기
Back-end/Spring Boot

[SpringBoot] 스프링부트 이해하기- 1편 Servlet이란(feat. Web Container)

by whatamigonnabe 2022. 7. 12.

최근 스프링부트 인강을 듣고 학원에서 나눠준 템플릿 위에 간단한 CRUD 게시판을 만들어보았는데, 스프링부트의 여러 설정파일이나 이 간단한 어플리케이션이 어떻게 동작하는지 전혀 모르는 것 같아서, 한번 이해해보고자 스프링부트 관련 개념들을 정리해보자한다. 누군가 프로그래밍을 배우는 과정은 눈감고 코끼리를 더듬거리며 코끼리를 알아가는 거랬는데, 엄청 와닿는 것 같다.

 

각설하고, 스프링부트는 우선 서버 개발을 편하게 해주는 프레임워크이기 때문에, 서버가 어떻게 동작하는지를 알아야할 것 같다. 그래서 우선 대망의 1편은 서블릿(Servlet)이다. 

 

서블릿(Servlet)이란?

사실 개념이 잘 그려지지 않아서 여러 자료를 둘러본 후 스스로 내린 정의는

서블릿은 동적 웹 페이지(Dynamic web page)를 위하여, HttpRequest를 받아 처리하여 웹 페이지를 동적으로 생성하여 HttpResponse로 반환하는 자바 클래스이다.

 

이 정의를 이해하기 위해서는, 우선 동적 웹 페이지를 정적 웹 페이지에 비교해서 이해할 필요가 있다.

동적 웹 페이지 vs 정적 웹 페이지

우선 정적 웹 페이지는 말 처럼 누구나 동일한 Response를 받는 것을 말한다. 예를 들면, 어떤 한 디자이너가 만든 포트폴리오 사이트 정도가 될 것 같다. 누가 그 웹페이지에 요청하든 같은 결과를 받는다. 반면, 동적 웹 페이지는 클라언트마다 다른 결과를 받는다. 예를 들면, 인스타그램, 유튜브, 네이버, 등 거의 모든 웹페이지가 될 것이다. 사용자에 따라, 또는 검색어에 따라, 접속한 지역에 따라 다른 결과를 받는다. 그렇다면 어떻게 이런 게 가능할까?

디자이너의 포트폴리오 사이트 https://solana.com/summercamp

웹 서버와 WAS(Web Application Server) (feat. web application container)

정적 웹 페이지의 경우 클라이언트가 http에 맞게 url로 요청하면, 웹서버가 정적 컨텐츠(html, css 등)을 http 형태로 리턴하고, 크롬과 같은 브라우저가 해석해서 우리가 보기 좋은 형태로 보여준다. 하지만 이때 클라이언트의 요청에 맞는 응답(예를 들면 검색)을 할 수가 없다. 그래서 등장한 것이 WAS(Web Application Server)이다. WAS는 웹 서버에 웹 어플리케이션 컨테이너를 더한 것이다. 웹 서버가 클라이언트의 요청을 보고 정적 요청인지 동적 요청인지 파악하여, 만약 동적 요청이라면 웹 어플리케이션 컨테이너로 그 처리를 위임한다. 웹 컨테이너는 요청에 맞게 처리를 하고 html에 조립(?)하여 리턴한다. (추가 적으로 웹서버와 웹어플리케이션컨테이너를 나누는 이유는 자원 이용의 효율성 및 장애 극복, 배포 및 유지보수의 편의성이라고 한다.) 그렇다면, WAS는 어떻게 동적 페이지를 리턴할 수 있을까? 이때 나오는 것이 서블릿이다.

서블릿과 Web Container

처음에 언급한 것처럼 블릿은 동적 웹 페이지(Dynamic web page)를 위하여, HttpRequest를 받아 처리하여 웹 페이지를 동적으로 생성하여 HttpResponse로 반환하는 자바 클래스이다. 위에서 '처리'라는 부분이 동적 페이지를 위해 비즈니스 로직을 처리하는 것이다. 그런데 객체지향을 위해 서블릿은 하나의 기능만 수행하기에 여러 서블릿 클래스가 있고, 클라이언트로부터의 요청은 다양하지만 하나의 http 요청으로 들어온다. 어떻게 클라이언트가 원하는 서블릿을 찾아서 실행시킬 수 있을까?

이때 웹 컨테이너가 등장한다. 웹 컨테이너는 웹 서버로부터 위임받은 요청을 보고 어떤 서블릿을 사용할지 결정하는데, 이때 web.xml설정파일을 이용한다. 아래와 같이 미리 어떤 사용자의 url에 어떤 서블릿을 호출할지 정의해놓고, 웹 컨테이너가 해당 서블릿 생성한다.

<!--web.xml-->
<web-app>
    <display-name>Web Application</display-name>

    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>me.doflamingo.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>

출처: https://doflamingo.tistory.com/45

 

웹 컨테이너가 하는 일은 이외에도 여러가지가 더 있다.

1. 서블릿 생명주기 관리

대부분 서블릿은 싱글톤으로 관리되기 때문에, 요청이 들어오면 서블릿 인스턴스가 있는지 확인한 후 있으면 그것을, 없으면 인스턴스를 만들어준다. 또한 수명이 다한 서블릿을 가비지 컬랙터를 통해 해제 시켜 자원 낭비를 막는다.

2. 멀티 쓰레드 지원

정확히는 컨테이너가 직접 서블릿을 컨트롤하지 않고, 요청이 올 때마다 쓰레드를 생성해서 쓰레드가 서블릿의 메서드를 호출한다. 

3. 선언적인 보안곤리

정확히 이해는 못했지만, 따로 보안 소스를 자바 클래스 내에 구현하지 않고, xml에 기록해놓는다고 한다. 

 

 

마지막으로 서블릿이 동작하는 과정을 설명한 부분이 있어 인용해본다.

2. Web Server는 클라이언트의 요청(Request)을 WAS에 보낸다.
3. WAS는 관련된 Servlet을 메모리에 올린다.
4. WAS는 web.xml을 참조하여 해당 Servlet에 대한 Thread를 생성한다. (Thread Pool 이용)
5. HttpServletRequest와 HttpServletResponse 객체를 생성하여 Servlet에 전달한다.
5-1. Thread는 Servlet의 service() 메서드를 호출한다.
5-2. service() 메서드는 요청에 맞게 doGet() 또는 doPost() 메서드를 호출한다.
5-3. protected doGet(HttpServletRequest request, HttpServletResponse response)
6. doGet() 또는 doPost() 메서드는 인자에 맞게 생성된 적절한 동적 페이지를 Response 객체에 담아 WAS에 전달한다.
7. WAS는 Response 객체를 HttpResponse 형태로 바꾸어 Web Server에 전달한다.
8. 생성된 Thread를 종료하고, HttpServletRequest와 HttpServletResponse 객체를 제거한다.

https://velog.io/@falling_star3/web-Web-Server%EC%99%80-WASWeb-Application-Server